1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2019-2020 Realtek Corporation
3 */
4
5 #include "coex.h"
6 #include "debug.h"
7 #include "fw.h"
8 #include "mac.h"
9 #include "phy.h"
10 #include "ps.h"
11 #include "reg.h"
12
13 #define RTW89_COEX_VERSION 0x07000113
14 #define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/
15 #define BTC_E2G_LIMIT_DEF 80
16
17 enum btc_fbtc_tdma_template {
18 CXTD_OFF = 0x0,
19 CXTD_OFF_B2,
20 CXTD_OFF_EXT,
21 CXTD_FIX,
22 CXTD_PFIX,
23 CXTD_AUTO,
24 CXTD_PAUTO,
25 CXTD_AUTO2,
26 CXTD_PAUTO2,
27 CXTD_MAX,
28 };
29
30 enum btc_fbtc_tdma_type {
31 CXTDMA_OFF = 0x0,
32 CXTDMA_FIX = 0x1,
33 CXTDMA_AUTO = 0x2,
34 CXTDMA_AUTO2 = 0x3,
35 CXTDMA_MAX
36 };
37
38 enum btc_fbtc_tdma_rx_flow_ctrl {
39 CXFLC_OFF = 0x0,
40 CXFLC_NULLP = 0x1,
41 CXFLC_QOSNULL = 0x2,
42 CXFLC_CTS = 0x3,
43 CXFLC_MAX
44 };
45
46 enum btc_fbtc_tdma_wlan_tx_pause {
47 CXTPS_OFF = 0x0, /* no wl tx pause*/
48 CXTPS_ON = 0x1,
49 CXTPS_MAX
50 };
51
52 enum btc_mlme_state {
53 MLME_NO_LINK,
54 MLME_LINKING,
55 MLME_LINKED,
56 };
57
58 struct btc_fbtc_1slot {
59 u8 fver;
60 u8 sid; /* slot id */
61 struct rtw89_btc_fbtc_slot slot;
62 } __packed;
63
64 static const struct rtw89_btc_fbtc_tdma t_def[] = {
65 [CXTD_OFF] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
66 [CXTD_OFF_B2] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0},
67 [CXTD_OFF_EXT] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 2, 0, 0},
68 [CXTD_FIX] = { CXTDMA_FIX, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
69 [CXTD_PFIX] = { CXTDMA_FIX, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0},
70 [CXTD_AUTO] = { CXTDMA_AUTO, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
71 [CXTD_PAUTO] = { CXTDMA_AUTO, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0},
72 [CXTD_AUTO2] = {CXTDMA_AUTO2, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
73 [CXTD_PAUTO2] = {CXTDMA_AUTO2, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}
74 };
75
76 #define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \
77 { .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \
78 .cxtype = cpu_to_le16(__cxtype),}
79
80 static const struct rtw89_btc_fbtc_slot s_def[] = {
81 [CXST_OFF] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
82 [CXST_B2W] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_ISO),
83 [CXST_W1] = __DEF_FBTC_SLOT(70, 0xea5a5a5a, SLOT_ISO),
84 [CXST_W2] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO),
85 [CXST_W2B] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO),
86 [CXST_B1] = __DEF_FBTC_SLOT(250, 0xe5555555, SLOT_MIX),
87 [CXST_B2] = __DEF_FBTC_SLOT(7, 0xea5a5a5a, SLOT_MIX),
88 [CXST_B3] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX),
89 [CXST_B4] = __DEF_FBTC_SLOT(50, 0xe5555555, SLOT_MIX),
90 [CXST_LK] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_ISO),
91 [CXST_BLK] = __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX),
92 [CXST_E2G] = __DEF_FBTC_SLOT(0, 0xea5a5a5a, SLOT_MIX),
93 [CXST_E5G] = __DEF_FBTC_SLOT(0, 0xffffffff, SLOT_ISO),
94 [CXST_EBT] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX),
95 [CXST_ENULL] = __DEF_FBTC_SLOT(0, 0xaaaaaaaa, SLOT_ISO),
96 [CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX),
97 [CXST_W1FDD] = __DEF_FBTC_SLOT(50, 0xffffffff, SLOT_ISO),
98 [CXST_B1FDD] = __DEF_FBTC_SLOT(50, 0xffffdfff, SLOT_ISO),
99 };
100
101 static const u32 cxtbl[] = {
102 0xffffffff, /* 0 */
103 0xaaaaaaaa, /* 1 */
104 0xe5555555, /* 2 */
105 0xee555555, /* 3 */
106 0xd5555555, /* 4 */
107 0x5a5a5a5a, /* 5 */
108 0xfa5a5a5a, /* 6 */
109 0xda5a5a5a, /* 7 */
110 0xea5a5a5a, /* 8 */
111 0x6a5a5aaa, /* 9 */
112 0x6a5a6a5a, /* 10 */
113 0x6a5a6aaa, /* 11 */
114 0x6afa5afa, /* 12 */
115 0xaaaa5aaa, /* 13 */
116 0xaaffffaa, /* 14 */
117 0xaa5555aa, /* 15 */
118 0xfafafafa, /* 16 */
119 0xffffddff, /* 17 */
120 0xdaffdaff, /* 18 */
121 0xfafadafa, /* 19 */
122 0xea6a6a6a, /* 20 */
123 0xea55556a, /* 21 */
124 0xaafafafa, /* 22 */
125 0xfafaaafa, /* 23 */
126 0xfafffaff, /* 24 */
127 0xea6a5a5a, /* 25 */
128 0xfaff5aff, /* 26 */
129 0xffffdfff, /* 27 */
130 0xe6555555, /* 28 */
131 };
132
133 static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
134 /* firmware version must be in decreasing order for each chip */
135 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 90, 0),
136 .fcxbtcrpt = 7, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
137 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
138 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
139 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
140 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
141 .max_role_num = 6,
142 },
143 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0),
144 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
145 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
146 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
147 .fwlrole = 8, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
148 .fwevntrptl = 1, .fwc2hfunc = 1, .drvinfo_type = 1, .info_buf = 1800,
149 .max_role_num = 6,
150 },
151 {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0),
152 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5,
153 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1,
154 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1,
155 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
156 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
157 .max_role_num = 6,
158 },
159 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0),
160 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
161 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
162 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
163 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
164 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
165 .max_role_num = 5,
166 },
167 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0),
168 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
169 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
170 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
171 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0,
172 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
173 .max_role_num = 5,
174 },
175 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0),
176 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
177 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
178 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
179 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0,
180 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
181 .max_role_num = 5,
182 },
183 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0),
184 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5,
185 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1,
186 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1,
187 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
188 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
189 .max_role_num = 6,
190 },
191 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0),
192 .fcxbtcrpt = 5, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 4,
193 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
194 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
195 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
196 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
197 .max_role_num = 6,
198 },
199 {RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0),
200 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
201 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
202 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
203 .fwlrole = 1, .frptmap = 1, .fcxctrl = 1, .fcxinit = 0,
204 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
205 .max_role_num = 5,
206 },
207 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0),
208 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
209 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
210 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
211 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
212 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1280,
213 .max_role_num = 5,
214 },
215 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0),
216 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2,
217 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1,
218 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
219 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0,
220 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1024,
221 .max_role_num = 5,
222 },
223
224 /* keep it to be the last as default entry */
225 {0, RTW89_FW_VER_CODE(0, 0, 0, 0),
226 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2,
227 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1,
228 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
229 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0,
230 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1024,
231 .max_role_num = 5,
232 },
233 };
234
235 #define RTW89_DEFAULT_BTC_VER_IDX (ARRAY_SIZE(rtw89_btc_ver_defs) - 1)
236
237 static const union rtw89_btc_wl_state_map btc_scanning_map = {
238 .map = {
239 .scan = 1,
240 .connecting = 1,
241 .roaming = 1,
242 .dbccing = 1,
243 ._4way = 1,
244 },
245 };
246
chip_id_to_bt_rom_code_id(u32 id)247 static u32 chip_id_to_bt_rom_code_id(u32 id)
248 {
249 switch (id) {
250 case RTL8852A:
251 case RTL8852B:
252 case RTL8852C:
253 case RTL8852BT:
254 return 0x8852;
255 case RTL8851B:
256 return 0x8851;
257 case RTL8922A:
258 return 0x8922;
259 default:
260 return 0;
261 }
262 }
263
264 struct rtw89_btc_btf_tlv {
265 u8 type;
266 u8 len;
267 u8 val[];
268 } __packed;
269
270 struct rtw89_btc_btf_tlv_v7 {
271 u8 type;
272 u8 ver;
273 u8 len;
274 u8 val[];
275 } __packed;
276
277 enum btc_btf_set_report_en {
278 RPT_EN_TDMA,
279 RPT_EN_CYCLE,
280 RPT_EN_MREG,
281 RPT_EN_BT_VER_INFO,
282 RPT_EN_BT_SCAN_INFO,
283 RPT_EN_BT_DEVICE_INFO,
284 RPT_EN_BT_AFH_MAP,
285 RPT_EN_BT_AFH_MAP_LE,
286 RPT_EN_FW_STEP_INFO,
287 RPT_EN_TEST,
288 RPT_EN_WL_ALL,
289 RPT_EN_BT_ALL,
290 RPT_EN_ALL,
291 RPT_EN_MONITER,
292 };
293
294 struct rtw89_btc_btf_set_report_v1 {
295 u8 fver;
296 __le32 enable;
297 __le32 para;
298 } __packed;
299
300 struct rtw89_btc_btf_set_report_v8 {
301 u8 type;
302 u8 fver;
303 u8 len;
304 __le32 map;
305 } __packed;
306
307 union rtw89_fbtc_rtp_ctrl {
308 struct rtw89_btc_btf_set_report_v1 v1;
309 struct rtw89_btc_btf_set_report_v8 v8;
310 };
311
312 #define BTF_SET_SLOT_TABLE_VER 1
313 struct rtw89_btc_btf_set_slot_table {
314 u8 fver;
315 u8 tbl_num;
316 struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num);
317 } __packed;
318
319 struct rtw89_btc_btf_set_slot_table_v7 {
320 u8 type;
321 u8 ver;
322 u8 len;
323 struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX];
324 } __packed;
325
326 struct rtw89_btc_btf_set_mon_reg_v1 {
327 u8 fver;
328 u8 reg_num;
329 struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num);
330 } __packed;
331
332 struct rtw89_btc_btf_set_mon_reg_v7 {
333 u8 type;
334 u8 fver;
335 u8 len;
336 struct rtw89_btc_fbtc_mreg regs[] __counted_by(len);
337 } __packed;
338
339 union rtw89_fbtc_set_mon_reg {
340 struct rtw89_btc_btf_set_mon_reg_v1 v1;
341 struct rtw89_btc_btf_set_mon_reg_v7 v7;
342 } __packed;
343
344 struct _wl_rinfo_now {
345 u8 link_mode;
346 u32 dbcc_2g_phy: 2;
347 };
348
349 enum btc_btf_set_cx_policy {
350 CXPOLICY_TDMA = 0x0,
351 CXPOLICY_SLOT = 0x1,
352 CXPOLICY_TYPE = 0x2,
353 CXPOLICY_MAX,
354 };
355
356 enum btc_b2w_scoreboard {
357 BTC_BSCB_ACT = BIT(0),
358 BTC_BSCB_ON = BIT(1),
359 BTC_BSCB_WHQL = BIT(2),
360 BTC_BSCB_BT_S1 = BIT(3),
361 BTC_BSCB_A2DP_ACT = BIT(4),
362 BTC_BSCB_RFK_RUN = BIT(5),
363 BTC_BSCB_RFK_REQ = BIT(6),
364 BTC_BSCB_LPS = BIT(7),
365 BTC_BSCB_BT_LNAB0 = BIT(8),
366 BTC_BSCB_BT_LNAB1 = BIT(10),
367 BTC_BSCB_WLRFK = BIT(11),
368 BTC_BSCB_BT_HILNA = BIT(13),
369 BTC_BSCB_BT_CONNECT = BIT(16),
370 BTC_BSCB_PATCH_CODE = BIT(30),
371 BTC_BSCB_ALL = GENMASK(30, 0),
372 };
373
374 enum btc_phymap {
375 BTC_PHY_0 = BIT(0),
376 BTC_PHY_1 = BIT(1),
377 BTC_PHY_ALL = BIT(0) | BIT(1),
378 };
379
380 enum btc_cx_state_map {
381 BTC_WIDLE = 0,
382 BTC_WBUSY_BNOSCAN,
383 BTC_WBUSY_BSCAN,
384 BTC_WSCAN_BNOSCAN,
385 BTC_WSCAN_BSCAN,
386 BTC_WLINKING
387 };
388
389 enum btc_ant_phase {
390 BTC_ANT_WPOWERON = 0,
391 BTC_ANT_WINIT,
392 BTC_ANT_WONLY,
393 BTC_ANT_WOFF,
394 BTC_ANT_W2G,
395 BTC_ANT_W5G,
396 BTC_ANT_W25G,
397 BTC_ANT_FREERUN,
398 BTC_ANT_WRFK,
399 BTC_ANT_WRFK2,
400 BTC_ANT_BRFK,
401 BTC_ANT_MAX
402 };
403
404 enum btc_plt {
405 BTC_PLT_NONE = 0,
406 BTC_PLT_LTE_RX = BIT(0),
407 BTC_PLT_GNT_BT_TX = BIT(1),
408 BTC_PLT_GNT_BT_RX = BIT(2),
409 BTC_PLT_GNT_WL = BIT(3),
410 BTC_PLT_BT = BIT(1) | BIT(2),
411 BTC_PLT_ALL = 0xf
412 };
413
414 enum btc_cx_poicy_main_type {
415 BTC_CXP_OFF = 0,
416 BTC_CXP_OFFB,
417 BTC_CXP_OFFE,
418 BTC_CXP_FIX,
419 BTC_CXP_PFIX,
420 BTC_CXP_AUTO,
421 BTC_CXP_PAUTO,
422 BTC_CXP_AUTO2,
423 BTC_CXP_PAUTO2,
424 BTC_CXP_MANUAL,
425 BTC_CXP_USERDEF0,
426 BTC_CXP_MAIN_MAX
427 };
428
429 enum btc_cx_poicy_type {
430 /* TDMA off + pri: BT > WL */
431 BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0,
432
433 /* TDMA off + pri: WL > BT */
434 BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1,
435
436 /* TDMA off + pri: BT = WL */
437 BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2,
438
439 /* TDMA off + pri: BT = WL > BT_Lo */
440 BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3,
441
442 /* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */
443 BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4,
444
445 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
446 BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5,
447
448 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
449 BTC_CXP_OFF_EQ4 = (BTC_CXP_OFF << 8) | 6,
450
451 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
452 BTC_CXP_OFF_EQ5 = (BTC_CXP_OFF << 8) | 7,
453
454 /* TDMA off + pri: BT_Hi > WL > BT_Lo */
455 BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 8,
456
457 /* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
458 BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 9,
459
460 /* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
461 BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 10,
462
463 /* TDMA off + pri: WL_Hi-Tx = BT */
464 BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 11,
465
466 /* TDMA off + pri: WL > BT, Block-BT*/
467 BTC_CXP_OFF_WL2 = (BTC_CXP_OFF << 8) | 12,
468
469 /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/
470 BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
471
472 /* TDMA off + Ext-Ctrl + pri: default */
473 BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0,
474
475 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
476 BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1,
477
478 /* TDMA off + Ext-Ctrl + pri: default */
479 BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2,
480
481 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
482 BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3,
483
484 /* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */
485 BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4,
486
487 /* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */
488 BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5,
489
490 /* TDMA off + Ext-Ctrl + pri: default */
491 BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6,
492
493 /* TDMA Fix slot-0: W1:B1 = 30:30 */
494 BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0,
495
496 /* TDMA Fix slot-1: W1:B1 = 50:50 */
497 BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1,
498
499 /* TDMA Fix slot-2: W1:B1 = 20:30 */
500 BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2,
501
502 /* TDMA Fix slot-3: W1:B1 = 40:10 */
503 BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3,
504
505 /* TDMA Fix slot-4: W1:B1 = 70:10 */
506 BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4,
507
508 /* TDMA Fix slot-5: W1:B1 = 20:60 */
509 BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5,
510
511 /* TDMA Fix slot-6: W1:B1 = 30:60 */
512 BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6,
513
514 /* TDMA Fix slot-7: W1:B1 = 20:80 */
515 BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7,
516
517 /* TDMA Fix slot-8: W1:B1 = user-define */
518 BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8,
519
520 /* TDMA Fix slot-9: W1:B1 = 40:10 */
521 BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 9,
522
523 /* TDMA Fix slot-10: W1:B1 = 40:10 */
524 BTC_CXP_FIX_TD4010ISO_DL = (BTC_CXP_FIX << 8) | 10,
525
526 /* TDMA Fix slot-11: W1:B1 = 40:10 */
527 BTC_CXP_FIX_TD4010ISO_UL = (BTC_CXP_FIX << 8) | 11,
528
529 /* PS-TDMA Fix slot-0: W1:B1 = 30:30 */
530 BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0,
531
532 /* PS-TDMA Fix slot-1: W1:B1 = 50:50 */
533 BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1,
534
535 /* PS-TDMA Fix slot-2: W1:B1 = 20:30 */
536 BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2,
537
538 /* PS-TDMA Fix slot-3: W1:B1 = 20:60 */
539 BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3,
540
541 /* PS-TDMA Fix slot-4: W1:B1 = 30:70 */
542 BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4,
543
544 /* PS-TDMA Fix slot-5: W1:B1 = 20:80 */
545 BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5,
546
547 /* PS-TDMA Fix slot-6: W1:B1 = user-define */
548 BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6,
549
550 /* TDMA Auto slot-0: W1:B1 = 50:200 */
551 BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0,
552
553 /* TDMA Auto slot-1: W1:B1 = 60:200 */
554 BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1,
555
556 /* TDMA Auto slot-2: W1:B1 = 20:200 */
557 BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2,
558
559 /* TDMA Auto slot-3: W1:B1 = user-define */
560 BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3,
561
562 /* PS-TDMA Auto slot-0: W1:B1 = 50:200 */
563 BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0,
564
565 /* PS-TDMA Auto slot-1: W1:B1 = 60:200 */
566 BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1,
567
568 /* PS-TDMA Auto slot-2: W1:B1 = 20:200 */
569 BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2,
570
571 /* PS-TDMA Auto slot-3: W1:B1 = user-define */
572 BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3,
573
574 /* TDMA Auto slot2-0: W1:B4 = 30:50 */
575 BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0,
576
577 /* TDMA Auto slot2-1: W1:B4 = 30:70 */
578 BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1,
579
580 /* TDMA Auto slot2-2: W1:B4 = 50:50 */
581 BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2,
582
583 /* TDMA Auto slot2-3: W1:B4 = 60:60 */
584 BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3,
585
586 /* TDMA Auto slot2-4: W1:B4 = 20:80 */
587 BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4,
588
589 /* TDMA Auto slot2-5: W1:B4 = user-define */
590 BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5,
591
592 /* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */
593 BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0,
594
595 /* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */
596 BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1,
597
598 /* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */
599 BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2,
600
601 /* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */
602 BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3,
603
604 /* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */
605 BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4,
606
607 /* PS-TDMA Auto slot2-5: W1:B4 = user-define */
608 BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5,
609
610 BTC_CXP_MAX = 0xffff
611 };
612
613 enum btc_wl_rfk_result {
614 BTC_WRFK_REJECT = 0,
615 BTC_WRFK_ALLOW = 1,
616 };
617
618 enum btc_coex_info_map_en {
619 BTC_COEX_INFO_CX = BIT(0),
620 BTC_COEX_INFO_WL = BIT(1),
621 BTC_COEX_INFO_BT = BIT(2),
622 BTC_COEX_INFO_DM = BIT(3),
623 BTC_COEX_INFO_MREG = BIT(4),
624 BTC_COEX_INFO_SUMMARY = BIT(5),
625 BTC_COEX_INFO_ALL = GENMASK(7, 0),
626 };
627
628 #define BTC_CXP_MASK GENMASK(15, 8)
629
630 enum btc_w2b_scoreboard {
631 BTC_WSCB_ACTIVE = BIT(0),
632 BTC_WSCB_ON = BIT(1),
633 BTC_WSCB_SCAN = BIT(2),
634 BTC_WSCB_UNDERTEST = BIT(3),
635 BTC_WSCB_RXGAIN = BIT(4),
636 BTC_WSCB_WLBUSY = BIT(7),
637 BTC_WSCB_EXTFEM = BIT(8),
638 BTC_WSCB_TDMA = BIT(9),
639 BTC_WSCB_FIX2M = BIT(10),
640 BTC_WSCB_WLRFK = BIT(11),
641 BTC_WSCB_RXSCAN_PRI = BIT(12),
642 BTC_WSCB_BT_HILNA = BIT(13),
643 BTC_WSCB_BTLOG = BIT(14),
644 BTC_WSCB_ALL = GENMASK(23, 0),
645 };
646
647 enum btc_wl_link_mode {
648 BTC_WLINK_NOLINK = 0x0,
649 BTC_WLINK_2G_STA,
650 BTC_WLINK_2G_AP,
651 BTC_WLINK_2G_GO,
652 BTC_WLINK_2G_GC,
653 BTC_WLINK_2G_SCC,
654 BTC_WLINK_2G_MCC,
655 BTC_WLINK_25G_MCC,
656 BTC_WLINK_25G_DBCC,
657 BTC_WLINK_5G,
658 BTC_WLINK_2G_NAN,
659 BTC_WLINK_OTHER,
660 BTC_WLINK_MAX
661 };
662
663 enum btc_wl_mrole_type {
664 BTC_WLMROLE_NONE = 0x0,
665 BTC_WLMROLE_STA_GC,
666 BTC_WLMROLE_STA_GC_NOA,
667 BTC_WLMROLE_STA_GO,
668 BTC_WLMROLE_STA_GO_NOA,
669 BTC_WLMROLE_STA_STA,
670 BTC_WLMROLE_MAX
671 };
672
673 enum btc_bt_hid_type {
674 BTC_HID_218 = BIT(0),
675 BTC_HID_418 = BIT(1),
676 BTC_HID_BLE = BIT(2),
677 BTC_HID_RCU = BIT(3),
678 BTC_HID_RCU_VOICE = BIT(4),
679 BTC_HID_OTHER_LEGACY = BIT(5)
680 };
681
682 enum btc_reset_module {
683 BTC_RESET_CX = BIT(0),
684 BTC_RESET_DM = BIT(1),
685 BTC_RESET_CTRL = BIT(2),
686 BTC_RESET_CXDM = BIT(0) | BIT(1),
687 BTC_RESET_BTINFO = BIT(3),
688 BTC_RESET_MDINFO = BIT(4),
689 BTC_RESET_ALL = GENMASK(7, 0),
690 };
691
692 enum btc_gnt_state {
693 BTC_GNT_HW = 0,
694 BTC_GNT_SW_LO,
695 BTC_GNT_SW_HI,
696 BTC_GNT_MAX
697 };
698
699 enum btc_ctr_path {
700 BTC_CTRL_BY_BT = 0,
701 BTC_CTRL_BY_WL
702 };
703
704 enum btc_wlact_state {
705 BTC_WLACT_HW = 0,
706 BTC_WLACT_SW_LO,
707 BTC_WLACT_SW_HI,
708 BTC_WLACT_MAX,
709 };
710
711 enum btc_wl_max_tx_time {
712 BTC_MAX_TX_TIME_L1 = 500,
713 BTC_MAX_TX_TIME_L2 = 1000,
714 BTC_MAX_TX_TIME_L3 = 2000,
715 BTC_MAX_TX_TIME_DEF = 5280
716 };
717
718 enum btc_wl_max_tx_retry {
719 BTC_MAX_TX_RETRY_L1 = 7,
720 BTC_MAX_TX_RETRY_L2 = 15,
721 BTC_MAX_TX_RETRY_DEF = 31,
722 };
723
724 enum btc_reason_and_action {
725 BTC_RSN_NONE,
726 BTC_RSN_NTFY_INIT,
727 BTC_RSN_NTFY_SWBAND,
728 BTC_RSN_NTFY_WL_STA,
729 BTC_RSN_NTFY_RADIO_STATE,
730 BTC_RSN_UPDATE_BT_SCBD,
731 BTC_RSN_NTFY_WL_RFK,
732 BTC_RSN_UPDATE_BT_INFO,
733 BTC_RSN_NTFY_SCAN_START,
734 BTC_RSN_NTFY_SCAN_FINISH,
735 BTC_RSN_NTFY_SPECIFIC_PACKET,
736 BTC_RSN_NTFY_POWEROFF,
737 BTC_RSN_NTFY_ROLE_INFO,
738 BTC_RSN_CMD_SET_COEX,
739 BTC_RSN_ACT1_WORK,
740 BTC_RSN_BT_DEVINFO_WORK,
741 BTC_RSN_RFK_CHK_WORK,
742 BTC_RSN_NUM,
743 BTC_ACT_NONE = 100,
744 BTC_ACT_WL_ONLY,
745 BTC_ACT_WL_5G,
746 BTC_ACT_WL_OTHER,
747 BTC_ACT_WL_IDLE,
748 BTC_ACT_WL_NC,
749 BTC_ACT_WL_RFK,
750 BTC_ACT_WL_INIT,
751 BTC_ACT_WL_OFF,
752 BTC_ACT_FREERUN,
753 BTC_ACT_BT_WHQL,
754 BTC_ACT_BT_RFK,
755 BTC_ACT_BT_OFF,
756 BTC_ACT_BT_IDLE,
757 BTC_ACT_BT_HFP,
758 BTC_ACT_BT_HID,
759 BTC_ACT_BT_A2DP,
760 BTC_ACT_BT_A2DPSINK,
761 BTC_ACT_BT_PAN,
762 BTC_ACT_BT_A2DP_HID,
763 BTC_ACT_BT_A2DP_PAN,
764 BTC_ACT_BT_PAN_HID,
765 BTC_ACT_BT_A2DP_PAN_HID,
766 BTC_ACT_WL_25G_MCC,
767 BTC_ACT_WL_2G_MCC,
768 BTC_ACT_WL_2G_SCC,
769 BTC_ACT_WL_2G_AP,
770 BTC_ACT_WL_2G_GO,
771 BTC_ACT_WL_2G_GC,
772 BTC_ACT_WL_2G_NAN,
773 BTC_ACT_LAST,
774 BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE,
775 BTC_ACT_EXT_BIT = BIT(14),
776 BTC_POLICY_EXT_BIT = BIT(15),
777 };
778
779 #define BTC_FREERUN_ANTISO_MIN 30
780 #define BTC_TDMA_BTHID_MAX 2
781 #define BTC_BLINK_NOCONNECT 0
782 #define BTC_B1_MAX 250 /* unit ms */
783
784 static void _run_coex(struct rtw89_dev *rtwdev,
785 enum btc_reason_and_action reason);
786 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state);
787 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update);
788
_send_fw_cmd(struct rtw89_dev * rtwdev,u8 h2c_class,u8 h2c_func,void * param,u16 len)789 static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func,
790 void *param, u16 len)
791 {
792 struct rtw89_btc *btc = &rtwdev->btc;
793 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
794 struct rtw89_btc_cx *cx = &btc->cx;
795 struct rtw89_btc_wl_info *wl = &cx->wl;
796 struct rtw89_btc_dm *dm = &btc->dm;
797 int ret;
798
799 if (len > BTC_H2C_MAXLEN || len == 0) {
800 btc->fwinfo.cnt_h2c_fail++;
801 dm->error.map.h2c_buffer_over = true;
802 return -EINVAL;
803 } else if (!wl->status.map.init_ok) {
804 rtw89_debug(rtwdev, RTW89_DBG_BTC,
805 "[BTC], %s(): return by btc not init!!\n", __func__);
806 pfwinfo->cnt_h2c_fail++;
807 return -EINVAL;
808 } else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF &&
809 wl->status.map.rf_off == BTC_LPS_RF_OFF) ||
810 (wl->status.map.lps_pre == BTC_LPS_RF_OFF &&
811 wl->status.map.lps == BTC_LPS_RF_OFF)) {
812 rtw89_debug(rtwdev, RTW89_DBG_BTC,
813 "[BTC], %s(): return by wl off!!\n", __func__);
814 pfwinfo->cnt_h2c_fail++;
815 return -EINVAL;
816 }
817
818 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, param, len,
819 false, true);
820 if (ret)
821 pfwinfo->cnt_h2c_fail++;
822 else
823 pfwinfo->cnt_h2c++;
824
825 return ret;
826 }
827
_reset_btc_var(struct rtw89_dev * rtwdev,u8 type)828 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
829 {
830 struct rtw89_btc *btc = &rtwdev->btc;
831 const struct rtw89_btc_ver *ver = btc->ver;
832 struct rtw89_btc_cx *cx = &btc->cx;
833 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
834 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
835 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
836 struct rtw89_btc_wl_link_info *wl_linfo;
837 u8 i;
838
839 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
840
841 if (type & BTC_RESET_CX)
842 memset(cx, 0, sizeof(*cx));
843
844 if (type & BTC_RESET_BTINFO) /* only for BT enable */
845 memset(bt, 0, sizeof(*bt));
846
847 if (type & BTC_RESET_CTRL) {
848 memset(&btc->ctrl, 0, sizeof(btc->ctrl));
849 btc->manual_ctrl = false;
850 if (ver->fcxctrl != 7)
851 btc->ctrl.ctrl.trace_step = FCXDEF_STEP;
852 }
853
854 /* Init Coex variables that are not zero */
855 if (type & BTC_RESET_DM) {
856 memset(&btc->dm, 0, sizeof(btc->dm));
857 memset(bt_linfo->rssi_state, 0, sizeof(bt_linfo->rssi_state));
858 for (i = 0; i < RTW89_PORT_NUM; i++) {
859 if (btc->ver->fwlrole == 8)
860 wl_linfo = &wl->rlink_info[i][0];
861 else
862 wl_linfo = &wl->link_info[i];
863 memset(wl_linfo->rssi_state, 0, sizeof(wl_linfo->rssi_state));
864 }
865
866 /* set the slot_now table to original */
867 btc->dm.tdma_now = t_def[CXTD_OFF];
868 btc->dm.tdma = t_def[CXTD_OFF];
869 if (ver->fcxslots >= 7) {
870 for (i = 0; i < ARRAY_SIZE(s_def); i++) {
871 btc->dm.slot.v7[i].dur = s_def[i].dur;
872 btc->dm.slot.v7[i].cxtype = s_def[i].cxtype;
873 btc->dm.slot.v7[i].cxtbl = s_def[i].cxtbl;
874 }
875 memcpy(&btc->dm.slot_now.v7, &btc->dm.slot.v7,
876 sizeof(btc->dm.slot_now.v7));
877 } else {
878 memcpy(&btc->dm.slot_now.v1, s_def,
879 sizeof(btc->dm.slot_now.v1));
880 memcpy(&btc->dm.slot.v1, s_def,
881 sizeof(btc->dm.slot.v1));
882 }
883
884 btc->policy_len = 0;
885 btc->bt_req_len = 0;
886
887 btc->dm.coex_info_map = BTC_COEX_INFO_ALL;
888 btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF;
889 btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF;
890 btc->dm.wl_pre_agc_rb = BTC_PREAGC_NOTFOUND;
891 btc->dm.wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_NOTFOUND;
892 }
893
894 if (type & BTC_RESET_MDINFO)
895 memset(&btc->mdinfo, 0, sizeof(btc->mdinfo));
896 }
897
_search_reg_index(struct rtw89_dev * rtwdev,u8 mreg_num,u16 reg_type,u32 target)898 static u8 _search_reg_index(struct rtw89_dev *rtwdev, u8 mreg_num, u16 reg_type, u32 target)
899 {
900 const struct rtw89_chip_info *chip = rtwdev->chip;
901 u8 i;
902
903 for (i = 0; i < mreg_num; i++)
904 if (le16_to_cpu(chip->mon_reg[i].type) == reg_type &&
905 le32_to_cpu(chip->mon_reg[i].offset) == target) {
906 return i;
907 }
908 return BTC_REG_NOTFOUND;
909 }
910
_get_reg_status(struct rtw89_dev * rtwdev,u8 type,u8 * val)911 static void _get_reg_status(struct rtw89_dev *rtwdev, u8 type, u8 *val)
912 {
913 struct rtw89_btc *btc = &rtwdev->btc;
914 const struct rtw89_btc_ver *ver = btc->ver;
915 union rtw89_btc_module_info *md = &btc->mdinfo;
916 union rtw89_btc_fbtc_mreg_val *pmreg;
917 u32 pre_agc_addr = R_BTC_BB_PRE_AGC_S1;
918 u32 reg_val;
919 u8 idx, switch_type;
920
921 if (ver->fcxinit == 7)
922 switch_type = md->md_v7.switch_type;
923 else
924 switch_type = md->md.switch_type;
925
926 if (btc->btg_pos == RF_PATH_A)
927 pre_agc_addr = R_BTC_BB_PRE_AGC_S0;
928
929 switch (type) {
930 case BTC_CSTATUS_TXDIV_POS:
931 if (switch_type == BTC_SWITCH_INTERNAL)
932 *val = BTC_ANT_DIV_MAIN;
933 break;
934 case BTC_CSTATUS_RXDIV_POS:
935 if (switch_type == BTC_SWITCH_INTERNAL)
936 *val = BTC_ANT_DIV_MAIN;
937 break;
938 case BTC_CSTATUS_BB_GNT_MUX:
939 reg_val = rtw89_phy_read32(rtwdev, R_BTC_BB_BTG_RX);
940 *val = !(reg_val & B_BTC_BB_GNT_MUX);
941 break;
942 case BTC_CSTATUS_BB_GNT_MUX_MON:
943 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
944 return;
945
946 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
947 if (ver->fcxmreg == 1) {
948 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
949 REG_BB, R_BTC_BB_BTG_RX);
950 if (idx == BTC_REG_NOTFOUND) {
951 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
952 } else {
953 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]);
954 *val = !(reg_val & B_BTC_BB_GNT_MUX);
955 }
956 } else if (ver->fcxmreg == 2) {
957 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
958 REG_BB, R_BTC_BB_BTG_RX);
959 if (idx == BTC_REG_NOTFOUND) {
960 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
961 } else {
962 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]);
963 *val = !(reg_val & B_BTC_BB_GNT_MUX);
964 }
965 }
966 break;
967 case BTC_CSTATUS_BB_PRE_AGC:
968 reg_val = rtw89_phy_read32(rtwdev, pre_agc_addr);
969 reg_val &= B_BTC_BB_PRE_AGC_MASK;
970 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
971 break;
972 case BTC_CSTATUS_BB_PRE_AGC_MON:
973 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
974 return;
975
976 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
977 if (ver->fcxmreg == 1) {
978 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
979 REG_BB, pre_agc_addr);
980 if (idx == BTC_REG_NOTFOUND) {
981 *val = BTC_PREAGC_NOTFOUND;
982 } else {
983 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]) &
984 B_BTC_BB_PRE_AGC_MASK;
985 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
986 }
987 } else if (ver->fcxmreg == 2) {
988 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
989 REG_BB, pre_agc_addr);
990 if (idx == BTC_REG_NOTFOUND) {
991 *val = BTC_PREAGC_NOTFOUND;
992 } else {
993 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]) &
994 B_BTC_BB_PRE_AGC_MASK;
995 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
996 }
997 }
998 break;
999 default:
1000 break;
1001 }
1002 }
1003
1004 #define BTC_RPT_HDR_SIZE 3
1005 #define BTC_CHK_WLSLOT_DRIFT_MAX 15
1006 #define BTC_CHK_BTSLOT_DRIFT_MAX 15
1007 #define BTC_CHK_HANG_MAX 3
1008
_chk_btc_err(struct rtw89_dev * rtwdev,u8 type,u32 cnt)1009 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt)
1010 {
1011 struct rtw89_btc *btc = &rtwdev->btc;
1012 struct rtw89_btc_cx *cx = &btc->cx;
1013 struct rtw89_btc_bt_info *bt = &cx->bt;
1014 struct rtw89_btc_wl_info *wl = &cx->wl;
1015 struct rtw89_btc_dm *dm = &btc->dm;
1016
1017 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1018 "[BTC], %s(): type:%d cnt:%d\n",
1019 __func__, type, cnt);
1020
1021 switch (type) {
1022 case BTC_DCNT_WL_FW_VER_MATCH:
1023 if ((wl->ver_info.fw_coex & 0xffff0000) !=
1024 rtwdev->chip->wlcx_desired) {
1025 wl->fw_ver_mismatch = true;
1026 dm->error.map.wl_ver_mismatch = true;
1027 } else {
1028 wl->fw_ver_mismatch = false;
1029 dm->error.map.wl_ver_mismatch = false;
1030 }
1031 break;
1032 case BTC_DCNT_RPT_HANG:
1033 if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map)
1034 dm->cnt_dm[BTC_DCNT_RPT_HANG]++;
1035 else
1036 dm->cnt_dm[BTC_DCNT_RPT_HANG] = 0;
1037
1038 if (dm->cnt_dm[BTC_DCNT_RPT_HANG] >= BTC_CHK_HANG_MAX)
1039 dm->error.map.wl_fw_hang = true;
1040 else
1041 dm->error.map.wl_fw_hang = false;
1042
1043 dm->cnt_dm[BTC_DCNT_RPT] = cnt;
1044 break;
1045 case BTC_DCNT_CYCLE_HANG:
1046 if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt &&
1047 (dm->tdma_now.type != CXTDMA_OFF ||
1048 dm->tdma_now.ext_ctrl == CXECTL_EXT))
1049 dm->cnt_dm[BTC_DCNT_CYCLE_HANG]++;
1050 else
1051 dm->cnt_dm[BTC_DCNT_CYCLE_HANG] = 0;
1052
1053 if (dm->cnt_dm[BTC_DCNT_CYCLE_HANG] >= BTC_CHK_HANG_MAX)
1054 dm->error.map.cycle_hang = true;
1055 else
1056 dm->error.map.cycle_hang = false;
1057
1058 dm->cnt_dm[BTC_DCNT_CYCLE] = cnt;
1059 break;
1060 case BTC_DCNT_W1_HANG:
1061 if (dm->cnt_dm[BTC_DCNT_W1] == cnt &&
1062 dm->tdma_now.type != CXTDMA_OFF)
1063 dm->cnt_dm[BTC_DCNT_W1_HANG]++;
1064 else
1065 dm->cnt_dm[BTC_DCNT_W1_HANG] = 0;
1066
1067 if (dm->cnt_dm[BTC_DCNT_W1_HANG] >= BTC_CHK_HANG_MAX)
1068 dm->error.map.w1_hang = true;
1069 else
1070 dm->error.map.w1_hang = false;
1071
1072 dm->cnt_dm[BTC_DCNT_W1] = cnt;
1073 break;
1074 case BTC_DCNT_B1_HANG:
1075 if (dm->cnt_dm[BTC_DCNT_B1] == cnt &&
1076 dm->tdma_now.type != CXTDMA_OFF)
1077 dm->cnt_dm[BTC_DCNT_B1_HANG]++;
1078 else
1079 dm->cnt_dm[BTC_DCNT_B1_HANG] = 0;
1080
1081 if (dm->cnt_dm[BTC_DCNT_B1_HANG] >= BTC_CHK_HANG_MAX)
1082 dm->error.map.b1_hang = true;
1083 else
1084 dm->error.map.b1_hang = false;
1085
1086 dm->cnt_dm[BTC_DCNT_B1] = cnt;
1087 break;
1088 case BTC_DCNT_E2G_HANG:
1089 if (dm->cnt_dm[BTC_DCNT_E2G] == cnt &&
1090 dm->tdma_now.ext_ctrl == CXECTL_EXT)
1091 dm->cnt_dm[BTC_DCNT_E2G_HANG]++;
1092 else
1093 dm->cnt_dm[BTC_DCNT_E2G_HANG] = 0;
1094
1095 if (dm->cnt_dm[BTC_DCNT_E2G_HANG] >= BTC_CHK_HANG_MAX)
1096 dm->error.map.wl_e2g_hang = true;
1097 else
1098 dm->error.map.wl_e2g_hang = false;
1099
1100 dm->cnt_dm[BTC_DCNT_E2G] = cnt;
1101 break;
1102 case BTC_DCNT_TDMA_NONSYNC:
1103 if (cnt != 0) /* if tdma not sync between drv/fw */
1104 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++;
1105 else
1106 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0;
1107
1108 if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX)
1109 dm->error.map.tdma_no_sync = true;
1110 else
1111 dm->error.map.tdma_no_sync = false;
1112 break;
1113 case BTC_DCNT_SLOT_NONSYNC:
1114 if (cnt != 0) /* if slot not sync between drv/fw */
1115 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++;
1116 else
1117 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0;
1118
1119 if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX)
1120 dm->error.map.slot_no_sync = true;
1121 else
1122 dm->error.map.slot_no_sync = false;
1123 break;
1124 case BTC_DCNT_BTTX_HANG:
1125 cnt = cx->cnt_bt[BTC_BCNT_LOPRI_TX];
1126
1127 if (cnt == 0 && bt->link_info.slave_role)
1128 dm->cnt_dm[BTC_DCNT_BTTX_HANG]++;
1129 else
1130 dm->cnt_dm[BTC_DCNT_BTTX_HANG] = 0;
1131
1132 if (dm->cnt_dm[BTC_DCNT_BTTX_HANG] >= BTC_CHK_HANG_MAX)
1133 dm->error.map.bt_tx_hang = true;
1134 else
1135 dm->error.map.bt_tx_hang = false;
1136 break;
1137 case BTC_DCNT_BTCNT_HANG:
1138 cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] +
1139 cx->cnt_bt[BTC_BCNT_HIPRI_TX] +
1140 cx->cnt_bt[BTC_BCNT_LOPRI_RX] +
1141 cx->cnt_bt[BTC_BCNT_LOPRI_TX];
1142
1143 if (cnt == 0)
1144 dm->cnt_dm[BTC_DCNT_BTCNT_HANG]++;
1145 else
1146 dm->cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
1147
1148 if ((dm->cnt_dm[BTC_DCNT_BTCNT_HANG] >= BTC_CHK_HANG_MAX &&
1149 bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_HANG] &&
1150 !bt->enable.now))
1151 _update_bt_scbd(rtwdev, false);
1152 break;
1153 case BTC_DCNT_WL_SLOT_DRIFT:
1154 if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX)
1155 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++;
1156 else
1157 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0;
1158
1159 if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1160 dm->error.map.wl_slot_drift = true;
1161 else
1162 dm->error.map.wl_slot_drift = false;
1163 break;
1164 case BTC_DCNT_BT_SLOT_DRIFT:
1165 if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX)
1166 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++;
1167 else
1168 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0;
1169
1170 if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1171 dm->error.map.bt_slot_drift = true;
1172 else
1173 dm->error.map.bt_slot_drift = false;
1174
1175 break;
1176 }
1177 }
1178
_update_bt_report(struct rtw89_dev * rtwdev,u8 rpt_type,u8 * pfinfo)1179 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo)
1180 {
1181 struct rtw89_btc *btc = &rtwdev->btc;
1182 const struct rtw89_btc_ver *ver = btc->ver;
1183 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1184 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
1185 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc;
1186 union rtw89_btc_fbtc_btver *pver = &btc->fwinfo.rpt_fbtc_btver.finfo;
1187 struct rtw89_btc_fbtc_btafh_v2 *pafh_v2 = NULL;
1188 struct rtw89_btc_fbtc_btafh_v7 *pafh_v7 = NULL;
1189 struct rtw89_btc_fbtc_btdevinfo *pdev = NULL;
1190 struct rtw89_btc_fbtc_btafh *pafh_v1 = NULL;
1191 struct rtw89_btc_fbtc_btscan_v1 *pscan_v1;
1192 struct rtw89_btc_fbtc_btscan_v2 *pscan_v2;
1193 struct rtw89_btc_fbtc_btscan_v7 *pscan_v7;
1194 bool scan_update = true;
1195 int i;
1196
1197 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1198 "[BTC], %s(): rpt_type:%d\n",
1199 __func__, rpt_type);
1200
1201 switch (rpt_type) {
1202 case BTC_RPT_TYPE_BT_VER:
1203 if (ver->fcxbtver == 7) {
1204 pver->v7 = *(struct rtw89_btc_fbtc_btver_v7 *)pfinfo;
1205 bt->ver_info.fw = le32_to_cpu(pver->v7.fw_ver);
1206 bt->ver_info.fw_coex = le32_get_bits(pver->v7.coex_ver,
1207 GENMASK(7, 0));
1208 bt->feature = le32_to_cpu(pver->v7.feature);
1209 } else {
1210 pver->v1 = *(struct rtw89_btc_fbtc_btver_v1 *)pfinfo;
1211 bt->ver_info.fw = le32_to_cpu(pver->v1.fw_ver);
1212 bt->ver_info.fw_coex = le32_get_bits(pver->v1.coex_ver,
1213 GENMASK(7, 0));
1214 bt->feature = le32_to_cpu(pver->v1.feature);
1215 }
1216 break;
1217 case BTC_RPT_TYPE_BT_SCAN:
1218 if (ver->fcxbtscan == 1) {
1219 pscan_v1 = (struct rtw89_btc_fbtc_btscan_v1 *)pfinfo;
1220 for (i = 0; i < BTC_SCAN_MAX1; i++) {
1221 bt->scan_info_v1[i] = pscan_v1->scan[i];
1222 if (bt->scan_info_v1[i].win == 0 &&
1223 bt->scan_info_v1[i].intvl == 0)
1224 scan_update = false;
1225 }
1226 } else if (ver->fcxbtscan == 2) {
1227 pscan_v2 = (struct rtw89_btc_fbtc_btscan_v2 *)pfinfo;
1228 for (i = 0; i < CXSCAN_MAX; i++) {
1229 bt->scan_info_v2[i] = pscan_v2->para[i];
1230 if ((pscan_v2->type & BIT(i)) &&
1231 pscan_v2->para[i].win == 0 &&
1232 pscan_v2->para[i].intvl == 0)
1233 scan_update = false;
1234 }
1235 } else if (ver->fcxbtscan == 7) {
1236 pscan_v7 = (struct rtw89_btc_fbtc_btscan_v7 *)pfinfo;
1237 for (i = 0; i < CXSCAN_MAX; i++) {
1238 bt->scan_info_v2[i] = pscan_v7->para[i];
1239 if ((pscan_v7->type & BIT(i)) &&
1240 pscan_v7->para[i].win == 0 &&
1241 pscan_v7->para[i].intvl == 0)
1242 scan_update = false;
1243 }
1244 }
1245 if (scan_update)
1246 bt->scan_info_update = 1;
1247 break;
1248 case BTC_RPT_TYPE_BT_AFH:
1249 if (ver->fcxbtafh == 2) {
1250 pafh_v2 = (struct rtw89_btc_fbtc_btafh_v2 *)pfinfo;
1251 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1252 memcpy(&bt_linfo->afh_map[0], pafh_v2->afh_l, 4);
1253 memcpy(&bt_linfo->afh_map[4], pafh_v2->afh_m, 4);
1254 memcpy(&bt_linfo->afh_map[8], pafh_v2->afh_h, 2);
1255 }
1256 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LE) {
1257 memcpy(&bt_linfo->afh_map_le[0], pafh_v2->afh_le_a, 4);
1258 memcpy(&bt_linfo->afh_map_le[4], pafh_v2->afh_le_b, 1);
1259 }
1260 } else if (ver->fcxbtafh == 7) {
1261 pafh_v7 = (struct rtw89_btc_fbtc_btafh_v7 *)pfinfo;
1262 if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1263 memcpy(&bt_linfo->afh_map[0], pafh_v7->afh_l, 4);
1264 memcpy(&bt_linfo->afh_map[4], pafh_v7->afh_m, 4);
1265 memcpy(&bt_linfo->afh_map[8], pafh_v7->afh_h, 2);
1266 }
1267 if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LE) {
1268 memcpy(&bt_linfo->afh_map_le[0], pafh_v7->afh_le_a, 4);
1269 memcpy(&bt_linfo->afh_map_le[4], pafh_v7->afh_le_b, 1);
1270 }
1271 } else if (ver->fcxbtafh == 1) {
1272 pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo;
1273 memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4);
1274 memcpy(&bt_linfo->afh_map[4], pafh_v1->afh_m, 4);
1275 memcpy(&bt_linfo->afh_map[8], pafh_v1->afh_h, 2);
1276 }
1277 break;
1278 case BTC_RPT_TYPE_BT_DEVICE:
1279 pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo;
1280 a2dp->device_name = le32_to_cpu(pdev->dev_name);
1281 a2dp->vendor_id = le16_to_cpu(pdev->vendor_id);
1282 a2dp->flush_time = le32_to_cpu(pdev->flush_time);
1283 break;
1284 default:
1285 break;
1286 }
1287 }
1288
rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev * rtwdev,u8 * index)1289 static void rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev *rtwdev, u8 *index)
1290 {
1291 struct rtw89_btc *btc = &rtwdev->btc;
1292 const struct rtw89_btc_ver *ver = btc->ver;
1293
1294 if (ver->fwevntrptl == 1)
1295 return;
1296
1297 if (*index <= __BTC_RPT_TYPE_V0_SAME)
1298 return;
1299 else if (*index <= __BTC_RPT_TYPE_V0_MAX)
1300 (*index)++;
1301 else
1302 *index = BTC_RPT_TYPE_MAX;
1303 }
1304
1305 #define BTC_LEAK_AP_TH 10
1306 #define BTC_CYSTA_CHK_PERIOD 100
1307
1308 struct rtw89_btc_prpt {
1309 u8 type;
1310 __le16 len;
1311 u8 content[];
1312 } __packed;
1313
_chk_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * prptbuf,u32 index)1314 static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
1315 struct rtw89_btc_btf_fwinfo *pfwinfo,
1316 u8 *prptbuf, u32 index)
1317 {
1318 struct rtw89_btc *btc = &rtwdev->btc;
1319 const struct rtw89_btc_ver *ver = btc->ver;
1320 struct rtw89_btc_dm *dm = &btc->dm;
1321 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
1322 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1323 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1324 union rtw89_btc_fbtc_rpt_ctrl_ver_info *prpt = NULL;
1325 union rtw89_btc_fbtc_cysta_info *pcysta = NULL;
1326 struct rtw89_btc_prpt *btc_prpt = NULL;
1327 void *rpt_content = NULL, *pfinfo = NULL;
1328 u8 rpt_type = 0;
1329 u16 wl_slot_set = 0, wl_slot_real = 0, val16;
1330 u32 trace_step = 0, rpt_len = 0, diff_t = 0;
1331 u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr;
1332 u8 i, val = 0, val1, val2;
1333
1334 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1335 "[BTC], %s(): index:%d\n",
1336 __func__, index);
1337
1338 if (!prptbuf) {
1339 pfwinfo->err[BTFRE_INVALID_INPUT]++;
1340 return 0;
1341 }
1342
1343 btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index];
1344 rpt_type = btc_prpt->type;
1345 rpt_len = le16_to_cpu(btc_prpt->len);
1346 rpt_content = btc_prpt->content;
1347
1348 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1349 "[BTC], %s(): rpt_type:%d\n",
1350 __func__, rpt_type);
1351
1352 rtw89_btc_fw_rpt_evnt_ver(rtwdev, &rpt_type);
1353
1354 switch (rpt_type) {
1355 case BTC_RPT_TYPE_CTRL:
1356 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
1357 prpt = &pfwinfo->rpt_ctrl.finfo;
1358 if (ver->fcxbtcrpt == 1) {
1359 pfinfo = &pfwinfo->rpt_ctrl.finfo.v1;
1360 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v1);
1361 } else if (ver->fcxbtcrpt == 4) {
1362 pfinfo = &pfwinfo->rpt_ctrl.finfo.v4;
1363 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v4);
1364 } else if (ver->fcxbtcrpt == 5) {
1365 pfinfo = &pfwinfo->rpt_ctrl.finfo.v5;
1366 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v5);
1367 } else if (ver->fcxbtcrpt == 105) {
1368 pfinfo = &pfwinfo->rpt_ctrl.finfo.v105;
1369 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v105);
1370 pcinfo->req_fver = 5;
1371 break;
1372 } else if (ver->fcxbtcrpt == 8) {
1373 pfinfo = &pfwinfo->rpt_ctrl.finfo.v8;
1374 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8);
1375 break;
1376 } else if (ver->fcxbtcrpt == 7) {
1377 pfinfo = &pfwinfo->rpt_ctrl.finfo.v7;
1378 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v7);
1379 break;
1380 } else {
1381 goto err;
1382 }
1383 pcinfo->req_fver = ver->fcxbtcrpt;
1384 break;
1385 case BTC_RPT_TYPE_TDMA:
1386 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
1387 if (ver->fcxtdma == 1) {
1388 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
1389 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1);
1390 } else if (ver->fcxtdma == 3 || ver->fcxtdma == 7) {
1391 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3;
1392 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3);
1393 } else {
1394 goto err;
1395 }
1396 pcinfo->req_fver = ver->fcxtdma;
1397 break;
1398 case BTC_RPT_TYPE_SLOT:
1399 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
1400 if (ver->fcxslots == 1) {
1401 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1;
1402 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v1);
1403 } else if (ver->fcxslots == 7) {
1404 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7;
1405 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v7);
1406 } else {
1407 goto err;
1408 }
1409 pcinfo->req_fver = ver->fcxslots;
1410 break;
1411 case BTC_RPT_TYPE_CYSTA:
1412 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
1413 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
1414 if (ver->fcxcysta == 2) {
1415 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
1416 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
1417 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v2);
1418 } else if (ver->fcxcysta == 3) {
1419 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
1420 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
1421 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v3);
1422 } else if (ver->fcxcysta == 4) {
1423 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
1424 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
1425 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v4);
1426 } else if (ver->fcxcysta == 5) {
1427 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
1428 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
1429 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v5);
1430 } else if (ver->fcxcysta == 7) {
1431 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
1432 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
1433 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v7);
1434 } else {
1435 goto err;
1436 }
1437 pcinfo->req_fver = ver->fcxcysta;
1438 break;
1439 case BTC_RPT_TYPE_STEP:
1440 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
1441 if (ver->fcxctrl != 7)
1442 trace_step = btc->ctrl.ctrl.trace_step;
1443
1444 if (ver->fcxstep == 2) {
1445 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v2;
1446 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) *
1447 trace_step +
1448 offsetof(struct rtw89_btc_fbtc_steps_v2, step);
1449 } else if (ver->fcxstep == 3) {
1450 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3;
1451 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) *
1452 trace_step +
1453 offsetof(struct rtw89_btc_fbtc_steps_v3, step);
1454 } else {
1455 goto err;
1456 }
1457 pcinfo->req_fver = ver->fcxstep;
1458 break;
1459 case BTC_RPT_TYPE_NULLSTA:
1460 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
1461 if (ver->fcxnullsta == 1) {
1462 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1;
1463 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v1);
1464 } else if (ver->fcxnullsta == 2) {
1465 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2;
1466 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v2);
1467 } else if (ver->fcxnullsta == 7) {
1468 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v7;
1469 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v7);
1470 } else {
1471 goto err;
1472 }
1473 pcinfo->req_fver = ver->fcxnullsta;
1474 break;
1475 case BTC_RPT_TYPE_MREG:
1476 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
1477 if (ver->fcxmreg == 1) {
1478 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
1479 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v1);
1480 } else if (ver->fcxmreg == 2) {
1481 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
1482 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v2);
1483 } else if (ver->fcxmreg == 7) {
1484 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
1485 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v7);
1486 } else {
1487 goto err;
1488 }
1489 pcinfo->req_fver = ver->fcxmreg;
1490 break;
1491 case BTC_RPT_TYPE_GPIO_DBG:
1492 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
1493 if (ver->fcxgpiodbg == 7) {
1494 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7;
1495 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7);
1496 } else {
1497 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1;
1498 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1);
1499 }
1500 pcinfo->req_fver = ver->fcxgpiodbg;
1501 break;
1502 case BTC_RPT_TYPE_BT_VER:
1503 pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
1504 if (ver->fcxbtver == 1) {
1505 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v1;
1506 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v1);
1507 } else if (ver->fcxbtver == 7) {
1508 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v7;
1509 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v7);
1510 }
1511 pcinfo->req_fver = ver->fcxbtver;
1512 break;
1513 case BTC_RPT_TYPE_BT_SCAN:
1514 pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
1515 if (ver->fcxbtscan == 1) {
1516 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1;
1517 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v1);
1518 } else if (ver->fcxbtscan == 2) {
1519 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2;
1520 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v2);
1521 } else if (ver->fcxbtscan == 7) {
1522 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v7;
1523 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v7);
1524 } else {
1525 goto err;
1526 }
1527 pcinfo->req_fver = ver->fcxbtscan;
1528 break;
1529 case BTC_RPT_TYPE_BT_AFH:
1530 pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
1531 if (ver->fcxbtafh == 1) {
1532 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1;
1533 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v1);
1534 } else if (ver->fcxbtafh == 2) {
1535 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2;
1536 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2);
1537 } else {
1538 goto err;
1539 }
1540 pcinfo->req_fver = ver->fcxbtafh;
1541 break;
1542 case BTC_RPT_TYPE_BT_DEVICE:
1543 pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
1544 pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo;
1545 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo);
1546 pcinfo->req_fver = ver->fcxbtdevinfo;
1547 break;
1548 default:
1549 pfwinfo->err[BTFRE_UNDEF_TYPE]++;
1550 return 0;
1551 }
1552
1553 pcinfo->rx_len = rpt_len;
1554 pcinfo->rx_cnt++;
1555
1556 if (rpt_len != pcinfo->req_len) {
1557 if (rpt_type < BTC_RPT_TYPE_MAX)
1558 pfwinfo->len_mismch |= (0x1 << rpt_type);
1559 else
1560 pfwinfo->len_mismch |= BIT(31);
1561 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1562 "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n",
1563 __func__, rpt_type, rpt_len, pcinfo->req_len);
1564
1565 pcinfo->valid = 0;
1566 return 0;
1567 } else if (!pfinfo || !rpt_content || !pcinfo->req_len) {
1568 pfwinfo->err[BTFRE_EXCEPTION]++;
1569 pcinfo->valid = 0;
1570 return 0;
1571 }
1572
1573 memcpy(pfinfo, rpt_content, pcinfo->req_len);
1574 pcinfo->valid = 1;
1575
1576 switch (rpt_type) {
1577 case BTC_RPT_TYPE_CTRL:
1578 if (ver->fcxbtcrpt == 1) {
1579 prpt->v1 = pfwinfo->rpt_ctrl.finfo.v1;
1580 btc->fwinfo.rpt_en_map = prpt->v1.rpt_enable;
1581 wl->ver_info.fw_coex = prpt->v1.wl_fw_coex_ver;
1582 wl->ver_info.fw = prpt->v1.wl_fw_ver;
1583 dm->wl_fw_cx_offload = !!prpt->v1.wl_fw_cx_offload;
1584
1585 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1586 pfwinfo->event[BTF_EVNT_RPT]);
1587
1588 /* To avoid I/O if WL LPS or power-off */
1589 if (wl->status.map.lps != BTC_LPS_RF_OFF &&
1590 !wl->status.map.rf_off) {
1591 rtwdev->chip->ops->btc_update_bt_cnt(rtwdev);
1592 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1593
1594 btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1595 rtw89_mac_get_plt_cnt(rtwdev,
1596 RTW89_MAC_0);
1597 }
1598 } else if (ver->fcxbtcrpt == 4) {
1599 prpt->v4 = pfwinfo->rpt_ctrl.finfo.v4;
1600 btc->fwinfo.rpt_en_map = le32_to_cpu(prpt->v4.rpt_info.en);
1601 wl->ver_info.fw_coex = le32_to_cpu(prpt->v4.wl_fw_info.cx_ver);
1602 wl->ver_info.fw = le32_to_cpu(prpt->v4.wl_fw_info.fw_ver);
1603 dm->wl_fw_cx_offload = !!le32_to_cpu(prpt->v4.wl_fw_info.cx_offload);
1604
1605 for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1606 memcpy(&dm->gnt.band[i], &prpt->v4.gnt_val[i],
1607 sizeof(dm->gnt.band[i]));
1608
1609 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1610 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_TX]);
1611 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1612 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_RX]);
1613 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1614 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_TX]);
1615 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1616 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_RX]);
1617 btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1618 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_POLLUTED]);
1619
1620 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1621 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1622 pfwinfo->event[BTF_EVNT_RPT]);
1623
1624 if (le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
1625 bt->rfk_info.map.timeout = 1;
1626 else
1627 bt->rfk_info.map.timeout = 0;
1628
1629 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1630 } else if (ver->fcxbtcrpt == 5) {
1631 prpt->v5 = pfwinfo->rpt_ctrl.finfo.v5;
1632 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v5.rpt_info.en);
1633 wl->ver_info.fw_coex = le32_to_cpu(prpt->v5.rpt_info.cx_ver);
1634 wl->ver_info.fw = le32_to_cpu(prpt->v5.rpt_info.fw_ver);
1635 dm->wl_fw_cx_offload = 0;
1636
1637 for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1638 memcpy(&dm->gnt.band[i], &prpt->v5.gnt_val[i][0],
1639 sizeof(dm->gnt.band[i]));
1640
1641 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1642 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_TX]);
1643 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1644 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_RX]);
1645 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1646 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_TX]);
1647 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1648 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_RX]);
1649 btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1650 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_POLLUTED]);
1651
1652 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1653 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1654 pfwinfo->event[BTF_EVNT_RPT]);
1655
1656 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1657 } else if (ver->fcxbtcrpt == 105) {
1658 prpt->v105 = pfwinfo->rpt_ctrl.finfo.v105;
1659 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v105.rpt_info.en);
1660 wl->ver_info.fw_coex = le32_to_cpu(prpt->v105.rpt_info.cx_ver);
1661 wl->ver_info.fw = le32_to_cpu(prpt->v105.rpt_info.fw_ver);
1662 dm->wl_fw_cx_offload = 0;
1663
1664 for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1665 memcpy(&dm->gnt.band[i], &prpt->v105.gnt_val[i][0],
1666 sizeof(dm->gnt.band[i]));
1667
1668 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1669 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_TX_V105]);
1670 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1671 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_RX_V105]);
1672 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1673 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_TX_V105]);
1674 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1675 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_RX_V105]);
1676 btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1677 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1678
1679 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1680 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1681 pfwinfo->event[BTF_EVNT_RPT]);
1682
1683 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1684 } else if (ver->fcxbtcrpt == 7) {
1685 prpt->v7 = pfwinfo->rpt_ctrl.finfo.v7;
1686 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v7.rpt_info.en);
1687 wl->ver_info.fw_coex = le32_to_cpu(prpt->v7.rpt_info.cx_ver);
1688 wl->ver_info.fw = le32_to_cpu(prpt->v7.rpt_info.fw_ver);
1689
1690 for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1691 memcpy(&dm->gnt.band[i], &prpt->v7.gnt_val[i][0],
1692 sizeof(dm->gnt.band[i]));
1693
1694 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1695 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_TX_V105]);
1696 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1697 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_RX_V105]);
1698 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1699 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_TX_V105]);
1700 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1701 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_RX_V105]);
1702
1703 val1 = le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1704 if (val1 > btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW])
1705 val1 -= btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]; /* diff */
1706
1707 btc->cx.cnt_bt[BTC_BCNT_POLUT_DIFF] = val1;
1708 btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW] =
1709 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1710
1711 val1 = pfwinfo->event[BTF_EVNT_RPT];
1712 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1713 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
1714 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
1715 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
1716 } else if (ver->fcxbtcrpt == 8) {
1717 prpt->v8 = pfwinfo->rpt_ctrl.finfo.v8;
1718 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v8.rpt_info.en);
1719 wl->ver_info.fw_coex = le32_to_cpu(prpt->v8.rpt_info.cx_ver);
1720 wl->ver_info.fw = le32_to_cpu(prpt->v8.rpt_info.fw_ver);
1721
1722 for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1723 memcpy(&dm->gnt.band[i], &prpt->v8.gnt_val[i][0],
1724 sizeof(dm->gnt.band[i]));
1725
1726 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1727 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_TX_V105]);
1728 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1729 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_RX_V105]);
1730 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1731 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_TX_V105]);
1732 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1733 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_RX_V105]);
1734
1735 val1 = le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1736 if (val1 > btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW])
1737 val1 -= btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]; /* diff */
1738
1739 btc->cx.cnt_bt[BTC_BCNT_POLUT_DIFF] = val1;
1740 btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW] =
1741 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1742
1743 val1 = pfwinfo->event[BTF_EVNT_RPT];
1744 if (((prpt->v8.rpt_len_max_h << 8) +
1745 prpt->v8.rpt_len_max_l) != ver->info_buf)
1746 dm->error.map.h2c_c2h_buffer_mismatch = true;
1747 else
1748 dm->error.map.h2c_c2h_buffer_mismatch = false;
1749
1750 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1751 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
1752 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
1753 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
1754 } else {
1755 goto err;
1756 }
1757 break;
1758 case BTC_RPT_TYPE_TDMA:
1759 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1760 "[BTC], %s(): check %d %zu\n", __func__,
1761 BTC_DCNT_TDMA_NONSYNC,
1762 sizeof(dm->tdma_now));
1763 if (ver->fcxtdma == 1)
1764 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
1765 memcmp(&dm->tdma_now,
1766 &pfwinfo->rpt_fbtc_tdma.finfo.v1,
1767 sizeof(dm->tdma_now)));
1768 else if (ver->fcxtdma == 3 || ver->fcxtdma == 7)
1769 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
1770 memcmp(&dm->tdma_now,
1771 &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma,
1772 sizeof(dm->tdma_now)));
1773 else
1774 goto err;
1775 break;
1776 case BTC_RPT_TYPE_SLOT:
1777 if (ver->fcxslots == 7) {
1778 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1779 "[BTC], %s(): check %d %zu\n",
1780 __func__, BTC_DCNT_SLOT_NONSYNC,
1781 sizeof(dm->slot_now.v7));
1782 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
1783 memcmp(dm->slot_now.v7,
1784 pfwinfo->rpt_fbtc_slots.finfo.v7.slot,
1785 sizeof(dm->slot_now.v7)));
1786 } else if (ver->fcxslots == 1) {
1787 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1788 "[BTC], %s(): check %d %zu\n",
1789 __func__, BTC_DCNT_SLOT_NONSYNC,
1790 sizeof(dm->slot_now.v1));
1791 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
1792 memcmp(dm->slot_now.v1,
1793 pfwinfo->rpt_fbtc_slots.finfo.v1.slot,
1794 sizeof(dm->slot_now.v1)));
1795 }
1796 break;
1797 case BTC_RPT_TYPE_CYSTA:
1798 if (ver->fcxcysta == 2) {
1799 if (le16_to_cpu(pcysta->v2.cycles) < BTC_CYSTA_CHK_PERIOD)
1800 break;
1801 /* Check Leak-AP */
1802 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) != 0 &&
1803 le32_to_cpu(pcysta->v2.leakrx_cnt) != 0 && dm->tdma_now.rxflctrl) {
1804 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) <
1805 BTC_LEAK_AP_TH * le32_to_cpu(pcysta->v2.leakrx_cnt))
1806 dm->leak_ap = 1;
1807 }
1808
1809 /* Check diff time between WL slot and W1/E2G slot */
1810 if (dm->tdma_now.type == CXTDMA_OFF &&
1811 dm->tdma_now.ext_ctrl == CXECTL_EXT) {
1812 if (ver->fcxslots == 1)
1813 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_E2G].dur);
1814 else if (ver->fcxslots == 7)
1815 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_E2G].dur);
1816 } else {
1817 if (ver->fcxslots == 1)
1818 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1819 else if (ver->fcxslots == 7)
1820 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1821 }
1822
1823 if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) {
1824 diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set;
1825 _chk_btc_err(rtwdev,
1826 BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1827 }
1828
1829 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1830 le32_to_cpu(pcysta->v2.slot_cnt[CXST_W1]));
1831 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1832 le32_to_cpu(pcysta->v2.slot_cnt[CXST_B1]));
1833 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1834 le16_to_cpu(pcysta->v2.cycles));
1835 } else if (ver->fcxcysta == 3) {
1836 if (le16_to_cpu(pcysta->v3.cycles) < BTC_CYSTA_CHK_PERIOD)
1837 break;
1838
1839 cnt_leak_slot = le32_to_cpu(pcysta->v3.slot_cnt[CXST_LK]);
1840 cnt_rx_imr = le32_to_cpu(pcysta->v3.leak_slot.cnt_rximr);
1841
1842 /* Check Leak-AP */
1843 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
1844 dm->tdma_now.rxflctrl) {
1845 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
1846 dm->leak_ap = 1;
1847 }
1848
1849 /* Check diff time between real WL slot and W1 slot */
1850 if (dm->tdma_now.type == CXTDMA_OFF) {
1851 if (ver->fcxslots == 1)
1852 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1853 else if (ver->fcxslots == 7)
1854 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1855 wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]);
1856 if (wl_slot_real > wl_slot_set) {
1857 diff_t = wl_slot_real - wl_slot_set;
1858 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1859 }
1860 }
1861
1862 /* Check diff time between real BT slot and EBT/E5G slot */
1863 if (dm->tdma_now.type == CXTDMA_OFF &&
1864 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
1865 btc->bt_req_len != 0) {
1866 bt_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_BT]);
1867 if (btc->bt_req_len > bt_slot_real) {
1868 diff_t = btc->bt_req_len - bt_slot_real;
1869 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
1870 }
1871 }
1872
1873 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1874 le32_to_cpu(pcysta->v3.slot_cnt[CXST_W1]));
1875 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
1876 le32_to_cpu(pcysta->v3.slot_cnt[CXST_B1]));
1877 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1878 le16_to_cpu(pcysta->v3.cycles));
1879 } else if (ver->fcxcysta == 4) {
1880 if (le16_to_cpu(pcysta->v4.cycles) < BTC_CYSTA_CHK_PERIOD)
1881 break;
1882
1883 cnt_leak_slot = le16_to_cpu(pcysta->v4.slot_cnt[CXST_LK]);
1884 cnt_rx_imr = le32_to_cpu(pcysta->v4.leak_slot.cnt_rximr);
1885
1886 /* Check Leak-AP */
1887 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
1888 dm->tdma_now.rxflctrl) {
1889 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
1890 dm->leak_ap = 1;
1891 }
1892
1893 /* Check diff time between real WL slot and W1 slot */
1894 if (dm->tdma_now.type == CXTDMA_OFF) {
1895 if (ver->fcxslots == 1)
1896 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1897 else if (ver->fcxslots == 7)
1898 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1899 wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]);
1900 if (wl_slot_real > wl_slot_set) {
1901 diff_t = wl_slot_real - wl_slot_set;
1902 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1903 }
1904 }
1905
1906 /* Check diff time between real BT slot and EBT/E5G slot */
1907 if (dm->tdma_now.type == CXTDMA_OFF &&
1908 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
1909 btc->bt_req_len != 0) {
1910 bt_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_BT]);
1911
1912 if (btc->bt_req_len > bt_slot_real) {
1913 diff_t = btc->bt_req_len - bt_slot_real;
1914 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
1915 }
1916 }
1917
1918 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1919 le16_to_cpu(pcysta->v4.slot_cnt[CXST_W1]));
1920 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
1921 le16_to_cpu(pcysta->v4.slot_cnt[CXST_B1]));
1922 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1923 le16_to_cpu(pcysta->v4.cycles));
1924 } else if (ver->fcxcysta == 5) {
1925 if (dm->fddt_train == BTC_FDDT_ENABLE)
1926 break;
1927 cnt_leak_slot = le16_to_cpu(pcysta->v5.slot_cnt[CXST_LK]);
1928 cnt_rx_imr = le32_to_cpu(pcysta->v5.leak_slot.cnt_rximr);
1929
1930 /* Check Leak-AP */
1931 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
1932 dm->tdma_now.rxflctrl) {
1933 if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD &&
1934 cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
1935 dm->leak_ap = 1;
1936 }
1937
1938 /* Check diff time between real WL slot and W1 slot */
1939 if (dm->tdma_now.type == CXTDMA_OFF) {
1940 if (ver->fcxslots == 1)
1941 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1942 else if (ver->fcxslots == 7)
1943 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1944 wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]);
1945
1946 if (wl_slot_real > wl_slot_set)
1947 diff_t = wl_slot_real - wl_slot_set;
1948 else
1949 diff_t = wl_slot_set - wl_slot_real;
1950 }
1951 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1952
1953 /* Check diff time between real BT slot and EBT/E5G slot */
1954 bt_slot_set = btc->bt_req_len;
1955 bt_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_BT]);
1956 diff_t = 0;
1957 if (dm->tdma_now.type == CXTDMA_OFF &&
1958 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
1959 bt_slot_set != 0) {
1960 if (bt_slot_set > bt_slot_real)
1961 diff_t = bt_slot_set - bt_slot_real;
1962 else
1963 diff_t = bt_slot_real - bt_slot_set;
1964 }
1965
1966 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
1967 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
1968 le16_to_cpu(pcysta->v5.slot_cnt[CXST_E2G]));
1969 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1970 le16_to_cpu(pcysta->v5.slot_cnt[CXST_W1]));
1971 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
1972 le16_to_cpu(pcysta->v5.slot_cnt[CXST_B1]));
1973 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1974 le16_to_cpu(pcysta->v5.cycles));
1975 } else if (ver->fcxcysta == 7) {
1976 if (dm->fddt_train == BTC_FDDT_ENABLE)
1977 break;
1978
1979 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
1980
1981 if (dm->tdma_now.type != CXTDMA_OFF) {
1982 /* Check diff time between real WL slot and W1 slot */
1983 val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_WL]);
1984 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, val16);
1985
1986 /* Check Leak-AP */
1987 val1 = le32_to_cpu(pcysta->v7.leak_slot.cnt_rximr) *
1988 BTC_LEAK_AP_TH;
1989 val2 = le16_to_cpu(pcysta->v7.slot_cnt[CXST_LK]);
1990
1991 val16 = le16_to_cpu(pcysta->v7.cycles);
1992 if (dm->tdma_now.rxflctrl &&
1993 val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
1994 dm->leak_ap = 1;
1995 } else if (dm->tdma_now.ext_ctrl == CXECTL_EXT) {
1996 val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_BT]);
1997 /* Check diff between real BT slot and EBT/E5G slot */
1998 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, val16);
1999
2000 /* Check bt slot length for P2P mode*/
2001 val1 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt_timeout) *
2002 BTC_SLOT_REQ_TH;
2003 val2 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt);
2004
2005 val16 = le16_to_cpu(pcysta->v7.cycles);
2006 if (val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
2007 dm->slot_req_more = 1;
2008 else if (bt->link_info.status.map.connect == 0)
2009 dm->slot_req_more = 0;
2010 }
2011
2012 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
2013 le16_to_cpu(pcysta->v7.slot_cnt[CXST_E2G]));
2014 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2015 le16_to_cpu(pcysta->v7.slot_cnt[CXST_W1]));
2016 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2017 le16_to_cpu(pcysta->v7.slot_cnt[CXST_B1]));
2018
2019 /* "BT_SLOT_FLOOD" error-check MUST before "CYCLE_HANG" */
2020 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_FLOOD,
2021 le16_to_cpu(pcysta->v7.cycles));
2022 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2023 le16_to_cpu(pcysta->v7.cycles));
2024 } else {
2025 goto err;
2026 }
2027 break;
2028 case BTC_RPT_TYPE_MREG:
2029 if (ver->fcxmreg == 7)
2030 break;
2031 _get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX_MON, &val);
2032 if (dm->wl_btg_rx == BTC_BTGCTRL_BB_GNT_FWCTRL)
2033 dm->wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_FWCTRL;
2034 else
2035 dm->wl_btg_rx_rb = val;
2036
2037 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC_MON, &val);
2038 if (dm->wl_pre_agc == BTC_PREAGC_BB_FWCTRL)
2039 dm->wl_pre_agc_rb = BTC_PREAGC_BB_FWCTRL;
2040 else
2041 dm->wl_pre_agc_rb = val;
2042 break;
2043 case BTC_RPT_TYPE_BT_VER:
2044 case BTC_RPT_TYPE_BT_SCAN:
2045 case BTC_RPT_TYPE_BT_AFH:
2046 case BTC_RPT_TYPE_BT_DEVICE:
2047 _update_bt_report(rtwdev, rpt_type, pfinfo);
2048 break;
2049 }
2050 return (rpt_len + BTC_RPT_HDR_SIZE);
2051
2052 err:
2053 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2054 "[BTC], %s(): Undefined version for type=%d\n", __func__, rpt_type);
2055 return 0;
2056 }
2057
_parse_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * pbuf,u32 buf_len)2058 static void _parse_btc_report(struct rtw89_dev *rtwdev,
2059 struct rtw89_btc_btf_fwinfo *pfwinfo,
2060 u8 *pbuf, u32 buf_len)
2061 {
2062 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
2063 struct rtw89_btc_prpt *btc_prpt = NULL;
2064 u32 index = 0, rpt_len = 0;
2065
2066 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2067 "[BTC], %s(): buf_len:%d\n",
2068 __func__, buf_len);
2069
2070 while (pbuf) {
2071 btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index];
2072 if (index + 2 >= ver->info_buf)
2073 break;
2074 /* At least 3 bytes: type(1) & len(2) */
2075 rpt_len = le16_to_cpu(btc_prpt->len);
2076 if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len)
2077 break;
2078
2079 rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index);
2080 if (!rpt_len)
2081 break;
2082 index += rpt_len;
2083 }
2084 }
2085
2086 #define BTC_TLV_HDR_LEN 2
2087 #define BTC_TLV_HDR_LEN_V7 3
2088
_append_tdma(struct rtw89_dev * rtwdev)2089 static void _append_tdma(struct rtw89_dev *rtwdev)
2090 {
2091 struct rtw89_btc *btc = &rtwdev->btc;
2092 const struct rtw89_btc_ver *ver = btc->ver;
2093 struct rtw89_btc_dm *dm = &btc->dm;
2094 struct rtw89_btc_btf_tlv *tlv;
2095 struct rtw89_btc_btf_tlv_v7 *tlv_v7;
2096 struct rtw89_btc_fbtc_tdma *v;
2097 struct rtw89_btc_fbtc_tdma_v3 *v3;
2098 u16 len = btc->policy_len;
2099
2100 if (!btc->update_policy_force &&
2101 !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) {
2102 rtw89_debug(rtwdev,
2103 RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n",
2104 __func__);
2105 return;
2106 }
2107
2108 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
2109 tlv->type = CXPOLICY_TDMA;
2110 if (ver->fcxtdma == 1) {
2111 v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0];
2112 tlv->len = sizeof(*v);
2113 *v = dm->tdma;
2114 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
2115 } else if (ver->fcxtdma == 7) {
2116 tlv_v7 = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2117 tlv_v7->len = sizeof(dm->tdma);
2118 tlv_v7->ver = ver->fcxtdma;
2119 tlv_v7->type = CXPOLICY_TDMA;
2120 memcpy(tlv_v7->val, &dm->tdma, tlv_v7->len);
2121 btc->policy_len += BTC_TLV_HDR_LEN_V7 + tlv_v7->len;
2122 } else {
2123 tlv->len = sizeof(*v3);
2124 v3 = (struct rtw89_btc_fbtc_tdma_v3 *)&tlv->val[0];
2125 v3->fver = ver->fcxtdma;
2126 v3->tdma = dm->tdma;
2127 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v3);
2128 }
2129
2130 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2131 "[BTC], %s(): type:%d, rxflctrl=%d, txpause=%d, wtgle_n=%d, leak_n=%d, ext_ctrl=%d\n",
2132 __func__, dm->tdma.type, dm->tdma.rxflctrl,
2133 dm->tdma.txpause, dm->tdma.wtgle_n, dm->tdma.leak_n,
2134 dm->tdma.ext_ctrl);
2135 }
2136
_append_slot_v1(struct rtw89_dev * rtwdev)2137 static void _append_slot_v1(struct rtw89_dev *rtwdev)
2138 {
2139 struct rtw89_btc *btc = &rtwdev->btc;
2140 struct rtw89_btc_dm *dm = &btc->dm;
2141 struct rtw89_btc_btf_tlv *tlv = NULL;
2142 struct btc_fbtc_1slot *v = NULL;
2143 u16 len = 0;
2144 u8 i, cnt = 0;
2145
2146 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2147 "[BTC], %s(): A:btc->policy_len = %d\n",
2148 __func__, btc->policy_len);
2149
2150 for (i = 0; i < CXST_MAX; i++) {
2151 if (!btc->update_policy_force &&
2152 !memcmp(&dm->slot.v1[i], &dm->slot_now.v1[i],
2153 sizeof(dm->slot.v1[i])))
2154 continue;
2155
2156 len = btc->policy_len;
2157
2158 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
2159 v = (struct btc_fbtc_1slot *)&tlv->val[0];
2160 tlv->type = CXPOLICY_SLOT;
2161 tlv->len = sizeof(*v);
2162
2163 v->fver = btc->ver->fcxslots;
2164 v->sid = i;
2165 v->slot = dm->slot.v1[i];
2166
2167 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2168 "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n",
2169 __func__, i, dm->slot.v1[i].dur, dm->slot.v1[i].cxtbl,
2170 dm->slot.v1[i].cxtype);
2171 cnt++;
2172
2173 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
2174 }
2175
2176 if (cnt > 0)
2177 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2178 "[BTC], %s(): slot update (cnt=%d)!!\n",
2179 __func__, cnt);
2180 }
2181
_append_slot_v7(struct rtw89_dev * rtwdev)2182 static void _append_slot_v7(struct rtw89_dev *rtwdev)
2183 {
2184 struct rtw89_btc_btf_tlv_v7 *tlv = NULL;
2185 struct rtw89_btc *btc = &rtwdev->btc;
2186 struct rtw89_btc_dm *dm = &btc->dm;
2187 u8 i, cnt = 0;
2188 u16 len;
2189
2190 for (i = 0; i < CXST_MAX; i++) {
2191 if (!btc->update_policy_force &&
2192 !memcmp(&dm->slot.v7[i], &dm->slot_now.v7[i],
2193 sizeof(dm->slot.v7[i])))
2194 continue;
2195
2196 len = btc->policy_len;
2197
2198 if (!tlv) {
2199 if ((len + BTC_TLV_HDR_LEN_V7) > RTW89_BTC_POLICY_MAXLEN) {
2200 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2201 "[BTC], %s(): buff overflow!\n", __func__);
2202 break;
2203 }
2204
2205 tlv = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2206 tlv->type = CXPOLICY_SLOT;
2207 tlv->ver = btc->ver->fcxslots;
2208 tlv->len = sizeof(dm->slot.v7[0]) + BTC_TLV_SLOT_ID_LEN_V7;
2209 len += BTC_TLV_HDR_LEN_V7;
2210 }
2211
2212 if ((len + (u16)tlv->len) > RTW89_BTC_POLICY_MAXLEN) {
2213 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2214 "[BTC], %s(): buff overflow!\n", __func__);
2215 break;
2216 }
2217
2218 btc->policy[len] = i; /* slot-id */
2219 memcpy(&btc->policy[len + 1], &dm->slot.v7[i],
2220 sizeof(dm->slot.v7[0]));
2221 len += tlv->len;
2222
2223 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2224 "[BTC], %s: policy_len=%d, slot-%d: dur=%d, type=%d, table=0x%08x\n",
2225 __func__, btc->policy_len, i, dm->slot.v7[i].dur,
2226 dm->slot.v7[i].cxtype, dm->slot.v7[i].cxtbl);
2227 cnt++;
2228 btc->policy_len = len; /* update total length */
2229 }
2230
2231 if (cnt > 0)
2232 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2233 "[BTC], %s: slot update (cnt=%d, len=%d)!!\n",
2234 __func__, cnt, btc->policy_len);
2235 }
2236
_append_slot(struct rtw89_dev * rtwdev)2237 static void _append_slot(struct rtw89_dev *rtwdev)
2238 {
2239 struct rtw89_btc *btc = &rtwdev->btc;
2240
2241 if (btc->ver->fcxslots == 7)
2242 _append_slot_v7(rtwdev);
2243 else
2244 _append_slot_v1(rtwdev);
2245 }
2246
rtw89_btc_fw_rpt_ver(struct rtw89_dev * rtwdev,u32 rpt_map)2247 static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map)
2248 {
2249 struct rtw89_btc *btc = &rtwdev->btc;
2250 const struct rtw89_btc_ver *ver = btc->ver;
2251 u32 bit_map = 0;
2252
2253 switch (rpt_map) {
2254 case RPT_EN_TDMA:
2255 bit_map = BIT(0);
2256 break;
2257 case RPT_EN_CYCLE:
2258 bit_map = BIT(1);
2259 break;
2260 case RPT_EN_MREG:
2261 bit_map = BIT(2);
2262 break;
2263 case RPT_EN_BT_VER_INFO:
2264 bit_map = BIT(3);
2265 break;
2266 case RPT_EN_BT_SCAN_INFO:
2267 bit_map = BIT(4);
2268 break;
2269 case RPT_EN_BT_DEVICE_INFO:
2270 switch (ver->frptmap) {
2271 case 0:
2272 case 1:
2273 case 2:
2274 bit_map = BIT(6);
2275 break;
2276 case 3:
2277 bit_map = BIT(5);
2278 break;
2279 default:
2280 break;
2281 }
2282 break;
2283 case RPT_EN_BT_AFH_MAP:
2284 switch (ver->frptmap) {
2285 case 0:
2286 case 1:
2287 case 2:
2288 bit_map = BIT(5);
2289 break;
2290 case 3:
2291 bit_map = BIT(6);
2292 break;
2293 default:
2294 break;
2295 }
2296 break;
2297 case RPT_EN_BT_AFH_MAP_LE:
2298 switch (ver->frptmap) {
2299 case 2:
2300 bit_map = BIT(8);
2301 break;
2302 case 3:
2303 bit_map = BIT(7);
2304 break;
2305 default:
2306 break;
2307 }
2308 break;
2309 case RPT_EN_FW_STEP_INFO:
2310 switch (ver->frptmap) {
2311 case 1:
2312 case 2:
2313 bit_map = BIT(7);
2314 break;
2315 case 3:
2316 bit_map = BIT(8);
2317 break;
2318 default:
2319 break;
2320 }
2321 break;
2322 case RPT_EN_TEST:
2323 bit_map = BIT(31);
2324 break;
2325 case RPT_EN_WL_ALL:
2326 switch (ver->frptmap) {
2327 case 0:
2328 case 1:
2329 case 2:
2330 bit_map = GENMASK(2, 0);
2331 break;
2332 case 3:
2333 bit_map = GENMASK(2, 0) | BIT(8);
2334 break;
2335 default:
2336 break;
2337 }
2338 break;
2339 case RPT_EN_BT_ALL:
2340 switch (ver->frptmap) {
2341 case 0:
2342 case 1:
2343 bit_map = GENMASK(6, 3);
2344 break;
2345 case 2:
2346 bit_map = GENMASK(6, 3) | BIT(8);
2347 break;
2348 case 3:
2349 bit_map = GENMASK(7, 3);
2350 break;
2351 default:
2352 break;
2353 }
2354 break;
2355 case RPT_EN_ALL:
2356 switch (ver->frptmap) {
2357 case 0:
2358 bit_map = GENMASK(6, 0);
2359 break;
2360 case 1:
2361 bit_map = GENMASK(7, 0);
2362 break;
2363 case 2:
2364 case 3:
2365 bit_map = GENMASK(8, 0);
2366 break;
2367 default:
2368 break;
2369 }
2370 break;
2371 case RPT_EN_MONITER:
2372 switch (ver->frptmap) {
2373 case 0:
2374 case 1:
2375 bit_map = GENMASK(6, 2);
2376 break;
2377 case 2:
2378 bit_map = GENMASK(6, 2) | BIT(8);
2379 break;
2380 case 3:
2381 bit_map = GENMASK(8, 2);
2382 break;
2383 default:
2384 break;
2385 }
2386 break;
2387 }
2388
2389 return bit_map;
2390 }
2391
rtw89_btc_fw_set_slots(struct rtw89_dev * rtwdev)2392 static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev)
2393 {
2394 struct rtw89_btc *btc = &rtwdev->btc;
2395 const struct rtw89_btc_ver *ver = btc->ver;
2396 struct rtw89_btc_btf_tlv_v7 *tlv_v7 = NULL;
2397 struct rtw89_btc_btf_set_slot_table *tbl;
2398 struct rtw89_btc_dm *dm = &btc->dm;
2399 u16 n, len;
2400
2401 if (ver->fcxslots == 7) {
2402 len = sizeof(*tlv_v7) + sizeof(dm->slot.v7);
2403 tlv_v7 = kmalloc(len, GFP_KERNEL);
2404 if (!tlv_v7)
2405 return;
2406
2407 tlv_v7->type = SET_SLOT_TABLE;
2408 tlv_v7->ver = ver->fcxslots;
2409 tlv_v7->len = ARRAY_SIZE(dm->slot.v7);
2410 memcpy(tlv_v7->val, dm->slot.v7, sizeof(dm->slot.v7));
2411
2412 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, (u8 *)tlv_v7, len);
2413
2414 kfree(tlv_v7);
2415 } else {
2416 n = struct_size(tbl, tbls, CXST_MAX);
2417 tbl = kmalloc(n, GFP_KERNEL);
2418 if (!tbl)
2419 return;
2420
2421 tbl->fver = BTF_SET_SLOT_TABLE_VER;
2422 tbl->tbl_num = CXST_MAX;
2423 memcpy(tbl->tbls, dm->slot.v1, flex_array_size(tbl, tbls, CXST_MAX));
2424
2425 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
2426
2427 kfree(tbl);
2428 }
2429 }
2430
rtw89_btc_fw_en_rpt(struct rtw89_dev * rtwdev,u32 rpt_map,bool rpt_state)2431 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
2432 u32 rpt_map, bool rpt_state)
2433 {
2434 struct rtw89_btc *btc = &rtwdev->btc;
2435 struct rtw89_btc_wl_smap *wl_smap = &btc->cx.wl.status.map;
2436 struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo;
2437 union rtw89_fbtc_rtp_ctrl r;
2438 u32 val, bit_map;
2439 int ret;
2440
2441 if ((wl_smap->rf_off || wl_smap->lps != BTC_LPS_OFF) && rpt_state != 0)
2442 return;
2443
2444 bit_map = rtw89_btc_fw_rpt_ver(rtwdev, rpt_map);
2445
2446 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2447 "[BTC], %s(): rpt_map=%x, rpt_state=%x\n",
2448 __func__, rpt_map, rpt_state);
2449
2450 if (rpt_state)
2451 val = fwinfo->rpt_en_map | bit_map;
2452 else
2453 val = fwinfo->rpt_en_map & ~bit_map;
2454
2455 if (val == fwinfo->rpt_en_map)
2456 return;
2457
2458 if (btc->ver->fcxbtcrpt == 7 || btc->ver->fcxbtcrpt == 8) {
2459 r.v8.type = SET_REPORT_EN;
2460 r.v8.fver = btc->ver->fcxbtcrpt;
2461 r.v8.len = sizeof(r.v8.map);
2462 r.v8.map = cpu_to_le32(val);
2463 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v8,
2464 sizeof(r.v8));
2465 } else {
2466 if (btc->ver->fcxbtcrpt == 105)
2467 r.v1.fver = 5;
2468 else
2469 r.v1.fver = btc->ver->fcxbtcrpt;
2470 r.v1.enable = cpu_to_le32(val);
2471 r.v1.para = cpu_to_le32(rpt_state);
2472 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v1,
2473 sizeof(r.v1));
2474 }
2475
2476 if (!ret)
2477 fwinfo->rpt_en_map = val;
2478 }
2479
btc_fw_set_monreg(struct rtw89_dev * rtwdev)2480 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
2481 {
2482 const struct rtw89_chip_info *chip = rtwdev->chip;
2483 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
2484 struct rtw89_btc_btf_set_mon_reg_v1 *v1 = NULL;
2485 struct rtw89_btc_btf_set_mon_reg_v7 *v7 = NULL;
2486 u8 i, n, ulen, cxmreg_max;
2487 u16 sz = 0;
2488
2489 n = chip->mon_reg_num;
2490 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2491 "[BTC], %s(): mon_reg_num=%d\n", __func__, n);
2492
2493 if (ver->fcxmreg == 1)
2494 cxmreg_max = CXMREG_MAX;
2495 else
2496 cxmreg_max = CXMREG_MAX_V2;
2497
2498 if (n > cxmreg_max) {
2499 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2500 "[BTC], %s(): mon reg count %d > %d\n",
2501 __func__, n, cxmreg_max);
2502 return;
2503 }
2504
2505 ulen = sizeof(struct rtw89_btc_fbtc_mreg);
2506
2507 if (ver->fcxmreg == 7) {
2508 sz = struct_size(v7, regs, n);
2509 v7 = kmalloc(sz, GFP_KERNEL);
2510 if (!v7)
2511 return;
2512 v7->type = RPT_EN_MREG;
2513 v7->fver = ver->fcxmreg;
2514 v7->len = n;
2515 for (i = 0; i < n; i++) {
2516 v7->regs[i].type = chip->mon_reg[i].type;
2517 v7->regs[i].bytes = chip->mon_reg[i].bytes;
2518 v7->regs[i].offset = chip->mon_reg[i].offset;
2519 }
2520
2521 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v7, sz);
2522 kfree(v7);
2523 } else {
2524 sz = struct_size(v1, regs, n);
2525 v1 = kmalloc(sz, GFP_KERNEL);
2526 if (!v1)
2527 return;
2528 v1->fver = ver->fcxmreg;
2529 v1->reg_num = n;
2530 memcpy(v1->regs, chip->mon_reg, flex_array_size(v1, regs, n));
2531
2532 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v1, sz);
2533 kfree(v1);
2534 }
2535
2536 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2537 "[BTC], %s(): sz=%d ulen=%d n=%d\n",
2538 __func__, sz, ulen, n);
2539
2540 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
2541 }
2542
_update_dm_step(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason_or_action)2543 static void _update_dm_step(struct rtw89_dev *rtwdev,
2544 enum btc_reason_and_action reason_or_action)
2545 {
2546 struct rtw89_btc *btc = &rtwdev->btc;
2547 struct rtw89_btc_dm *dm = &btc->dm;
2548
2549 /* use ring-structure to store dm step */
2550 dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action;
2551 dm->dm_step.step_pos++;
2552
2553 if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) {
2554 dm->dm_step.step_pos = 0;
2555 dm->dm_step.step_ov = true;
2556 }
2557 }
2558
_fw_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)2559 static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
2560 enum btc_reason_and_action action)
2561 {
2562 struct rtw89_btc *btc = &rtwdev->btc;
2563 struct rtw89_btc_dm *dm = &btc->dm;
2564 int ret;
2565
2566 dm->run_action = action;
2567
2568 _update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT);
2569 _update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT);
2570
2571 btc->policy_len = 0;
2572 btc->policy_type = policy_type;
2573
2574 _append_tdma(rtwdev);
2575 _append_slot(rtwdev);
2576
2577 if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN)
2578 return;
2579
2580 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2581 "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n",
2582 __func__, action, policy_type, btc->policy_len);
2583
2584 if (dm->tdma.rxflctrl == CXFLC_NULLP ||
2585 dm->tdma.rxflctrl == CXFLC_QOSNULL)
2586 btc->lps = 1;
2587 else
2588 btc->lps = 0;
2589
2590 if (btc->lps == 1)
2591 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
2592
2593 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY,
2594 btc->policy, btc->policy_len);
2595 if (!ret) {
2596 memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now));
2597 if (btc->ver->fcxslots == 7)
2598 memcpy(&dm->slot_now.v7, &dm->slot.v7, sizeof(dm->slot_now.v7));
2599 else
2600 memcpy(&dm->slot_now.v1, &dm->slot.v1, sizeof(dm->slot_now.v1));
2601 }
2602
2603 if (btc->update_policy_force)
2604 btc->update_policy_force = false;
2605
2606 if (btc->lps == 0)
2607 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
2608 }
2609
_fw_set_drv_info(struct rtw89_dev * rtwdev,u8 type)2610 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 type)
2611 {
2612 struct rtw89_btc *btc = &rtwdev->btc;
2613 const struct rtw89_btc_ver *ver = btc->ver;
2614 struct rtw89_btc_dm *dm = &btc->dm;
2615 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2616 struct rtw89_btc_rf_trx_para rf_para = dm->rf_trx_para;
2617
2618 switch (type) {
2619 case CXDRVINFO_INIT:
2620 if (ver->fcxinit == 7)
2621 rtw89_fw_h2c_cxdrv_init_v7(rtwdev, type);
2622 else
2623 rtw89_fw_h2c_cxdrv_init(rtwdev, type);
2624 break;
2625 case CXDRVINFO_ROLE:
2626 if (ver->fwlrole == 0)
2627 rtw89_fw_h2c_cxdrv_role(rtwdev, type);
2628 else if (ver->fwlrole == 1)
2629 rtw89_fw_h2c_cxdrv_role_v1(rtwdev, type);
2630 else if (ver->fwlrole == 2)
2631 rtw89_fw_h2c_cxdrv_role_v2(rtwdev, type);
2632 else if (ver->fwlrole == 7)
2633 rtw89_fw_h2c_cxdrv_role_v7(rtwdev, type);
2634 else if (ver->fwlrole == 8)
2635 rtw89_fw_h2c_cxdrv_role_v8(rtwdev, type);
2636 break;
2637 case CXDRVINFO_CTRL:
2638 if (ver->drvinfo_type == 1)
2639 type = 2;
2640
2641 if (ver->fcxctrl == 7)
2642 rtw89_fw_h2c_cxdrv_ctrl_v7(rtwdev, type);
2643 else
2644 rtw89_fw_h2c_cxdrv_ctrl(rtwdev, type);
2645 break;
2646 case CXDRVINFO_TRX:
2647 if (ver->drvinfo_type == 1)
2648 type = 3;
2649
2650 dm->trx_info.tx_power = u32_get_bits(rf_para.wl_tx_power,
2651 RTW89_BTC_WL_DEF_TX_PWR);
2652 dm->trx_info.rx_gain = u32_get_bits(rf_para.wl_rx_gain,
2653 RTW89_BTC_WL_DEF_TX_PWR);
2654 dm->trx_info.bt_tx_power = u32_get_bits(rf_para.bt_tx_power,
2655 RTW89_BTC_WL_DEF_TX_PWR);
2656 dm->trx_info.bt_rx_gain = u32_get_bits(rf_para.bt_rx_gain,
2657 RTW89_BTC_WL_DEF_TX_PWR);
2658 dm->trx_info.cn = wl->cn_report;
2659 dm->trx_info.nhm = wl->nhm.pwr;
2660 rtw89_fw_h2c_cxdrv_trx(rtwdev, type);
2661 break;
2662 case CXDRVINFO_RFK:
2663 if (ver->drvinfo_type == 1)
2664 return;
2665
2666 rtw89_fw_h2c_cxdrv_rfk(rtwdev, type);
2667 break;
2668 case CXDRVINFO_TXPWR:
2669 case CXDRVINFO_FDDT:
2670 case CXDRVINFO_MLO:
2671 case CXDRVINFO_OSI:
2672 default:
2673 break;
2674 }
2675 }
2676
2677 static
btc_fw_event(struct rtw89_dev * rtwdev,u8 evt_id,void * data,u32 len)2678 void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len)
2679 {
2680 struct rtw89_btc *btc = &rtwdev->btc;
2681 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
2682
2683 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2684 "[BTC], %s(): evt_id:%d len:%d\n",
2685 __func__, evt_id, len);
2686
2687 if (!len || !data)
2688 return;
2689
2690 switch (evt_id) {
2691 case BTF_EVNT_RPT:
2692 _parse_btc_report(rtwdev, pfwinfo, data, len);
2693 break;
2694 default:
2695 break;
2696 }
2697 }
2698
_set_gnt(struct rtw89_dev * rtwdev,u8 phy_map,u8 wl_state,u8 bt_state)2699 static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map, u8 wl_state, u8 bt_state)
2700 {
2701 struct rtw89_btc *btc = &rtwdev->btc;
2702 struct rtw89_btc_dm *dm = &btc->dm;
2703 struct rtw89_mac_ax_gnt *g = dm->gnt.band;
2704 u8 i;
2705
2706 if (phy_map > BTC_PHY_ALL)
2707 return;
2708
2709 for (i = 0; i < RTW89_PHY_MAX; i++) {
2710 if (!(phy_map & BIT(i)))
2711 continue;
2712
2713 switch (wl_state) {
2714 case BTC_GNT_HW:
2715 g[i].gnt_wl_sw_en = 0;
2716 g[i].gnt_wl = 0;
2717 break;
2718 case BTC_GNT_SW_LO:
2719 g[i].gnt_wl_sw_en = 1;
2720 g[i].gnt_wl = 0;
2721 break;
2722 case BTC_GNT_SW_HI:
2723 g[i].gnt_wl_sw_en = 1;
2724 g[i].gnt_wl = 1;
2725 break;
2726 }
2727
2728 switch (bt_state) {
2729 case BTC_GNT_HW:
2730 g[i].gnt_bt_sw_en = 0;
2731 g[i].gnt_bt = 0;
2732 break;
2733 case BTC_GNT_SW_LO:
2734 g[i].gnt_bt_sw_en = 1;
2735 g[i].gnt_bt = 0;
2736 break;
2737 case BTC_GNT_SW_HI:
2738 g[i].gnt_bt_sw_en = 1;
2739 g[i].gnt_bt = 1;
2740 break;
2741 }
2742 }
2743
2744 rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
2745 }
2746
_set_gnt_v1(struct rtw89_dev * rtwdev,u8 phy_map,u8 wl_state,u8 bt_state,u8 wlact_state)2747 static void _set_gnt_v1(struct rtw89_dev *rtwdev, u8 phy_map,
2748 u8 wl_state, u8 bt_state, u8 wlact_state)
2749 {
2750 struct rtw89_btc *btc = &rtwdev->btc;
2751 struct rtw89_btc_dm *dm = &btc->dm;
2752 struct rtw89_mac_ax_gnt *g = dm->gnt.band;
2753 u8 i, bt_idx = dm->bt_select + 1;
2754
2755 if (phy_map > BTC_PHY_ALL)
2756 return;
2757
2758 for (i = 0; i < RTW89_PHY_MAX; i++) {
2759 if (!(phy_map & BIT(i)))
2760 continue;
2761
2762 switch (wl_state) {
2763 case BTC_GNT_HW:
2764 g[i].gnt_wl_sw_en = 0;
2765 g[i].gnt_wl = 0;
2766 break;
2767 case BTC_GNT_SW_LO:
2768 g[i].gnt_wl_sw_en = 1;
2769 g[i].gnt_wl = 0;
2770 break;
2771 case BTC_GNT_SW_HI:
2772 g[i].gnt_wl_sw_en = 1;
2773 g[i].gnt_wl = 1;
2774 break;
2775 }
2776
2777 switch (bt_state) {
2778 case BTC_GNT_HW:
2779 g[i].gnt_bt_sw_en = 0;
2780 g[i].gnt_bt = 0;
2781 break;
2782 case BTC_GNT_SW_LO:
2783 g[i].gnt_bt_sw_en = 1;
2784 g[i].gnt_bt = 0;
2785 break;
2786 case BTC_GNT_SW_HI:
2787 g[i].gnt_bt_sw_en = 1;
2788 g[i].gnt_bt = 1;
2789 break;
2790 }
2791 }
2792
2793 if (rtwdev->chip->para_ver & BTC_FEAT_WLAN_ACT_MUX) {
2794 for (i = 0; i < 2; i++) {
2795 if (!(bt_idx & BIT(i)))
2796 continue;
2797
2798 switch (wlact_state) {
2799 case BTC_WLACT_HW:
2800 dm->gnt.bt[i].wlan_act_en = 0;
2801 dm->gnt.bt[i].wlan_act = 0;
2802 break;
2803 case BTC_WLACT_SW_LO:
2804 dm->gnt.bt[i].wlan_act_en = 1;
2805 dm->gnt.bt[i].wlan_act = 0;
2806 break;
2807 case BTC_WLACT_SW_HI:
2808 dm->gnt.bt[i].wlan_act_en = 1;
2809 dm->gnt.bt[i].wlan_act = 1;
2810 break;
2811 }
2812 }
2813 }
2814 rtw89_mac_cfg_gnt_v2(rtwdev, &dm->gnt);
2815 }
2816
2817 #define BTC_TDMA_WLROLE_MAX 3
2818
_set_bt_ignore_wlan_act(struct rtw89_dev * rtwdev,u8 enable)2819 static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable)
2820 {
2821 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2822 "[BTC], %s(): set bt %s wlan_act\n", __func__,
2823 enable ? "ignore" : "do not ignore");
2824
2825 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1);
2826 }
2827
2828 #define WL_TX_POWER_NO_BTC_CTRL GENMASK(31, 0)
2829 #define WL_TX_POWER_ALL_TIME GENMASK(15, 0)
2830 #define WL_TX_POWER_WITH_BT GENMASK(31, 16)
2831 #define WL_TX_POWER_INT_PART GENMASK(8, 2)
2832 #define WL_TX_POWER_FRA_PART GENMASK(1, 0)
2833 #define B_BTC_WL_TX_POWER_SIGN BIT(7)
2834 #define B_TSSI_WL_TX_POWER_SIGN BIT(8)
2835
_set_wl_tx_power(struct rtw89_dev * rtwdev,u32 level)2836 static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level)
2837 {
2838 const struct rtw89_chip_info *chip = rtwdev->chip;
2839 struct rtw89_btc *btc = &rtwdev->btc;
2840 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2841 u32 pwr_val;
2842
2843 if (wl->rf_para.tx_pwr_freerun == level)
2844 return;
2845
2846 wl->rf_para.tx_pwr_freerun = level;
2847 btc->dm.rf_trx_para.wl_tx_power = level;
2848
2849 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2850 "[BTC], %s(): level = %d\n",
2851 __func__, level);
2852
2853 if (level == RTW89_BTC_WL_DEF_TX_PWR) {
2854 pwr_val = WL_TX_POWER_NO_BTC_CTRL;
2855 } else { /* only apply "force tx power" */
2856 pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level);
2857 if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR)
2858 pwr_val = RTW89_BTC_WL_DEF_TX_PWR;
2859
2860 if (level & B_BTC_WL_TX_POWER_SIGN)
2861 pwr_val |= B_TSSI_WL_TX_POWER_SIGN;
2862 pwr_val |= WL_TX_POWER_WITH_BT;
2863 }
2864
2865 chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val);
2866 }
2867
_set_wl_rx_gain(struct rtw89_dev * rtwdev,u32 level)2868 static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
2869 {
2870 const struct rtw89_chip_info *chip = rtwdev->chip;
2871 struct rtw89_btc *btc = &rtwdev->btc;
2872 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2873
2874 if (wl->rf_para.rx_gain_freerun == level)
2875 return;
2876
2877 wl->rf_para.rx_gain_freerun = level;
2878 btc->dm.rf_trx_para.wl_rx_gain = level;
2879
2880 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2881 "[BTC], %s(): level = %d\n",
2882 __func__, level);
2883
2884 chip->ops->btc_set_wl_rx_gain(rtwdev, level);
2885 }
2886
_set_bt_tx_power(struct rtw89_dev * rtwdev,u8 level)2887 static void _set_bt_tx_power(struct rtw89_dev *rtwdev, u8 level)
2888 {
2889 struct rtw89_btc *btc = &rtwdev->btc;
2890 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
2891 int ret;
2892 u8 buf;
2893
2894 if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0)
2895 return;
2896
2897 if (bt->rf_para.tx_pwr_freerun == level)
2898 return;
2899
2900 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2901 "[BTC], %s(): level = %d\n",
2902 __func__, level);
2903
2904 buf = (s8)(-level);
2905 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_TX_PWR, &buf, 1);
2906 if (!ret) {
2907 bt->rf_para.tx_pwr_freerun = level;
2908 btc->dm.rf_trx_para.bt_tx_power = level;
2909 }
2910 }
2911
2912 #define BTC_BT_RX_NORMAL_LVL 7
2913
_set_bt_rx_gain(struct rtw89_dev * rtwdev,u8 level)2914 static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, u8 level)
2915 {
2916 struct rtw89_btc *btc = &rtwdev->btc;
2917 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
2918
2919 if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0)
2920 return;
2921
2922 if ((bt->rf_para.rx_gain_freerun == level ||
2923 level > BTC_BT_RX_NORMAL_LVL) &&
2924 (!rtwdev->chip->scbd || bt->lna_constrain == level))
2925 return;
2926
2927 bt->rf_para.rx_gain_freerun = level;
2928 btc->dm.rf_trx_para.bt_rx_gain = level;
2929
2930 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2931 "[BTC], %s(): level = %d\n",
2932 __func__, level);
2933
2934 if (level == BTC_BT_RX_NORMAL_LVL)
2935 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, false);
2936 else
2937 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
2938
2939 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_LNA_CONSTRAIN, &level, sizeof(level));
2940 }
2941
_set_rf_trx_para(struct rtw89_dev * rtwdev)2942 static void _set_rf_trx_para(struct rtw89_dev *rtwdev)
2943 {
2944 const struct rtw89_chip_info *chip = rtwdev->chip;
2945 struct rtw89_btc *btc = &rtwdev->btc;
2946 const struct rtw89_btc_ver *ver = btc->ver;
2947 struct rtw89_btc_dm *dm = &btc->dm;
2948 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2949 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
2950 struct rtw89_btc_bt_link_info *b = &bt->link_info;
2951 struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
2952 struct rtw89_btc_rf_trx_para para;
2953 u32 wl_stb_chg = 0;
2954 u8 level_id = 0, link_mode = 0, i, dbcc_2g_phy = 0;
2955
2956 if (ver->fwlrole == 0) {
2957 link_mode = wl->role_info.link_mode;
2958 for (i = 0; i < RTW89_PHY_MAX; i++) {
2959 if (wl->dbcc_info.real_band[i] == RTW89_BAND_2G)
2960 dbcc_2g_phy = i;
2961 }
2962 } else if (ver->fwlrole == 1) {
2963 link_mode = wl->role_info_v1.link_mode;
2964 dbcc_2g_phy = wl->role_info_v1.dbcc_2g_phy;
2965 } else if (ver->fwlrole == 2) {
2966 link_mode = wl->role_info_v2.link_mode;
2967 dbcc_2g_phy = wl->role_info_v2.dbcc_2g_phy;
2968 }
2969
2970 /* decide trx_para_level */
2971 if (btc->ant_type == BTC_ANT_SHARED) {
2972 /* fix LNA2 + TIA gain not change by GNT_BT */
2973 if ((btc->dm.wl_btg_rx && b->profile_cnt.now != 0) ||
2974 dm->bt_only == 1)
2975 dm->trx_para_level = 1; /* for better BT ACI issue */
2976 else
2977 dm->trx_para_level = 0;
2978 } else { /* non-shared antenna */
2979 dm->trx_para_level = 5;
2980 /* modify trx_para if WK 2.4G-STA-DL + bt link */
2981 if (b->profile_cnt.now != 0 &&
2982 link_mode == BTC_WLINK_2G_STA &&
2983 wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { /* uplink */
2984 if (wl->rssi_level == 4 && bt->rssi_level > 2)
2985 dm->trx_para_level = 6;
2986 else if (wl->rssi_level == 3 && bt->rssi_level > 3)
2987 dm->trx_para_level = 7;
2988 }
2989 }
2990
2991 level_id = dm->trx_para_level;
2992 if (level_id >= chip->rf_para_dlink_num ||
2993 level_id >= chip->rf_para_ulink_num) {
2994 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2995 "[BTC], %s(): invalid level_id: %d\n",
2996 __func__, level_id);
2997 return;
2998 }
2999
3000 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
3001 para = chip->rf_para_ulink[level_id];
3002 else
3003 para = chip->rf_para_dlink[level_id];
3004
3005 if (dm->fddt_train) {
3006 _set_wl_rx_gain(rtwdev, 1);
3007 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
3008 } else {
3009 _set_wl_tx_power(rtwdev, para.wl_tx_power);
3010 _set_wl_rx_gain(rtwdev, para.wl_rx_gain);
3011 _set_bt_tx_power(rtwdev, para.bt_tx_power);
3012 _set_bt_rx_gain(rtwdev, para.bt_rx_gain);
3013 }
3014
3015 if (!bt->enable.now || dm->wl_only || wl_smap->rf_off ||
3016 wl_smap->lps == BTC_LPS_RF_OFF ||
3017 link_mode == BTC_WLINK_5G ||
3018 link_mode == BTC_WLINK_NOLINK ||
3019 (rtwdev->dbcc_en && dbcc_2g_phy != RTW89_PHY_1))
3020 wl_stb_chg = 0;
3021 else
3022 wl_stb_chg = 1;
3023
3024 if (wl_stb_chg != dm->wl_stb_chg) {
3025 dm->wl_stb_chg = wl_stb_chg;
3026 chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg);
3027 }
3028 }
3029
_update_btc_state_map(struct rtw89_dev * rtwdev)3030 static void _update_btc_state_map(struct rtw89_dev *rtwdev)
3031 {
3032 struct rtw89_btc *btc = &rtwdev->btc;
3033 struct rtw89_btc_cx *cx = &btc->cx;
3034 struct rtw89_btc_wl_info *wl = &cx->wl;
3035 struct rtw89_btc_bt_info *bt = &cx->bt;
3036 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
3037
3038 if (wl->status.map.connecting || wl->status.map._4way ||
3039 wl->status.map.roaming || wl->status.map.dbccing) {
3040 cx->state_map = BTC_WLINKING;
3041 } else if (wl->status.map.scan) { /* wl scan */
3042 if (bt_linfo->status.map.inq_pag)
3043 cx->state_map = BTC_WSCAN_BSCAN;
3044 else
3045 cx->state_map = BTC_WSCAN_BNOSCAN;
3046 } else if (wl->status.map.busy) { /* only busy */
3047 if (bt_linfo->status.map.inq_pag)
3048 cx->state_map = BTC_WBUSY_BSCAN;
3049 else
3050 cx->state_map = BTC_WBUSY_BNOSCAN;
3051 } else { /* wl idle */
3052 cx->state_map = BTC_WIDLE;
3053 }
3054 }
3055
_set_bt_afh_info(struct rtw89_dev * rtwdev)3056 static void _set_bt_afh_info(struct rtw89_dev *rtwdev)
3057 {
3058 const struct rtw89_chip_info *chip = rtwdev->chip;
3059 struct rtw89_btc *btc = &rtwdev->btc;
3060 const struct rtw89_btc_ver *ver = btc->ver;
3061 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3062 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3063 struct rtw89_btc_bt_link_info *b = &bt->link_info;
3064 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3065 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3066 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
3067 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
3068 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
3069 struct rtw89_btc_wl_active_role *r;
3070 struct rtw89_btc_wl_active_role_v1 *r1;
3071 struct rtw89_btc_wl_active_role_v2 *r2;
3072 struct rtw89_btc_wl_active_role_v7 *r7;
3073 struct rtw89_btc_wl_rlink *rlink;
3074 u8 en = 0, i, ch = 0, bw = 0;
3075 u8 mode, connect_cnt;
3076
3077 if (btc->manual_ctrl || wl->status.map.scan)
3078 return;
3079
3080 if (ver->fwlrole == 0) {
3081 mode = wl_rinfo->link_mode;
3082 connect_cnt = wl_rinfo->connect_cnt;
3083 } else if (ver->fwlrole == 1) {
3084 mode = wl_rinfo_v1->link_mode;
3085 connect_cnt = wl_rinfo_v1->connect_cnt;
3086 } else if (ver->fwlrole == 2) {
3087 mode = wl_rinfo_v2->link_mode;
3088 connect_cnt = wl_rinfo_v2->connect_cnt;
3089 } else if (ver->fwlrole == 7) {
3090 mode = wl_rinfo_v7->link_mode;
3091 connect_cnt = wl_rinfo_v7->connect_cnt;
3092 } else if (ver->fwlrole == 8) {
3093 mode = wl_rinfo_v8->link_mode;
3094 connect_cnt = wl_rinfo_v8->connect_cnt;
3095 } else {
3096 return;
3097 }
3098
3099 if (wl->status.map.rf_off || bt->whql_test ||
3100 mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_5G ||
3101 connect_cnt > BTC_TDMA_WLROLE_MAX) {
3102 en = false;
3103 } else if (mode == BTC_WLINK_2G_MCC || mode == BTC_WLINK_2G_SCC) {
3104 en = true;
3105 /* get p2p channel */
3106 for (i = 0; i < RTW89_PORT_NUM; i++) {
3107 r = &wl_rinfo->active_role[i];
3108 r1 = &wl_rinfo_v1->active_role_v1[i];
3109 r2 = &wl_rinfo_v2->active_role_v2[i];
3110 r7 = &wl_rinfo_v7->active_role[i];
3111 rlink = &wl_rinfo_v8->rlink[i][0];
3112
3113 if (ver->fwlrole == 0 &&
3114 (r->role == RTW89_WIFI_ROLE_P2P_GO ||
3115 r->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3116 ch = r->ch;
3117 bw = r->bw;
3118 break;
3119 } else if (ver->fwlrole == 1 &&
3120 (r1->role == RTW89_WIFI_ROLE_P2P_GO ||
3121 r1->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3122 ch = r1->ch;
3123 bw = r1->bw;
3124 break;
3125 } else if (ver->fwlrole == 2 &&
3126 (r2->role == RTW89_WIFI_ROLE_P2P_GO ||
3127 r2->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3128 ch = r2->ch;
3129 bw = r2->bw;
3130 break;
3131 } else if (ver->fwlrole == 7 &&
3132 (r7->role == RTW89_WIFI_ROLE_P2P_GO ||
3133 r7->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3134 ch = r7->ch;
3135 bw = r7->bw;
3136 break;
3137 } else if (ver->fwlrole == 8 &&
3138 (rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
3139 rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3140 ch = rlink->ch;
3141 bw = rlink->bw;
3142 break;
3143 }
3144 }
3145 } else {
3146 en = true;
3147 /* get 2g channel */
3148 for (i = 0; i < RTW89_PORT_NUM; i++) {
3149 r = &wl_rinfo->active_role[i];
3150 r1 = &wl_rinfo_v1->active_role_v1[i];
3151 r2 = &wl_rinfo_v2->active_role_v2[i];
3152 r7 = &wl_rinfo_v7->active_role[i];
3153 rlink = &wl_rinfo_v8->rlink[i][0];
3154
3155 if (ver->fwlrole == 0 &&
3156 r->connected && r->band == RTW89_BAND_2G) {
3157 ch = r->ch;
3158 bw = r->bw;
3159 break;
3160 } else if (ver->fwlrole == 1 &&
3161 r1->connected && r1->band == RTW89_BAND_2G) {
3162 ch = r1->ch;
3163 bw = r1->bw;
3164 break;
3165 } else if (ver->fwlrole == 2 &&
3166 r2->connected && r2->band == RTW89_BAND_2G) {
3167 ch = r2->ch;
3168 bw = r2->bw;
3169 break;
3170 } else if (ver->fwlrole == 7 &&
3171 r7->connected && r7->band == RTW89_BAND_2G) {
3172 ch = r7->ch;
3173 bw = r7->bw;
3174 break;
3175 } else if (ver->fwlrole == 8 &&
3176 rlink->connected && rlink->rf_band == RTW89_BAND_2G) {
3177 ch = rlink->ch;
3178 bw = rlink->bw;
3179 break;
3180 }
3181 }
3182 }
3183
3184 switch (bw) {
3185 case RTW89_CHANNEL_WIDTH_20:
3186 bw = 20 + chip->afh_guard_ch * 2;
3187 break;
3188 case RTW89_CHANNEL_WIDTH_40:
3189 bw = 40 + chip->afh_guard_ch * 2;
3190 break;
3191 case RTW89_CHANNEL_WIDTH_5:
3192 bw = 5 + chip->afh_guard_ch * 2;
3193 break;
3194 case RTW89_CHANNEL_WIDTH_10:
3195 bw = 10 + chip->afh_guard_ch * 2;
3196 break;
3197 default:
3198 bw = 0;
3199 en = false; /* turn off AFH info if BW > 40 */
3200 break;
3201 }
3202
3203 if (wl->afh_info.en == en &&
3204 wl->afh_info.ch == ch &&
3205 wl->afh_info.bw == bw &&
3206 b->profile_cnt.last == b->profile_cnt.now) {
3207 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3208 "[BTC], %s(): return because no change!\n",
3209 __func__);
3210 return;
3211 }
3212
3213 wl->afh_info.en = en;
3214 wl->afh_info.ch = ch;
3215 wl->afh_info.bw = bw;
3216
3217 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3);
3218
3219 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3220 "[BTC], %s(): en=%d, ch=%d, bw=%d\n",
3221 __func__, en, ch, bw);
3222 btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++;
3223 }
3224
_check_freerun(struct rtw89_dev * rtwdev)3225 static bool _check_freerun(struct rtw89_dev *rtwdev)
3226 {
3227 struct rtw89_btc *btc = &rtwdev->btc;
3228 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3229 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3230 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3231 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3232 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
3233 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
3234 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
3235 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
3236 struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc;
3237 union rtw89_btc_module_info *md = &btc->mdinfo;
3238 const struct rtw89_btc_ver *ver = btc->ver;
3239 u8 isolation, connect_cnt = 0;
3240
3241 if (ver->fcxinit == 7)
3242 isolation = md->md_v7.ant.isolation;
3243 else
3244 isolation = md->md.ant.isolation;
3245
3246 if (ver->fwlrole == 0)
3247 connect_cnt = wl_rinfo->connect_cnt;
3248 else if (ver->fwlrole == 1)
3249 connect_cnt = wl_rinfo_v1->connect_cnt;
3250 else if (ver->fwlrole == 2)
3251 connect_cnt = wl_rinfo_v2->connect_cnt;
3252 else if (ver->fwlrole == 7)
3253 connect_cnt = wl_rinfo_v7->connect_cnt;
3254 else if (ver->fwlrole == 8)
3255 connect_cnt = wl_rinfo_v8->connect_cnt;
3256
3257 if (btc->ant_type == BTC_ANT_SHARED) {
3258 btc->dm.trx_para_level = 0;
3259 return false;
3260 }
3261
3262 /* The below is dedicated antenna case */
3263 if (connect_cnt > BTC_TDMA_WLROLE_MAX) {
3264 btc->dm.trx_para_level = 5;
3265 return true;
3266 }
3267
3268 if (bt_linfo->profile_cnt.now == 0) {
3269 btc->dm.trx_para_level = 5;
3270 return true;
3271 }
3272
3273 if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) {
3274 btc->dm.trx_para_level = 5;
3275 return true;
3276 }
3277
3278 /* TODO get isolation by BT psd */
3279 if (isolation >= BTC_FREERUN_ANTISO_MIN) {
3280 btc->dm.trx_para_level = 5;
3281 return true;
3282 }
3283
3284 if (!wl->status.map.busy) {/* wl idle -> freerun */
3285 btc->dm.trx_para_level = 5;
3286 return true;
3287 } else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */
3288 btc->dm.trx_para_level = 0;
3289 return false;
3290 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
3291 if (wl->rssi_level == 0 && bt_linfo->rssi > 31) {
3292 btc->dm.trx_para_level = 6;
3293 return true;
3294 } else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) {
3295 btc->dm.trx_para_level = 7;
3296 return true;
3297 }
3298 btc->dm.trx_para_level = 0;
3299 return false;
3300 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) {
3301 if (bt_linfo->rssi > 28) {
3302 btc->dm.trx_para_level = 6;
3303 return true;
3304 }
3305 }
3306
3307 btc->dm.trx_para_level = 0;
3308 return false;
3309 }
3310
3311 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; })
3312 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; })
3313 #define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; })
3314 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; })
3315
3316 struct btc_btinfo_lb2 {
3317 u8 connect: 1;
3318 u8 sco_busy: 1;
3319 u8 inq_pag: 1;
3320 u8 acl_busy: 1;
3321 u8 hfp: 1;
3322 u8 hid: 1;
3323 u8 a2dp: 1;
3324 u8 pan: 1;
3325 };
3326
3327 struct btc_btinfo_lb3 {
3328 u8 retry: 4;
3329 u8 cqddr: 1;
3330 u8 inq: 1;
3331 u8 mesh_busy: 1;
3332 u8 pag: 1;
3333 };
3334
3335 struct btc_btinfo_hb0 {
3336 s8 rssi;
3337 };
3338
3339 struct btc_btinfo_hb1 {
3340 u8 ble_connect: 1;
3341 u8 reinit: 1;
3342 u8 relink: 1;
3343 u8 igno_wl: 1;
3344 u8 voice: 1;
3345 u8 ble_scan: 1;
3346 u8 role_sw: 1;
3347 u8 multi_link: 1;
3348 };
3349
3350 struct btc_btinfo_hb2 {
3351 u8 pan_active: 1;
3352 u8 afh_update: 1;
3353 u8 a2dp_active: 1;
3354 u8 slave: 1;
3355 u8 hid_slot: 2;
3356 u8 hid_cnt: 2;
3357 };
3358
3359 struct btc_btinfo_hb3 {
3360 u8 a2dp_bitpool: 6;
3361 u8 tx_3m: 1;
3362 u8 a2dp_sink: 1;
3363 };
3364
3365 union btc_btinfo {
3366 u8 val;
3367 struct btc_btinfo_lb2 lb2;
3368 struct btc_btinfo_lb3 lb3;
3369 struct btc_btinfo_hb0 hb0;
3370 struct btc_btinfo_hb1 hb1;
3371 struct btc_btinfo_hb2 hb2;
3372 struct btc_btinfo_hb3 hb3;
3373 };
3374
_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)3375 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
3376 enum btc_reason_and_action action)
3377 {
3378 const struct rtw89_chip_info *chip = rtwdev->chip;
3379
3380 chip->ops->btc_set_policy(rtwdev, policy_type);
3381 _fw_set_policy(rtwdev, policy_type, action);
3382 }
3383
3384 #define BTC_B1_MAX 250 /* unit ms */
rtw89_btc_set_policy(struct rtw89_dev * rtwdev,u16 policy_type)3385 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type)
3386 {
3387 struct rtw89_btc *btc = &rtwdev->btc;
3388 struct rtw89_btc_dm *dm = &btc->dm;
3389 struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
3390 struct rtw89_btc_fbtc_slot *s = dm->slot.v1;
3391 u8 type;
3392 u32 tbl_w1, tbl_b1, tbl_b4;
3393
3394 if (btc->ant_type == BTC_ANT_SHARED) {
3395 if (btc->cx.wl.status.map._4way)
3396 tbl_w1 = cxtbl[1];
3397 else
3398 tbl_w1 = cxtbl[8];
3399 tbl_b1 = cxtbl[3];
3400 tbl_b4 = cxtbl[3];
3401 } else {
3402 tbl_w1 = cxtbl[16];
3403 tbl_b1 = cxtbl[17];
3404 tbl_b4 = cxtbl[17];
3405 }
3406
3407 type = (u8)((policy_type & BTC_CXP_MASK) >> 8);
3408 btc->bt_req_en = false;
3409
3410 switch (type) {
3411 case BTC_CXP_USERDEF0:
3412 *t = t_def[CXTD_OFF];
3413 s[CXST_OFF] = s_def[CXST_OFF];
3414 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
3415 btc->update_policy_force = true;
3416 break;
3417 case BTC_CXP_OFF: /* TDMA off */
3418 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
3419 *t = t_def[CXTD_OFF];
3420 s[CXST_OFF] = s_def[CXST_OFF];
3421
3422 switch (policy_type) {
3423 case BTC_CXP_OFF_BT:
3424 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
3425 break;
3426 case BTC_CXP_OFF_WL:
3427 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
3428 break;
3429 case BTC_CXP_OFF_EQ0:
3430 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
3431 break;
3432 case BTC_CXP_OFF_EQ1:
3433 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
3434 break;
3435 case BTC_CXP_OFF_EQ2:
3436 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
3437 break;
3438 case BTC_CXP_OFF_EQ3:
3439 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
3440 break;
3441 case BTC_CXP_OFF_BWB0:
3442 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
3443 break;
3444 case BTC_CXP_OFF_BWB1:
3445 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
3446 break;
3447 case BTC_CXP_OFF_BWB3:
3448 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
3449 break;
3450 }
3451 break;
3452 case BTC_CXP_OFFB: /* TDMA off + beacon protect */
3453 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
3454 *t = t_def[CXTD_OFF_B2];
3455 s[CXST_OFF] = s_def[CXST_OFF];
3456 switch (policy_type) {
3457 case BTC_CXP_OFFB_BWB0:
3458 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
3459 break;
3460 }
3461 break;
3462 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
3463 btc->bt_req_en = true;
3464 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3465 *t = t_def[CXTD_OFF_EXT];
3466 switch (policy_type) {
3467 case BTC_CXP_OFFE_DEF:
3468 s[CXST_E2G] = s_def[CXST_E2G];
3469 s[CXST_E5G] = s_def[CXST_E5G];
3470 s[CXST_EBT] = s_def[CXST_EBT];
3471 s[CXST_ENULL] = s_def[CXST_ENULL];
3472 break;
3473 case BTC_CXP_OFFE_DEF2:
3474 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
3475 s[CXST_E5G] = s_def[CXST_E5G];
3476 s[CXST_EBT] = s_def[CXST_EBT];
3477 s[CXST_ENULL] = s_def[CXST_ENULL];
3478 break;
3479 }
3480 break;
3481 case BTC_CXP_FIX: /* TDMA Fix-Slot */
3482 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3483 *t = t_def[CXTD_FIX];
3484 switch (policy_type) {
3485 case BTC_CXP_FIX_TD3030:
3486 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3487 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3488 break;
3489 case BTC_CXP_FIX_TD5050:
3490 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3491 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
3492 break;
3493 case BTC_CXP_FIX_TD2030:
3494 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3495 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3496 break;
3497 case BTC_CXP_FIX_TD4010:
3498 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
3499 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3500 break;
3501 case BTC_CXP_FIX_TD4010ISO:
3502 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
3503 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3504 break;
3505 case BTC_CXP_FIX_TD4010ISO_DL:
3506 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
3507 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
3508 break;
3509 case BTC_CXP_FIX_TD4010ISO_UL:
3510 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
3511 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
3512 break;
3513 case BTC_CXP_FIX_TD7010:
3514 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
3515 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3516 break;
3517 case BTC_CXP_FIX_TD2060:
3518 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3519 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3520 break;
3521 case BTC_CXP_FIX_TD3060:
3522 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3523 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3524 break;
3525 case BTC_CXP_FIX_TD2080:
3526 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3527 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
3528 break;
3529 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
3530 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3531 tbl_w1, SLOT_ISO);
3532 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3533 tbl_b1, SLOT_MIX);
3534 break;
3535 }
3536 break;
3537 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
3538 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3539 *t = t_def[CXTD_PFIX];
3540 if (btc->cx.wl.role_info.role_map.role.ap)
3541 _tdma_set_flctrl(btc, CXFLC_QOSNULL);
3542
3543 switch (policy_type) {
3544 case BTC_CXP_PFIX_TD3030:
3545 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3546 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3547 break;
3548 case BTC_CXP_PFIX_TD5050:
3549 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3550 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
3551 break;
3552 case BTC_CXP_PFIX_TD2030:
3553 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3554 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3555 break;
3556 case BTC_CXP_PFIX_TD2060:
3557 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3558 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3559 break;
3560 case BTC_CXP_PFIX_TD3070:
3561 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3562 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3563 break;
3564 case BTC_CXP_PFIX_TD2080:
3565 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3566 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
3567 break;
3568 }
3569 break;
3570 case BTC_CXP_AUTO: /* TDMA Auto-Slot */
3571 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3572 *t = t_def[CXTD_AUTO];
3573 switch (policy_type) {
3574 case BTC_CXP_AUTO_TD50B1:
3575 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3576 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3577 break;
3578 case BTC_CXP_AUTO_TD60B1:
3579 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3580 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3581 break;
3582 case BTC_CXP_AUTO_TD20B1:
3583 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3584 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3585 break;
3586 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
3587 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3588 tbl_w1, SLOT_ISO);
3589 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3590 tbl_b1, SLOT_MIX);
3591 break;
3592 }
3593 break;
3594 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
3595 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3596 *t = t_def[CXTD_PAUTO];
3597 switch (policy_type) {
3598 case BTC_CXP_PAUTO_TD50B1:
3599 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3600 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3601 break;
3602 case BTC_CXP_PAUTO_TD60B1:
3603 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3604 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3605 break;
3606 case BTC_CXP_PAUTO_TD20B1:
3607 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3608 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3609 break;
3610 case BTC_CXP_PAUTO_TDW1B1:
3611 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3612 tbl_w1, SLOT_ISO);
3613 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3614 tbl_b1, SLOT_MIX);
3615 break;
3616 }
3617 break;
3618 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
3619 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3620 *t = t_def[CXTD_AUTO2];
3621 switch (policy_type) {
3622 case BTC_CXP_AUTO2_TD3050:
3623 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3624 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3625 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3626 break;
3627 case BTC_CXP_AUTO2_TD3070:
3628 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3629 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
3630 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3631 break;
3632 case BTC_CXP_AUTO2_TD5050:
3633 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3634 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3635 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3636 break;
3637 case BTC_CXP_AUTO2_TD6060:
3638 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3639 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
3640 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3641 break;
3642 case BTC_CXP_AUTO2_TD2080:
3643 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3644 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
3645 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3646 break;
3647 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
3648 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3649 tbl_w1, SLOT_ISO);
3650 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
3651 tbl_b4, SLOT_MIX);
3652 break;
3653 }
3654 break;
3655 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
3656 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3657 *t = t_def[CXTD_PAUTO2];
3658 switch (policy_type) {
3659 case BTC_CXP_PAUTO2_TD3050:
3660 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3661 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3662 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3663 break;
3664 case BTC_CXP_PAUTO2_TD3070:
3665 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3666 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
3667 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3668 break;
3669 case BTC_CXP_PAUTO2_TD5050:
3670 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3671 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3672 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3673 break;
3674 case BTC_CXP_PAUTO2_TD6060:
3675 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3676 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
3677 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3678 break;
3679 case BTC_CXP_PAUTO2_TD2080:
3680 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3681 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
3682 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3683 break;
3684 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
3685 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3686 tbl_w1, SLOT_ISO);
3687 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
3688 tbl_b4, SLOT_MIX);
3689 break;
3690 }
3691 break;
3692 }
3693 }
3694 EXPORT_SYMBOL(rtw89_btc_set_policy);
3695
rtw89_btc_set_policy_v1(struct rtw89_dev * rtwdev,u16 policy_type)3696 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
3697 {
3698 struct rtw89_btc *btc = &rtwdev->btc;
3699 struct rtw89_btc_dm *dm = &btc->dm;
3700 struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
3701 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1;
3702 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
3703 struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
3704 struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc;
3705 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3706 u8 type, null_role;
3707 u32 tbl_w1, tbl_b1, tbl_b4;
3708 u16 dur_2;
3709
3710 type = FIELD_GET(BTC_CXP_MASK, policy_type);
3711
3712 if (btc->ant_type == BTC_ANT_SHARED) {
3713 if (btc->cx.wl.status.map._4way)
3714 tbl_w1 = cxtbl[1];
3715 else if (hid->exist && hid->type == BTC_HID_218)
3716 tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */
3717 else
3718 tbl_w1 = cxtbl[8];
3719
3720 if (dm->leak_ap &&
3721 (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) {
3722 tbl_b1 = cxtbl[3];
3723 tbl_b4 = cxtbl[3];
3724 } else if (hid->exist && hid->type == BTC_HID_218) {
3725 tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */
3726 tbl_b4 = cxtbl[4];
3727 } else {
3728 tbl_b1 = cxtbl[2];
3729 tbl_b4 = cxtbl[2];
3730 }
3731 } else {
3732 tbl_b1 = cxtbl[17];
3733 tbl_b4 = cxtbl[17];
3734
3735 if (wl->bg_mode)
3736 tbl_w1 = cxtbl[8];
3737 else if ((wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) &&
3738 hid->exist)
3739 tbl_w1 = cxtbl[19];
3740 else
3741 tbl_w1 = cxtbl[16];
3742 }
3743
3744 switch (type) {
3745 case BTC_CXP_USERDEF0:
3746 btc->update_policy_force = true;
3747 *t = t_def[CXTD_OFF];
3748 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
3749 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
3750 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
3751 break;
3752 case BTC_CXP_OFF: /* TDMA off */
3753 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
3754 *t = t_def[CXTD_OFF];
3755 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
3756 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
3757
3758 switch (policy_type) {
3759 case BTC_CXP_OFF_BT:
3760 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
3761 break;
3762 case BTC_CXP_OFF_WL:
3763 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
3764 break;
3765 case BTC_CXP_OFF_WL2:
3766 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
3767 _slot_set_type(btc, CXST_OFF, SLOT_ISO);
3768 break;
3769 case BTC_CXP_OFF_EQ0:
3770 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
3771 _slot_set_type(btc, CXST_OFF, SLOT_ISO);
3772 break;
3773 case BTC_CXP_OFF_EQ1:
3774 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
3775 break;
3776 case BTC_CXP_OFF_EQ2:
3777 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
3778 break;
3779 case BTC_CXP_OFF_EQ3:
3780 _slot_set_tbl(btc, CXST_OFF, cxtbl[24]);
3781 break;
3782 case BTC_CXP_OFF_EQ4:
3783 _slot_set_tbl(btc, CXST_OFF, cxtbl[26]);
3784 break;
3785 case BTC_CXP_OFF_EQ5:
3786 _slot_set_tbl(btc, CXST_OFF, cxtbl[27]);
3787 break;
3788 case BTC_CXP_OFF_BWB0:
3789 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
3790 break;
3791 case BTC_CXP_OFF_BWB1:
3792 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
3793 break;
3794 case BTC_CXP_OFF_BWB2:
3795 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
3796 break;
3797 case BTC_CXP_OFF_BWB3:
3798 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
3799 break;
3800 default:
3801 break;
3802 }
3803 break;
3804 case BTC_CXP_OFFB: /* TDMA off + beacon protect */
3805 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
3806 *t = t_def[CXTD_OFF_B2];
3807 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
3808 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
3809
3810 switch (policy_type) {
3811 case BTC_CXP_OFFB_BWB0:
3812 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
3813 break;
3814 default:
3815 break;
3816 }
3817 break;
3818 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
3819 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3820 *t = t_def[CXTD_OFF_EXT];
3821
3822 /* To avoid wl-s0 tx break by hid/hfp tx */
3823 if (hid->exist || hfp->exist)
3824 tbl_w1 = cxtbl[16];
3825
3826 dur_2 = dm->e2g_slot_limit;
3827
3828 switch (policy_type) {
3829 case BTC_CXP_OFFE_2GBWISOB: /* for normal-case */
3830 _slot_set(btc, CXST_E2G, 0, tbl_w1, SLOT_ISO);
3831 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
3832 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
3833 _slot_set_dur(btc, CXST_EBT, dur_2);
3834 break;
3835 case BTC_CXP_OFFE_2GISOB: /* for bt no-link */
3836 _slot_set(btc, CXST_E2G, 0, cxtbl[1], SLOT_ISO);
3837 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
3838 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
3839 _slot_set_dur(btc, CXST_EBT, dur_2);
3840 break;
3841 case BTC_CXP_OFFE_DEF:
3842 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
3843 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
3844 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
3845 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
3846 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
3847 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
3848 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
3849 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
3850 break;
3851 case BTC_CXP_OFFE_DEF2:
3852 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
3853 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
3854 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
3855 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
3856 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
3857 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
3858 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
3859 break;
3860 case BTC_CXP_OFFE_2GBWMIXB:
3861 if (a2dp->exist)
3862 _slot_set(btc, CXST_E2G, 0, cxtbl[2], SLOT_MIX);
3863 else
3864 _slot_set(btc, CXST_E2G, 0, tbl_w1, SLOT_MIX);
3865 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
3866 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
3867 break;
3868 case BTC_CXP_OFFE_WL: /* for 4-way */
3869 _slot_set(btc, CXST_E2G, 0, cxtbl[1], SLOT_MIX);
3870 _slot_set(btc, CXST_EBT, 0, cxtbl[1], SLOT_MIX);
3871 break;
3872 default:
3873 break;
3874 }
3875 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
3876 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
3877 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
3878 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
3879 break;
3880 case BTC_CXP_FIX: /* TDMA Fix-Slot */
3881 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3882 *t = t_def[CXTD_FIX];
3883
3884 switch (policy_type) {
3885 case BTC_CXP_FIX_TD3030:
3886 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3887 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3888 break;
3889 case BTC_CXP_FIX_TD5050:
3890 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3891 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
3892 break;
3893 case BTC_CXP_FIX_TD2030:
3894 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3895 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3896 break;
3897 case BTC_CXP_FIX_TD4010:
3898 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
3899 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3900 break;
3901 case BTC_CXP_FIX_TD4010ISO:
3902 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
3903 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3904 break;
3905 case BTC_CXP_FIX_TD4010ISO_DL:
3906 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
3907 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
3908 break;
3909 case BTC_CXP_FIX_TD4010ISO_UL:
3910 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
3911 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
3912 break;
3913 case BTC_CXP_FIX_TD7010:
3914 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
3915 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3916 break;
3917 case BTC_CXP_FIX_TD2060:
3918 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3919 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3920 break;
3921 case BTC_CXP_FIX_TD3060:
3922 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3923 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3924 break;
3925 case BTC_CXP_FIX_TD2080:
3926 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3927 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
3928 break;
3929 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
3930 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3931 tbl_w1, SLOT_ISO);
3932 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3933 tbl_b1, SLOT_MIX);
3934 break;
3935 default:
3936 break;
3937 }
3938 break;
3939 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
3940 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3941 *t = t_def[CXTD_PFIX];
3942
3943 switch (policy_type) {
3944 case BTC_CXP_PFIX_TD3030:
3945 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3946 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3947 break;
3948 case BTC_CXP_PFIX_TD5050:
3949 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3950 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
3951 break;
3952 case BTC_CXP_PFIX_TD2030:
3953 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3954 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3955 break;
3956 case BTC_CXP_PFIX_TD2060:
3957 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3958 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3959 break;
3960 case BTC_CXP_PFIX_TD3070:
3961 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3962 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3963 break;
3964 case BTC_CXP_PFIX_TD2080:
3965 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3966 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
3967 break;
3968 case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */
3969 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3970 tbl_w1, SLOT_ISO);
3971 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3972 tbl_b1, SLOT_MIX);
3973 break;
3974 default:
3975 break;
3976 }
3977 break;
3978 case BTC_CXP_AUTO: /* TDMA Auto-Slot */
3979 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3980 *t = t_def[CXTD_AUTO];
3981
3982 switch (policy_type) {
3983 case BTC_CXP_AUTO_TD50B1:
3984 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3985 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3986 break;
3987 case BTC_CXP_AUTO_TD60B1:
3988 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3989 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3990 break;
3991 case BTC_CXP_AUTO_TD20B1:
3992 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3993 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3994 break;
3995 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
3996 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3997 tbl_w1, SLOT_ISO);
3998 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3999 tbl_b1, SLOT_MIX);
4000 break;
4001 default:
4002 break;
4003 }
4004 break;
4005 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
4006 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4007 *t = t_def[CXTD_PAUTO];
4008
4009 switch (policy_type) {
4010 case BTC_CXP_PAUTO_TD50B1:
4011 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4012 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4013 break;
4014 case BTC_CXP_PAUTO_TD60B1:
4015 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4016 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4017 break;
4018 case BTC_CXP_PAUTO_TD20B1:
4019 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4020 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4021 break;
4022 case BTC_CXP_PAUTO_TDW1B1:
4023 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4024 tbl_w1, SLOT_ISO);
4025 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4026 tbl_b1, SLOT_MIX);
4027 break;
4028 default:
4029 break;
4030 }
4031 break;
4032 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
4033 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4034 *t = t_def[CXTD_AUTO2];
4035
4036 switch (policy_type) {
4037 case BTC_CXP_AUTO2_TD3050:
4038 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4039 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4040 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4041 break;
4042 case BTC_CXP_AUTO2_TD3070:
4043 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4044 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4045 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
4046 break;
4047 case BTC_CXP_AUTO2_TD5050:
4048 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4049 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4050 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4051 break;
4052 case BTC_CXP_AUTO2_TD6060:
4053 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4054 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4055 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
4056 break;
4057 case BTC_CXP_AUTO2_TD2080:
4058 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4059 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4060 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
4061 break;
4062 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
4063 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4064 tbl_w1, SLOT_ISO);
4065 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4066 tbl_b1, SLOT_MIX);
4067 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
4068 tbl_b4, SLOT_MIX);
4069 break;
4070 default:
4071 break;
4072 }
4073 break;
4074 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
4075 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4076 *t = t_def[CXTD_PAUTO2];
4077
4078 switch (policy_type) {
4079 case BTC_CXP_PAUTO2_TD3050:
4080 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4081 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4082 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4083 break;
4084 case BTC_CXP_PAUTO2_TD3070:
4085 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4086 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4087 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
4088 break;
4089 case BTC_CXP_PAUTO2_TD5050:
4090 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4091 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4092 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4093 break;
4094 case BTC_CXP_PAUTO2_TD6060:
4095 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4096 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4097 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
4098 break;
4099 case BTC_CXP_PAUTO2_TD2080:
4100 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4101 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4102 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
4103 break;
4104 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
4105 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4106 tbl_w1, SLOT_ISO);
4107 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4108 tbl_b1, SLOT_MIX);
4109 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
4110 tbl_b4, SLOT_MIX);
4111 break;
4112 default:
4113 break;
4114 }
4115 break;
4116 }
4117
4118 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) {
4119 null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) |
4120 FIELD_PREP(0xf0, dm->wl_scc.null_role2);
4121 _tdma_set_flctrl_role(btc, null_role);
4122 }
4123
4124 /* enter leak_slot after each null-1 */
4125 if (dm->leak_ap && dm->tdma.leak_n > 1)
4126 _tdma_set_lek(btc, 1);
4127
4128 if (dm->tdma_instant_excute) {
4129 btc->dm.tdma.option_ctrl |= BIT(0);
4130 btc->update_policy_force = true;
4131 }
4132 }
4133 EXPORT_SYMBOL(rtw89_btc_set_policy_v1);
4134
_set_bt_plut(struct rtw89_dev * rtwdev,u8 phy_map,u8 tx_val,u8 rx_val)4135 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
4136 u8 tx_val, u8 rx_val)
4137 {
4138 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
4139 struct rtw89_mac_ax_plt plt;
4140
4141 plt.tx = tx_val;
4142 plt.rx = rx_val;
4143
4144 if (rtwdev->btc.ver->fwlrole == 8) {
4145 plt.band = wl->pta_req_mac;
4146 if (wl->bt_polut_type[plt.band] == tx_val)
4147 return;
4148
4149 wl->bt_polut_type[plt.band] = tx_val;
4150 rtw89_mac_cfg_plt(rtwdev, &plt);
4151 } else {
4152 plt.band = RTW89_MAC_0;
4153
4154 if (phy_map & BTC_PHY_0)
4155 rtw89_mac_cfg_plt(rtwdev, &plt);
4156
4157 if (!rtwdev->dbcc_en)
4158 return;
4159
4160 plt.band = RTW89_MAC_1;
4161 if (phy_map & BTC_PHY_1)
4162 rtw89_mac_cfg_plt(rtwdev, &plt);
4163 }
4164 }
4165
_set_ant_v0(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4166 static void _set_ant_v0(struct rtw89_dev *rtwdev, bool force_exec,
4167 u8 phy_map, u8 type)
4168 {
4169 struct rtw89_btc *btc = &rtwdev->btc;
4170 struct rtw89_btc_dm *dm = &btc->dm;
4171 struct rtw89_btc_cx *cx = &btc->cx;
4172 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4173 struct rtw89_btc_bt_info *bt = &cx->bt;
4174 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4175 u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0;
4176 bool dbcc_chg = false;
4177 u32 ant_path_type;
4178
4179 ant_path_type = ((phy_map << 8) + type);
4180
4181 if (btc->ver->fwlrole == 1)
4182 dbcc_chg = wl->role_info_v1.dbcc_chg;
4183 else if (btc->ver->fwlrole == 2)
4184 dbcc_chg = wl->role_info_v2.dbcc_chg;
4185 else if (btc->ver->fwlrole == 7)
4186 dbcc_chg = wl->role_info_v7.dbcc_chg;
4187 else if (btc->ver->fwlrole == 8)
4188 dbcc_chg = wl->role_info_v8.dbcc_chg;
4189
4190 if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
4191 btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
4192 btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || dbcc_chg)
4193 force_exec = FC_EXEC;
4194
4195 if (!force_exec && ant_path_type == dm->set_ant_path) {
4196 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4197 "[BTC], %s(): return by no change!!\n",
4198 __func__);
4199 return;
4200 } else if (bt->rfk_info.map.run) {
4201 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4202 "[BTC], %s(): return by bt rfk!!\n", __func__);
4203 return;
4204 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
4205 wl->rfk_info.state != BTC_WRFK_STOP) {
4206 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4207 "[BTC], %s(): return by wl rfk!!\n", __func__);
4208 return;
4209 }
4210
4211 dm->set_ant_path = ant_path_type;
4212
4213 rtw89_debug(rtwdev,
4214 RTW89_DBG_BTC,
4215 "[BTC], %s(): path=0x%x, set_type=0x%x\n",
4216 __func__, phy_map, dm->set_ant_path & 0xff);
4217
4218 switch (type) {
4219 case BTC_ANT_WPOWERON:
4220 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4221 break;
4222 case BTC_ANT_WINIT:
4223 if (bt->enable.now)
4224 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
4225 else
4226 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4227
4228 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4229 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT);
4230 break;
4231 case BTC_ANT_WONLY:
4232 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4233 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4234 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4235 break;
4236 case BTC_ANT_WOFF:
4237 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4238 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4239 break;
4240 case BTC_ANT_W2G:
4241 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4242 if (rtwdev->dbcc_en) {
4243 for (i = 0; i < RTW89_PHY_MAX; i++) {
4244 b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G);
4245
4246 gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
4247 gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
4248 /* BT should control by GNT_BT if WL_2G at S0 */
4249 if (i == 1 &&
4250 wl_dinfo->real_band[0] == RTW89_BAND_2G &&
4251 wl_dinfo->real_band[1] == RTW89_BAND_5G)
4252 gnt_bt_ctrl = BTC_GNT_HW;
4253 _set_gnt(rtwdev, BIT(i), gnt_wl_ctrl, gnt_bt_ctrl);
4254 plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE;
4255 _set_bt_plut(rtwdev, BIT(i),
4256 plt_ctrl, plt_ctrl);
4257 }
4258 } else {
4259 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
4260 _set_bt_plut(rtwdev, BTC_PHY_ALL,
4261 BTC_PLT_BT, BTC_PLT_BT);
4262 }
4263 break;
4264 case BTC_ANT_W5G:
4265 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4266 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW);
4267 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4268 break;
4269 case BTC_ANT_W25G:
4270 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4271 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
4272 _set_bt_plut(rtwdev, BTC_PHY_ALL,
4273 BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
4274 break;
4275 case BTC_ANT_FREERUN:
4276 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4277 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI);
4278 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4279 break;
4280 case BTC_ANT_WRFK:
4281 case BTC_ANT_WRFK2:
4282 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4283 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4284 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
4285 break;
4286 case BTC_ANT_BRFK:
4287 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4288 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
4289 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
4290 break;
4291 default:
4292 break;
4293 }
4294 }
4295
_set_ant_v1(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4296 static void _set_ant_v1(struct rtw89_dev *rtwdev, bool force_exec,
4297 u8 phy_map, u8 type)
4298 {
4299 struct rtw89_btc *btc = &rtwdev->btc;
4300 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4301 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4302 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
4303 u32 ant_path_type = rtw89_get_antpath_type(phy_map, type);
4304 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4305 struct rtw89_btc_dm *dm = &btc->dm;
4306 u8 gwl = BTC_GNT_HW;
4307
4308 if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
4309 btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
4310 btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || wl_rinfo->dbcc_chg)
4311 force_exec = FC_EXEC;
4312
4313 if (wl_rinfo->link_mode != BTC_WLINK_25G_MCC &&
4314 btc->dm.wl_btg_rx == 2)
4315 force_exec = FC_EXEC;
4316
4317 if (!force_exec && ant_path_type == dm->set_ant_path) {
4318 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4319 "[BTC], %s(): return by no change!!\n",
4320 __func__);
4321 return;
4322 } else if (bt->rfk_info.map.run) {
4323 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4324 "[BTC], %s(): return by bt rfk!!\n", __func__);
4325 return;
4326 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
4327 wl->rfk_info.state != BTC_WRFK_STOP) {
4328 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4329 "[BTC], %s(): return by wl rfk!!\n", __func__);
4330 return;
4331 }
4332
4333 dm->set_ant_path = ant_path_type;
4334
4335 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4336 "[BTC], %s(): path=0x%x, set_type=0x%x\n",
4337 __func__, phy_map, dm->set_ant_path & 0xff);
4338
4339 switch (type) {
4340 case BTC_ANT_WINIT:
4341 /* To avoid BT MP driver case (bt_enable but no mailbox) */
4342 if (bt->enable.now && bt->run_patch_code)
4343 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
4344 BTC_WLACT_SW_LO);
4345 else
4346 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4347 BTC_WLACT_SW_HI);
4348 break;
4349 case BTC_ANT_WONLY:
4350 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4351 BTC_WLACT_SW_HI);
4352 break;
4353 case BTC_ANT_WOFF:
4354 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
4355 BTC_WLACT_SW_LO);
4356 break;
4357 case BTC_ANT_W2G:
4358 case BTC_ANT_W25G:
4359 if (wl_rinfo->dbcc_en) {
4360 if (wl_dinfo->real_band[RTW89_PHY_0] == RTW89_BAND_2G)
4361 gwl = BTC_GNT_HW;
4362 else
4363 gwl = BTC_GNT_SW_HI;
4364 _set_gnt_v1(rtwdev, BTC_PHY_0, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4365
4366 if (wl_dinfo->real_band[RTW89_PHY_1] == RTW89_BAND_2G)
4367 gwl = BTC_GNT_HW;
4368 else
4369 gwl = BTC_GNT_SW_HI;
4370 _set_gnt_v1(rtwdev, BTC_PHY_1, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4371 } else {
4372 gwl = BTC_GNT_HW;
4373 _set_gnt_v1(rtwdev, phy_map, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4374 }
4375 break;
4376 case BTC_ANT_W5G:
4377 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW, BTC_WLACT_HW);
4378 break;
4379 case BTC_ANT_FREERUN:
4380 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI,
4381 BTC_WLACT_SW_LO);
4382 break;
4383 case BTC_ANT_WRFK:
4384 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4385 BTC_WLACT_HW);
4386 break;
4387 case BTC_ANT_WRFK2:
4388 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4389 BTC_WLACT_SW_HI); /* no BT-Tx */
4390 break;
4391 default:
4392 return;
4393 }
4394
4395 _set_bt_plut(rtwdev, phy_map, BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
4396 }
4397
_set_ant(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4398 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
4399 u8 phy_map, u8 type)
4400 {
4401 if (rtwdev->chip->chip_id == RTL8922A)
4402 _set_ant_v1(rtwdev, force_exec, phy_map, type);
4403 else
4404 _set_ant_v0(rtwdev, force_exec, phy_map, type);
4405 }
4406
_action_wl_only(struct rtw89_dev * rtwdev)4407 static void _action_wl_only(struct rtw89_dev *rtwdev)
4408 {
4409 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
4410 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY);
4411 }
4412
_action_wl_init(struct rtw89_dev * rtwdev)4413 static void _action_wl_init(struct rtw89_dev *rtwdev)
4414 {
4415 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4416
4417 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT);
4418 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT);
4419 }
4420
_action_wl_off(struct rtw89_dev * rtwdev,u8 mode)4421 static void _action_wl_off(struct rtw89_dev *rtwdev, u8 mode)
4422 {
4423 struct rtw89_btc *btc = &rtwdev->btc;
4424 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4425
4426 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4427
4428 if (wl->status.map.rf_off || btc->dm.bt_only) {
4429 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF);
4430 } else if (wl->status.map.lps == BTC_LPS_RF_ON) {
4431 if (mode == BTC_WLINK_5G)
4432 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
4433 else
4434 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4435 }
4436
4437 if (mode == BTC_WLINK_5G) {
4438 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OFF);
4439 } else if (wl->status.map.lps == BTC_LPS_RF_ON) {
4440 if (btc->cx.bt.link_info.a2dp_desc.active)
4441 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
4442 else
4443 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_WL_OFF);
4444 } else {
4445 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
4446 }
4447 }
4448
_action_freerun(struct rtw89_dev * rtwdev)4449 static void _action_freerun(struct rtw89_dev *rtwdev)
4450 {
4451 struct rtw89_btc *btc = &rtwdev->btc;
4452
4453 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4454
4455 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN);
4456 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN);
4457
4458 btc->dm.freerun = true;
4459 }
4460
_action_bt_whql(struct rtw89_dev * rtwdev)4461 static void _action_bt_whql(struct rtw89_dev *rtwdev)
4462 {
4463 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4464
4465 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4466 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL);
4467 }
4468
_action_bt_off(struct rtw89_dev * rtwdev)4469 static void _action_bt_off(struct rtw89_dev *rtwdev)
4470 {
4471 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4472
4473 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
4474 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF);
4475 }
4476
_action_bt_idle(struct rtw89_dev * rtwdev)4477 static void _action_bt_idle(struct rtw89_dev *rtwdev)
4478 {
4479 struct rtw89_btc *btc = &rtwdev->btc;
4480 struct rtw89_btc_bt_link_info *b = &btc->cx.bt.link_info;
4481 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4482
4483 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4484
4485 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
4486 switch (btc->cx.state_map) {
4487 case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/
4488 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */
4489 if (b->status.map.connect)
4490 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_IDLE);
4491 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
4492 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_DL, BTC_ACT_BT_IDLE);
4493 else
4494 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_UL, BTC_ACT_BT_IDLE);
4495 break;
4496 case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */
4497 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050,
4498 BTC_ACT_BT_IDLE);
4499 break;
4500 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */
4501 _set_policy(rtwdev, BTC_CXP_FIX_TD5050,
4502 BTC_ACT_BT_IDLE);
4503 break;
4504 case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */
4505 _set_policy(rtwdev, BTC_CXP_FIX_TD7010,
4506 BTC_ACT_BT_IDLE);
4507 break;
4508 case BTC_WIDLE: /* wl-idle + bt-idle */
4509 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE);
4510 break;
4511 }
4512 } else { /* dedicated-antenna */
4513 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE);
4514 }
4515 }
4516
_action_bt_hfp(struct rtw89_dev * rtwdev)4517 static void _action_bt_hfp(struct rtw89_dev *rtwdev)
4518 {
4519 struct rtw89_btc *btc = &rtwdev->btc;
4520 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4521
4522 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4523
4524 if (btc->ant_type == BTC_ANT_SHARED) {
4525 if (btc->cx.wl.status.map._4way) {
4526 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP);
4527 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4528 btc->cx.bt.scan_rx_low_pri = true;
4529 _set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP);
4530 } else {
4531 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
4532 }
4533 } else {
4534 if (wl->bg_mode)
4535 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
4536 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
4537 _set_policy(rtwdev, BTC_CXP_OFF_EQ5, BTC_ACT_BT_HFP);
4538 else
4539 _set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP);
4540 }
4541 }
4542
_action_bt_hid(struct rtw89_dev * rtwdev)4543 static void _action_bt_hid(struct rtw89_dev *rtwdev)
4544 {
4545 const struct rtw89_chip_info *chip = rtwdev->chip;
4546 struct rtw89_btc *btc = &rtwdev->btc;
4547 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4548 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4549 struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc;
4550 u16 policy_type = BTC_CXP_OFF_BT;
4551
4552 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4553
4554 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
4555 if (wl->status.map._4way) {
4556 policy_type = BTC_CXP_OFF_WL;
4557 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4558 btc->cx.bt.scan_rx_low_pri = true;
4559 if (hid->type & BTC_HID_BLE)
4560 policy_type = BTC_CXP_OFF_BWB0;
4561 else
4562 policy_type = BTC_CXP_OFF_BWB2;
4563 } else if (hid->type == BTC_HID_218) {
4564 bt->scan_rx_low_pri = true;
4565 policy_type = BTC_CXP_OFF_BWB2;
4566 } else if (chip->para_ver == 0x1) {
4567 policy_type = BTC_CXP_OFF_BWB3;
4568 } else {
4569 policy_type = BTC_CXP_OFF_BWB1;
4570 }
4571 } else { /* dedicated-antenna */
4572 if (wl->bg_mode)
4573 policy_type = BTC_CXP_OFF_BWB1;
4574 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
4575 policy_type = BTC_CXP_OFF_EQ4;
4576 else
4577 policy_type = BTC_CXP_OFF_EQ3;
4578 }
4579
4580 _set_policy(rtwdev, policy_type, BTC_ACT_BT_HID);
4581 }
4582
_action_bt_a2dp(struct rtw89_dev * rtwdev)4583 static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
4584 {
4585 struct rtw89_btc *btc = &rtwdev->btc;
4586 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
4587 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
4588 struct rtw89_btc_dm *dm = &btc->dm;
4589
4590 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4591
4592 switch (btc->cx.state_map) {
4593 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
4594 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
4595 dm->slot_dur[CXST_W1] = 40;
4596 dm->slot_dur[CXST_B1] = 200;
4597 _set_policy(rtwdev,
4598 BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
4599 } else {
4600 _set_policy(rtwdev,
4601 BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP);
4602 }
4603 break;
4604 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
4605 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP);
4606 break;
4607 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */
4608 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP);
4609 break;
4610 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
4611 case BTC_WLINKING: /* wl-connecting + bt-A2DP */
4612 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
4613 dm->slot_dur[CXST_W1] = 40;
4614 dm->slot_dur[CXST_B1] = 200;
4615 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
4616 BTC_ACT_BT_A2DP);
4617 } else {
4618 _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
4619 BTC_ACT_BT_A2DP);
4620 }
4621 break;
4622 case BTC_WIDLE: /* wl-idle + bt-A2DP */
4623 _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP);
4624 break;
4625 }
4626 }
4627
_action_bt_a2dpsink(struct rtw89_dev * rtwdev)4628 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev)
4629 {
4630 struct rtw89_btc *btc = &rtwdev->btc;
4631
4632 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4633
4634 switch (btc->cx.state_map) {
4635 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */
4636 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK);
4637 break;
4638 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */
4639 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK);
4640 break;
4641 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */
4642 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK);
4643 break;
4644 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */
4645 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK);
4646 break;
4647 case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */
4648 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
4649 break;
4650 case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */
4651 _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK);
4652 break;
4653 }
4654 }
4655
_action_bt_pan(struct rtw89_dev * rtwdev)4656 static void _action_bt_pan(struct rtw89_dev *rtwdev)
4657 {
4658 struct rtw89_btc *btc = &rtwdev->btc;
4659 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
4660 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
4661 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
4662
4663 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4664
4665 switch (btc->cx.state_map) {
4666 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */
4667 if (a2dp.active || !pan.exist) {
4668 btc->dm.slot_dur[CXST_W1] = 80;
4669 btc->dm.slot_dur[CXST_B1] = 20;
4670 _set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN);
4671 } else {
4672 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
4673 }
4674 break;
4675 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */
4676 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN);
4677 break;
4678 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */
4679 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN);
4680 break;
4681 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */
4682 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN);
4683 break;
4684 case BTC_WLINKING: /* wl-connecting + bt-PAN */
4685 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO, BTC_ACT_BT_PAN);
4686 break;
4687 case BTC_WIDLE: /* wl-idle + bt-pan */
4688 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN);
4689 break;
4690 }
4691 }
4692
_action_bt_a2dp_hid(struct rtw89_dev * rtwdev)4693 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
4694 {
4695 struct rtw89_btc *btc = &rtwdev->btc;
4696 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
4697 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
4698 struct rtw89_btc_dm *dm = &btc->dm;
4699
4700 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4701
4702 switch (btc->cx.state_map) {
4703 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */
4704 case BTC_WIDLE: /* wl-idle + bt-A2DP */
4705 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
4706 dm->slot_dur[CXST_W1] = 40;
4707 dm->slot_dur[CXST_B1] = 200;
4708 _set_policy(rtwdev,
4709 BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
4710 } else {
4711 _set_policy(rtwdev,
4712 BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP_HID);
4713 }
4714 break;
4715 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */
4716 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
4717 break;
4718
4719 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */
4720 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
4721 break;
4722 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */
4723 case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */
4724 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
4725 dm->slot_dur[CXST_W1] = 40;
4726 dm->slot_dur[CXST_B1] = 200;
4727 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
4728 BTC_ACT_BT_A2DP_HID);
4729 } else {
4730 _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
4731 BTC_ACT_BT_A2DP_HID);
4732 }
4733 break;
4734 }
4735 }
4736
_action_bt_a2dp_pan(struct rtw89_dev * rtwdev)4737 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev)
4738 {
4739 struct rtw89_btc *btc = &rtwdev->btc;
4740
4741 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4742
4743 switch (btc->cx.state_map) {
4744 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */
4745 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
4746 break;
4747 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */
4748 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
4749 break;
4750 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */
4751 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN);
4752 break;
4753 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */
4754 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
4755 break;
4756 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */
4757 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN);
4758 break;
4759 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */
4760 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN);
4761 break;
4762 }
4763 }
4764
_action_bt_pan_hid(struct rtw89_dev * rtwdev)4765 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev)
4766 {
4767 struct rtw89_btc *btc = &rtwdev->btc;
4768
4769 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4770
4771 switch (btc->cx.state_map) {
4772 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */
4773 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID);
4774 break;
4775 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */
4776 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID);
4777 break;
4778 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */
4779 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID);
4780 break;
4781 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */
4782 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID);
4783 break;
4784 case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */
4785 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID);
4786 break;
4787 case BTC_WIDLE: /* wl-idle + bt-PAN+HID */
4788 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID);
4789 break;
4790 }
4791 }
4792
_action_bt_a2dp_pan_hid(struct rtw89_dev * rtwdev)4793 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev)
4794 {
4795 struct rtw89_btc *btc = &rtwdev->btc;
4796
4797 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4798
4799 switch (btc->cx.state_map) {
4800 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */
4801 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
4802 BTC_ACT_BT_A2DP_PAN_HID);
4803 break;
4804 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */
4805 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
4806 BTC_ACT_BT_A2DP_PAN_HID);
4807 break;
4808 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */
4809 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070,
4810 BTC_ACT_BT_A2DP_PAN_HID);
4811 break;
4812 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */
4813 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */
4814 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050,
4815 BTC_ACT_BT_A2DP_PAN_HID);
4816 break;
4817 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */
4818 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080,
4819 BTC_ACT_BT_A2DP_PAN_HID);
4820 break;
4821 }
4822 }
4823
_action_wl_5g(struct rtw89_dev * rtwdev)4824 static void _action_wl_5g(struct rtw89_dev *rtwdev)
4825 {
4826 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
4827 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G);
4828 }
4829
_action_wl_other(struct rtw89_dev * rtwdev)4830 static void _action_wl_other(struct rtw89_dev *rtwdev)
4831 {
4832 struct rtw89_btc *btc = &rtwdev->btc;
4833
4834 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4835
4836 if (btc->ant_type == BTC_ANT_SHARED)
4837 _set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER);
4838 else
4839 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER);
4840 }
4841
_action_wl_nc(struct rtw89_dev * rtwdev)4842 static void _action_wl_nc(struct rtw89_dev *rtwdev)
4843 {
4844 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4845 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC);
4846 }
4847
_action_wl_rfk(struct rtw89_dev * rtwdev)4848 static void _action_wl_rfk(struct rtw89_dev *rtwdev)
4849 {
4850 struct rtw89_btc *btc = &rtwdev->btc;
4851 struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info;
4852
4853 if (rfk.state != BTC_WRFK_START)
4854 return;
4855
4856 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n",
4857 __func__, rfk.band);
4858
4859 btc->dm.tdma_instant_excute = 1;
4860
4861 if (rfk.state == BTC_WRFK_ONESHOT_START ||
4862 btc->ant_type == BTC_ANT_SHARED) {
4863 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2);
4864 _set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK);
4865 } else {
4866 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
4867 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK);
4868 }
4869 }
4870
_set_btg_ctrl(struct rtw89_dev * rtwdev)4871 static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
4872 {
4873 struct rtw89_btc *btc = &rtwdev->btc;
4874 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4875 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
4876 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
4877 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
4878 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
4879 struct rtw89_btc_wl_role_info *wl_rinfo_v0 = &wl->role_info;
4880 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4881 const struct rtw89_chip_info *chip = rtwdev->chip;
4882 const struct rtw89_btc_ver *ver = btc->ver;
4883 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4884 struct rtw89_btc_dm *dm = &btc->dm;
4885 struct _wl_rinfo_now wl_rinfo;
4886 u32 run_reason = btc->dm.run_reason;
4887 u32 is_btg;
4888 u8 i, val;
4889
4890 if (btc->manual_ctrl)
4891 return;
4892
4893 if (ver->fwlrole == 0)
4894 wl_rinfo.link_mode = wl_rinfo_v0->link_mode;
4895 else if (ver->fwlrole == 1)
4896 wl_rinfo.link_mode = wl_rinfo_v1->link_mode;
4897 else if (ver->fwlrole == 2)
4898 wl_rinfo.link_mode = wl_rinfo_v2->link_mode;
4899 else if (ver->fwlrole == 7)
4900 wl_rinfo.link_mode = wl_rinfo_v7->link_mode;
4901 else if (ver->fwlrole == 8)
4902 wl_rinfo.link_mode = wl_rinfo_v8->link_mode;
4903 else
4904 return;
4905
4906 if (rtwdev->dbcc_en) {
4907 if (ver->fwlrole == 0) {
4908 wl_rinfo.dbcc_2g_phy = RTW89_PHY_MAX;
4909
4910 for (i = 0; i < RTW89_PHY_MAX; i++) {
4911 if (wl_dinfo->real_band[i] == RTW89_BAND_2G)
4912 wl_rinfo.dbcc_2g_phy = i;
4913 }
4914 } else if (ver->fwlrole == 1) {
4915 wl_rinfo.dbcc_2g_phy = wl_rinfo_v1->dbcc_2g_phy;
4916 } else if (ver->fwlrole == 2) {
4917 wl_rinfo.dbcc_2g_phy = wl_rinfo_v2->dbcc_2g_phy;
4918 } else if (ver->fwlrole == 7) {
4919 wl_rinfo.dbcc_2g_phy = wl_rinfo_v7->dbcc_2g_phy;
4920 } else if (ver->fwlrole == 8) {
4921 wl_rinfo.dbcc_2g_phy = wl_rinfo_v8->dbcc_2g_phy;
4922 } else {
4923 return;
4924 }
4925 }
4926
4927 if (wl_rinfo.link_mode == BTC_WLINK_25G_MCC)
4928 is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL;
4929 else if (!(bt->run_patch_code && bt->enable.now))
4930 is_btg = BTC_BTGCTRL_DISABLE;
4931 else if (wl_rinfo.link_mode == BTC_WLINK_5G)
4932 is_btg = BTC_BTGCTRL_DISABLE;
4933 else if (dm->freerun)
4934 is_btg = BTC_BTGCTRL_DISABLE;
4935 else if (rtwdev->dbcc_en && wl_rinfo.dbcc_2g_phy != RTW89_PHY_1)
4936 is_btg = BTC_BTGCTRL_DISABLE;
4937 else
4938 is_btg = BTC_BTGCTRL_ENABLE;
4939
4940 if (dm->wl_btg_rx_rb != dm->wl_btg_rx &&
4941 dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) {
4942 _get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX, &val);
4943 dm->wl_btg_rx_rb = val;
4944 }
4945
4946 if (run_reason == BTC_RSN_NTFY_INIT ||
4947 run_reason == BTC_RSN_NTFY_SWBAND ||
4948 dm->wl_btg_rx_rb != dm->wl_btg_rx ||
4949 is_btg != dm->wl_btg_rx) {
4950
4951 dm->wl_btg_rx = is_btg;
4952
4953 if (is_btg > BTC_BTGCTRL_ENABLE)
4954 return;
4955
4956 chip->ops->ctrl_btg_bt_rx(rtwdev, is_btg, RTW89_PHY_0);
4957 }
4958 }
4959
_set_wl_preagc_ctrl(struct rtw89_dev * rtwdev)4960 static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev)
4961 {
4962 struct rtw89_btc *btc = &rtwdev->btc;
4963 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
4964 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4965 struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2;
4966 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
4967 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8;
4968 const struct rtw89_chip_info *chip = rtwdev->chip;
4969 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4970 struct rtw89_btc_dm *dm = &btc->dm;
4971 u8 is_preagc, val, link_mode, dbcc_2g_phy;
4972 u8 role_ver = rtwdev->btc.ver->fwlrole;
4973 bool dbcc_en;
4974
4975 if (btc->manual_ctrl)
4976 return;
4977
4978 if (role_ver == 2) {
4979 dbcc_en = rinfo_v2->dbcc_en;
4980 link_mode = rinfo_v2->link_mode;
4981 dbcc_2g_phy = rinfo_v2->dbcc_2g_phy;
4982 } else if (role_ver == 7) {
4983 dbcc_en = rinfo_v7->dbcc_en;
4984 link_mode = rinfo_v7->link_mode;
4985 dbcc_2g_phy = rinfo_v7->dbcc_2g_phy;
4986 } else if (role_ver == 8) {
4987 dbcc_en = rinfo_v8->dbcc_en;
4988 link_mode = rinfo_v8->link_mode;
4989 dbcc_2g_phy = rinfo_v7->dbcc_2g_phy;
4990 } else {
4991 return;
4992 }
4993
4994 if (link_mode == BTC_WLINK_25G_MCC) {
4995 is_preagc = BTC_PREAGC_BB_FWCTRL;
4996 } else if (!(bt->run_patch_code && bt->enable.now)) {
4997 is_preagc = BTC_PREAGC_DISABLE;
4998 } else if (link_mode == BTC_WLINK_5G) {
4999 is_preagc = BTC_PREAGC_DISABLE;
5000 } else if (link_mode == BTC_WLINK_NOLINK ||
5001 btc->cx.bt.link_info.profile_cnt.now == 0) {
5002 is_preagc = BTC_PREAGC_DISABLE;
5003 } else if (dm->tdma_now.type != CXTDMA_OFF &&
5004 !bt_linfo->hfp_desc.exist &&
5005 !bt_linfo->hid_desc.exist &&
5006 dm->fddt_train == BTC_FDDT_DISABLE) {
5007 is_preagc = BTC_PREAGC_DISABLE;
5008 } else if (dbcc_en && (dbcc_2g_phy != RTW89_PHY_1)) {
5009 is_preagc = BTC_PREAGC_DISABLE;
5010 } else if (btc->ant_type == BTC_ANT_SHARED) {
5011 is_preagc = BTC_PREAGC_DISABLE;
5012 } else {
5013 is_preagc = BTC_PREAGC_ENABLE;
5014 }
5015
5016 if (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
5017 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) {
5018 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val);
5019 dm->wl_pre_agc_rb = val;
5020 }
5021
5022 if ((wl->coex_mode == BTC_MODE_NORMAL &&
5023 (dm->run_reason == BTC_RSN_NTFY_INIT ||
5024 dm->run_reason == BTC_RSN_NTFY_SWBAND ||
5025 dm->wl_pre_agc_rb != dm->wl_pre_agc)) ||
5026 is_preagc != dm->wl_pre_agc) {
5027 dm->wl_pre_agc = is_preagc;
5028
5029 if (is_preagc > BTC_PREAGC_ENABLE)
5030 return;
5031 chip->ops->ctrl_nbtg_bt_tx(rtwdev, dm->wl_pre_agc, RTW89_PHY_0);
5032 }
5033 }
5034
5035 struct rtw89_txtime_data {
5036 struct rtw89_dev *rtwdev;
5037 int type;
5038 u32 tx_time;
5039 u8 tx_retry;
5040 u16 enable;
5041 bool reenable;
5042 };
5043
__rtw89_tx_time_iter(struct rtw89_vif_link * rtwvif_link,struct rtw89_sta_link * rtwsta_link,struct rtw89_txtime_data * iter_data)5044 static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link,
5045 struct rtw89_sta_link *rtwsta_link,
5046 struct rtw89_txtime_data *iter_data)
5047 {
5048 struct rtw89_dev *rtwdev = iter_data->rtwdev;
5049 struct rtw89_btc *btc = &rtwdev->btc;
5050 struct rtw89_btc_cx *cx = &btc->cx;
5051 struct rtw89_btc_wl_info *wl = &cx->wl;
5052 struct rtw89_btc_wl_link_info *plink = NULL;
5053 u8 port = rtwvif_link->port;
5054 u32 tx_time = iter_data->tx_time;
5055 u8 tx_retry = iter_data->tx_retry;
5056 u16 enable = iter_data->enable;
5057 bool reenable = iter_data->reenable;
5058
5059 if (btc->ver->fwlrole == 8)
5060 plink = &wl->rlink_info[port][0];
5061 else
5062 plink = &wl->link_info[port];
5063
5064 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5065 "[BTC], %s(): port = %d\n", __func__, port);
5066
5067 if (!plink->connected) {
5068 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5069 "[BTC], %s(): connected = %d\n",
5070 __func__, plink->connected);
5071 return;
5072 }
5073
5074 /* backup the original tx time before tx-limit on */
5075 if (reenable) {
5076 rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time);
5077 rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry);
5078 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5079 "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n",
5080 __func__, plink->tx_time, plink->tx_retry);
5081 }
5082
5083 /* restore the original tx time if no tx-limit */
5084 if (!enable) {
5085 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time);
5086 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true,
5087 plink->tx_retry);
5088 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5089 "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n",
5090 __func__, plink->tx_time, plink->tx_retry);
5091
5092 } else {
5093 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time);
5094 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry);
5095 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5096 "[BTC], %s(): set, tx_time=%d tx_retry= %d\n",
5097 __func__, tx_time, tx_retry);
5098 }
5099 }
5100
rtw89_tx_time_iter(void * data,struct ieee80211_sta * sta)5101 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
5102 {
5103 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
5104 struct rtw89_txtime_data *iter_data =
5105 (struct rtw89_txtime_data *)data;
5106 struct rtw89_vif_link *rtwvif_link;
5107 struct rtw89_sta_link *rtwsta_link;
5108 unsigned int link_id;
5109
5110 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
5111 rtwvif_link = rtwsta_link->rtwvif_link;
5112 __rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data);
5113 }
5114 }
5115
_set_wl_tx_limit(struct rtw89_dev * rtwdev)5116 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
5117 {
5118 struct rtw89_btc *btc = &rtwdev->btc;
5119 const struct rtw89_btc_ver *ver = btc->ver;
5120 struct rtw89_btc_cx *cx = &btc->cx;
5121 struct rtw89_btc_dm *dm = &btc->dm;
5122 struct rtw89_btc_wl_info *wl = &cx->wl;
5123 struct rtw89_btc_bt_info *bt = &cx->bt;
5124 struct rtw89_btc_bt_link_info *b = &bt->link_info;
5125 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
5126 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
5127 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5128 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5129 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5130 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
5131 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5132 struct rtw89_txtime_data data = {.rtwdev = rtwdev};
5133 u8 mode, igno_bt, tx_retry;
5134 u32 tx_time;
5135 u16 enable;
5136 bool reenable = false;
5137
5138 if (btc->manual_ctrl)
5139 return;
5140
5141 if (ver->fwlrole == 0)
5142 mode = wl_rinfo->link_mode;
5143 else if (ver->fwlrole == 1)
5144 mode = wl_rinfo_v1->link_mode;
5145 else if (ver->fwlrole == 2)
5146 mode = wl_rinfo_v2->link_mode;
5147 else if (ver->fwlrole == 7)
5148 mode = wl_rinfo_v7->link_mode;
5149 else if (ver->fwlrole == 8)
5150 mode = wl_rinfo_v8->link_mode;
5151 else
5152 return;
5153
5154 if (ver->fcxctrl == 7)
5155 igno_bt = btc->ctrl.ctrl_v7.igno_bt;
5156 else
5157 igno_bt = btc->ctrl.ctrl.igno_bt;
5158
5159 if (btc->dm.freerun || igno_bt || b->profile_cnt.now == 0 ||
5160 mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) {
5161 enable = 0;
5162 tx_time = BTC_MAX_TX_TIME_DEF;
5163 tx_retry = BTC_MAX_TX_RETRY_DEF;
5164 } else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) {
5165 enable = 1;
5166 tx_time = BTC_MAX_TX_TIME_L2;
5167 tx_retry = BTC_MAX_TX_RETRY_L1;
5168 } else if (hfp->exist || hid->exist) {
5169 enable = 1;
5170 tx_time = BTC_MAX_TX_TIME_L3;
5171 tx_retry = BTC_MAX_TX_RETRY_L1;
5172 } else {
5173 enable = 0;
5174 tx_time = BTC_MAX_TX_TIME_DEF;
5175 tx_retry = BTC_MAX_TX_RETRY_DEF;
5176 }
5177
5178 if (dm->wl_tx_limit.enable == enable &&
5179 dm->wl_tx_limit.tx_time == tx_time &&
5180 dm->wl_tx_limit.tx_retry == tx_retry)
5181 return;
5182
5183 if (!dm->wl_tx_limit.enable && enable)
5184 reenable = true;
5185
5186 dm->wl_tx_limit.enable = enable;
5187 dm->wl_tx_limit.tx_time = tx_time;
5188 dm->wl_tx_limit.tx_retry = tx_retry;
5189
5190 data.enable = enable;
5191 data.tx_time = tx_time;
5192 data.tx_retry = tx_retry;
5193 data.reenable = reenable;
5194
5195 ieee80211_iterate_stations_atomic(rtwdev->hw,
5196 rtw89_tx_time_iter,
5197 &data);
5198 }
5199
_set_bt_rx_agc(struct rtw89_dev * rtwdev)5200 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
5201 {
5202 struct rtw89_btc *btc = &rtwdev->btc;
5203 const struct rtw89_btc_ver *ver = btc->ver;
5204 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5205 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5206 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5207 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5208 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
5209 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5210 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5211 bool bt_hi_lna_rx = false;
5212 u8 mode;
5213
5214 if (ver->fwlrole == 0)
5215 mode = wl_rinfo->link_mode;
5216 else if (ver->fwlrole == 1)
5217 mode = wl_rinfo_v1->link_mode;
5218 else if (ver->fwlrole == 2)
5219 mode = wl_rinfo_v2->link_mode;
5220 else if (ver->fwlrole == 7)
5221 mode = wl_rinfo_v7->link_mode;
5222 else if (ver->fwlrole == 8)
5223 mode = wl_rinfo_v8->link_mode;
5224 else
5225 return;
5226
5227 if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
5228 bt_hi_lna_rx = true;
5229
5230 if (bt_hi_lna_rx == bt->hi_lna_rx)
5231 return;
5232
5233 _write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx);
5234 }
5235
_set_bt_rx_scan_pri(struct rtw89_dev * rtwdev)5236 static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev)
5237 {
5238 struct rtw89_btc *btc = &rtwdev->btc;
5239 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5240
5241 _write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri));
5242 }
5243
_action_common(struct rtw89_dev * rtwdev)5244 static void _action_common(struct rtw89_dev *rtwdev)
5245 {
5246 struct rtw89_btc *btc = &rtwdev->btc;
5247 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5248 struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
5249 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5250 struct rtw89_btc_dm *dm = &btc->dm;
5251 u32 bt_rom_code_id, bt_fw_ver;
5252
5253 _set_btg_ctrl(rtwdev);
5254 _set_wl_preagc_ctrl(rtwdev);
5255 _set_wl_tx_limit(rtwdev);
5256 _set_bt_afh_info(rtwdev);
5257 _set_bt_rx_agc(rtwdev);
5258 _set_rf_trx_para(rtwdev);
5259 _set_bt_rx_scan_pri(rtwdev);
5260
5261 bt_rom_code_id = chip_id_to_bt_rom_code_id(rtwdev->btc.ver->chip_id);
5262 bt_fw_ver = bt->ver_info.fw & 0xffff;
5263 if (bt->enable.now &&
5264 (bt_fw_ver == 0 ||
5265 (bt_fw_ver == bt_rom_code_id && bt->run_patch_code && rtwdev->chip->scbd)))
5266 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 1);
5267 else
5268 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 0);
5269
5270 if (dm->run_reason == BTC_RSN_NTFY_INIT ||
5271 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE ||
5272 dm->run_reason == BTC_RSN_NTFY_POWEROFF) {
5273 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
5274
5275 if (wl_smap->rf_off == 1 || wl_smap->lps != BTC_LPS_OFF)
5276 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
5277 else
5278 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
5279 }
5280
5281 if (wl->scbd_change) {
5282 rtw89_mac_cfg_sb(rtwdev, wl->scbd);
5283 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n",
5284 wl->scbd);
5285 wl->scbd_change = false;
5286 btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++;
5287 }
5288 btc->dm.tdma_instant_excute = 0;
5289 }
5290
_action_by_bt(struct rtw89_dev * rtwdev)5291 static void _action_by_bt(struct rtw89_dev *rtwdev)
5292 {
5293 struct rtw89_btc *btc = &rtwdev->btc;
5294 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5295 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
5296 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
5297 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
5298 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
5299 struct rtw89_btc_dm *dm = &btc->dm;
5300 u8 profile_map = 0;
5301
5302 if (dm->freerun_chk) {
5303 _action_freerun(rtwdev);
5304 return;
5305 }
5306
5307 if (bt_linfo->hfp_desc.exist)
5308 profile_map |= BTC_BT_HFP;
5309
5310 if (bt_linfo->hid_desc.exist)
5311 profile_map |= BTC_BT_HID;
5312
5313 if (bt_linfo->a2dp_desc.exist)
5314 profile_map |= BTC_BT_A2DP;
5315
5316 if (bt_linfo->pan_desc.exist)
5317 profile_map |= BTC_BT_PAN;
5318
5319 switch (profile_map) {
5320 case BTC_BT_NOPROFILE:
5321 if (pan.active)
5322 _action_bt_pan(rtwdev);
5323 else
5324 _action_bt_idle(rtwdev);
5325 break;
5326 case BTC_BT_HFP:
5327 _action_bt_hfp(rtwdev);
5328 break;
5329 case BTC_BT_HFP | BTC_BT_HID:
5330 case BTC_BT_HID:
5331 _action_bt_hid(rtwdev);
5332 break;
5333 case BTC_BT_A2DP:
5334 if (a2dp.sink)
5335 _action_bt_a2dpsink(rtwdev);
5336 else if (bt_linfo->multi_link.now && !hid.pair_cnt)
5337 _action_bt_a2dp_pan(rtwdev);
5338 else
5339 _action_bt_a2dp(rtwdev);
5340 break;
5341 case BTC_BT_PAN:
5342 _action_bt_pan(rtwdev);
5343 break;
5344 case BTC_BT_A2DP | BTC_BT_HFP:
5345 case BTC_BT_A2DP | BTC_BT_HID:
5346 case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID:
5347 if (a2dp.sink)
5348 _action_bt_a2dpsink(rtwdev);
5349 else if (pan.active)
5350 _action_bt_a2dp_pan_hid(rtwdev);
5351 else
5352 _action_bt_a2dp_hid(rtwdev);
5353 break;
5354 case BTC_BT_A2DP | BTC_BT_PAN:
5355 if (a2dp.sink)
5356 _action_bt_a2dpsink(rtwdev);
5357 else
5358 _action_bt_a2dp_pan(rtwdev);
5359 break;
5360 case BTC_BT_PAN | BTC_BT_HFP:
5361 case BTC_BT_PAN | BTC_BT_HID:
5362 case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID:
5363 _action_bt_pan_hid(rtwdev);
5364 break;
5365 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID:
5366 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP:
5367 default:
5368 if (a2dp.sink)
5369 _action_bt_a2dpsink(rtwdev);
5370 else
5371 _action_bt_a2dp_pan_hid(rtwdev);
5372 break;
5373 }
5374 }
5375
_action_wl_2g_sta(struct rtw89_dev * rtwdev)5376 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev)
5377 {
5378 _action_by_bt(rtwdev);
5379 }
5380
_action_wl_25g_mcc(struct rtw89_dev * rtwdev)5381 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev)
5382 {
5383 struct rtw89_btc *btc = &rtwdev->btc;
5384 u16 policy_type = BTC_CXP_OFF_BT;
5385
5386 if (btc->ant_type == BTC_ANT_SHARED) {
5387 if (btc->cx.wl.status.map._4way)
5388 policy_type = BTC_CXP_OFFE_WL;
5389 else if (btc->cx.wl.status.val & btc_scanning_map.val)
5390 policy_type = BTC_CXP_OFFE_2GBWMIXB;
5391 else if (btc->cx.bt.link_info.status.map.connect == 0)
5392 policy_type = BTC_CXP_OFFE_2GISOB;
5393 else
5394 policy_type = BTC_CXP_OFFE_2GBWISOB;
5395 } else { /* dedicated-antenna */
5396 policy_type = BTC_CXP_OFF_EQ0;
5397 }
5398
5399 btc->dm.e2g_slot_limit = BTC_E2G_LIMIT_DEF;
5400
5401 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
5402 _set_policy(rtwdev, policy_type, BTC_ACT_WL_25G_MCC);
5403 }
5404
_action_wl_scan(struct rtw89_dev * rtwdev)5405 static void _action_wl_scan(struct rtw89_dev *rtwdev)
5406 {
5407 struct rtw89_btc *btc = &rtwdev->btc;
5408 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5409 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5410
5411 if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
5412 _action_wl_25g_mcc(rtwdev);
5413 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n");
5414 } else if (rtwdev->dbcc_en) {
5415 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G &&
5416 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
5417 _action_wl_5g(rtwdev);
5418 else
5419 _action_by_bt(rtwdev);
5420 } else {
5421 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G)
5422 _action_wl_5g(rtwdev);
5423 else
5424 _action_by_bt(rtwdev);
5425 }
5426 }
5427
_action_wl_2g_mcc(struct rtw89_dev * rtwdev)5428 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev)
5429 { struct rtw89_btc *btc = &rtwdev->btc;
5430
5431 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5432
5433 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5434 if (btc->cx.bt.link_info.profile_cnt.now == 0)
5435 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
5436 BTC_ACT_WL_2G_MCC);
5437 else
5438 _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
5439 BTC_ACT_WL_2G_MCC);
5440 } else { /* dedicated-antenna */
5441 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC);
5442 }
5443 }
5444
_action_wl_2g_scc(struct rtw89_dev * rtwdev)5445 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev)
5446 {
5447 struct rtw89_btc *btc = &rtwdev->btc;
5448
5449 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5450
5451 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5452 if (btc->cx.bt.link_info.profile_cnt.now == 0)
5453 _set_policy(rtwdev,
5454 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC);
5455 else
5456 _set_policy(rtwdev,
5457 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC);
5458 } else { /* dedicated-antenna */
5459 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC);
5460 }
5461 }
5462
_action_wl_2g_scc_v1(struct rtw89_dev * rtwdev)5463 static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev)
5464 {
5465 struct rtw89_btc *btc = &rtwdev->btc;
5466 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5467 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5468 struct rtw89_btc_dm *dm = &btc->dm;
5469 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
5470 u16 policy_type = BTC_CXP_OFF_BT;
5471 u32 dur;
5472
5473 if (btc->ant_type == BTC_ANT_DEDICATED) {
5474 policy_type = BTC_CXP_OFF_EQ0;
5475 } else {
5476 /* shared-antenna */
5477 switch (wl_rinfo->mrole_type) {
5478 case BTC_WLMROLE_STA_GC:
5479 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5480 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
5481 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5482 _action_by_bt(rtwdev);
5483 return;
5484 case BTC_WLMROLE_STA_STA:
5485 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5486 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
5487 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5488 _action_by_bt(rtwdev);
5489 return;
5490 case BTC_WLMROLE_STA_GC_NOA:
5491 case BTC_WLMROLE_STA_GO:
5492 case BTC_WLMROLE_STA_GO_NOA:
5493 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5494 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
5495 dur = wl_rinfo->mrole_noa_duration;
5496
5497 if (wl->status.map._4way) {
5498 dm->wl_scc.ebt_null = 0;
5499 policy_type = BTC_CXP_OFFE_WL;
5500 } else if (bt->link_info.status.map.connect == 0) {
5501 dm->wl_scc.ebt_null = 0;
5502 policy_type = BTC_CXP_OFFE_2GISOB;
5503 } else if (bt->link_info.a2dp_desc.exist &&
5504 dur < btc->bt_req_len) {
5505 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5506 policy_type = BTC_CXP_OFFE_2GBWMIXB2;
5507 } else if (bt->link_info.a2dp_desc.exist ||
5508 bt->link_info.pan_desc.exist) {
5509 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5510 policy_type = BTC_CXP_OFFE_2GBWISOB;
5511 } else {
5512 dm->wl_scc.ebt_null = 0;
5513 policy_type = BTC_CXP_OFFE_2GBWISOB;
5514 }
5515 break;
5516 default:
5517 break;
5518 }
5519 }
5520
5521 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5522 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5523 }
5524
_action_wl_2g_scc_v2(struct rtw89_dev * rtwdev)5525 static void _action_wl_2g_scc_v2(struct rtw89_dev *rtwdev)
5526 {
5527 struct rtw89_btc *btc = &rtwdev->btc;
5528 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5529 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5530 struct rtw89_btc_dm *dm = &btc->dm;
5531 struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2;
5532 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
5533 u32 dur, mrole_type, mrole_noa_duration;
5534 u16 policy_type = BTC_CXP_OFF_BT;
5535
5536 if (btc->ver->fwlrole == 2) {
5537 mrole_type = rinfo_v2->mrole_type;
5538 mrole_noa_duration = rinfo_v2->mrole_noa_duration;
5539 } else if (btc->ver->fwlrole == 7) {
5540 mrole_type = rinfo_v7->mrole_type;
5541 mrole_noa_duration = rinfo_v7->mrole_noa_duration;
5542 } else {
5543 return;
5544 }
5545
5546 if (btc->ant_type == BTC_ANT_DEDICATED) {
5547 policy_type = BTC_CXP_OFF_EQ0;
5548 } else {
5549 /* shared-antenna */
5550 switch (mrole_type) {
5551 case BTC_WLMROLE_STA_GC:
5552 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5553 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
5554 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5555 _action_by_bt(rtwdev);
5556 return;
5557 case BTC_WLMROLE_STA_STA:
5558 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5559 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
5560 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5561 _action_by_bt(rtwdev);
5562 return;
5563 case BTC_WLMROLE_STA_GC_NOA:
5564 case BTC_WLMROLE_STA_GO:
5565 case BTC_WLMROLE_STA_GO_NOA:
5566 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5567 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
5568 dur = mrole_noa_duration;
5569
5570 if (wl->status.map._4way) {
5571 dm->wl_scc.ebt_null = 0;
5572 policy_type = BTC_CXP_OFFE_WL;
5573 } else if (bt->link_info.status.map.connect == 0) {
5574 dm->wl_scc.ebt_null = 0;
5575 policy_type = BTC_CXP_OFFE_2GISOB;
5576 } else if (bt->link_info.a2dp_desc.exist &&
5577 dur < btc->bt_req_len) {
5578 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5579 policy_type = BTC_CXP_OFFE_2GBWMIXB2;
5580 } else if (bt->link_info.a2dp_desc.exist ||
5581 bt->link_info.pan_desc.exist) {
5582 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5583 policy_type = BTC_CXP_OFFE_2GBWISOB;
5584 } else {
5585 dm->wl_scc.ebt_null = 0;
5586 policy_type = BTC_CXP_OFFE_2GBWISOB;
5587 }
5588 break;
5589 default:
5590 break;
5591 }
5592 }
5593
5594 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5595 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5596 }
5597
_action_wl_2g_scc_v8(struct rtw89_dev * rtwdev)5598 static void _action_wl_2g_scc_v8(struct rtw89_dev *rtwdev)
5599 {
5600 struct rtw89_btc *btc = &rtwdev->btc;
5601 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5602 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5603 struct rtw89_btc_dm *dm = &btc->dm;
5604 u16 policy_type = BTC_CXP_OFF_BT;
5605
5606 if (btc->ant_type == BTC_ANT_SHARED) {
5607 if (wl->status.map._4way)
5608 policy_type = BTC_CXP_OFFE_WL;
5609 else if (bt->link_info.status.map.connect == 0)
5610 policy_type = BTC_CXP_OFFE_2GISOB;
5611 else
5612 policy_type = BTC_CXP_OFFE_2GBWISOB;
5613 } else {
5614 policy_type = BTC_CXP_OFF_EQ0;
5615 }
5616
5617 dm->e2g_slot_limit = BTC_E2G_LIMIT_DEF;
5618
5619 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5620 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5621 }
5622
_action_wl_2g_ap(struct rtw89_dev * rtwdev)5623 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
5624 {
5625 struct rtw89_btc *btc = &rtwdev->btc;
5626
5627 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5628
5629 if (btc->ant_type == BTC_ANT_SHARED) {
5630 if (btc->cx.bt.link_info.profile_cnt.now == 0)
5631 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
5632 BTC_ACT_WL_2G_AP);
5633 else
5634 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP);
5635 } else {/* dedicated-antenna */
5636 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP);
5637 }
5638 }
5639
_action_wl_2g_go(struct rtw89_dev * rtwdev)5640 static void _action_wl_2g_go(struct rtw89_dev *rtwdev)
5641 {
5642 struct rtw89_btc *btc = &rtwdev->btc;
5643
5644 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5645
5646 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5647 if (btc->cx.bt.link_info.profile_cnt.now == 0)
5648 _set_policy(rtwdev,
5649 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO);
5650 else
5651 _set_policy(rtwdev,
5652 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO);
5653 } else { /* dedicated-antenna */
5654 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO);
5655 }
5656 }
5657
_action_wl_2g_gc(struct rtw89_dev * rtwdev)5658 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev)
5659 {
5660 struct rtw89_btc *btc = &rtwdev->btc;
5661
5662 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5663
5664 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5665 _action_by_bt(rtwdev);
5666 } else {/* dedicated-antenna */
5667 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC);
5668 }
5669 }
5670
_action_wl_2g_nan(struct rtw89_dev * rtwdev)5671 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev)
5672 {
5673 struct rtw89_btc *btc = &rtwdev->btc;
5674
5675 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5676
5677 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5678 if (btc->cx.bt.link_info.profile_cnt.now == 0)
5679 _set_policy(rtwdev,
5680 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN);
5681 else
5682 _set_policy(rtwdev,
5683 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN);
5684 } else { /* dedicated-antenna */
5685 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN);
5686 }
5687 }
5688
_read_scbd(struct rtw89_dev * rtwdev)5689 static u32 _read_scbd(struct rtw89_dev *rtwdev)
5690 {
5691 const struct rtw89_chip_info *chip = rtwdev->chip;
5692 struct rtw89_btc *btc = &rtwdev->btc;
5693 u32 scbd_val = 0;
5694
5695 if (!chip->scbd)
5696 return 0;
5697
5698 scbd_val = rtw89_mac_get_sb(rtwdev);
5699 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n",
5700 scbd_val);
5701
5702 btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++;
5703 return scbd_val;
5704 }
5705
_write_scbd(struct rtw89_dev * rtwdev,u32 val,bool state)5706 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state)
5707 {
5708 const struct rtw89_chip_info *chip = rtwdev->chip;
5709 struct rtw89_btc *btc = &rtwdev->btc;
5710 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5711 u32 scbd_val = 0;
5712 u8 force_exec = false;
5713
5714 if (!chip->scbd)
5715 return;
5716
5717 scbd_val = state ? wl->scbd | val : wl->scbd & ~val;
5718
5719 if (val & BTC_WSCB_ACTIVE || val & BTC_WSCB_ON)
5720 force_exec = true;
5721
5722 if (scbd_val != wl->scbd || force_exec) {
5723 wl->scbd = scbd_val;
5724 wl->scbd_change = true;
5725 }
5726 }
5727
5728 static u8
_update_rssi_state(struct rtw89_dev * rtwdev,u8 pre_state,u8 rssi,u8 thresh)5729 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh)
5730 {
5731 const struct rtw89_chip_info *chip = rtwdev->chip;
5732 u8 next_state, tol = chip->rssi_tol;
5733
5734 if (pre_state == BTC_RSSI_ST_LOW ||
5735 pre_state == BTC_RSSI_ST_STAY_LOW) {
5736 if (rssi >= (thresh + tol))
5737 next_state = BTC_RSSI_ST_HIGH;
5738 else
5739 next_state = BTC_RSSI_ST_STAY_LOW;
5740 } else {
5741 if (rssi < thresh)
5742 next_state = BTC_RSSI_ST_LOW;
5743 else
5744 next_state = BTC_RSSI_ST_STAY_HIGH;
5745 }
5746
5747 return next_state;
5748 }
5749
_wl_req_mac(struct rtw89_dev * rtwdev,u8 mac)5750 static void _wl_req_mac(struct rtw89_dev *rtwdev, u8 mac)
5751 {
5752 if (mac == RTW89_MAC_0)
5753 rtw89_write32_clr(rtwdev, R_AX_BTC_CFG, B_AX_WL_SRC);
5754 else
5755 rtw89_write32_set(rtwdev, R_AX_BTC_CFG, B_AX_WL_SRC);
5756 }
5757
5758 static
_update_dbcc_band(struct rtw89_dev * rtwdev,enum rtw89_phy_idx phy_idx)5759 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
5760 {
5761 struct rtw89_btc *btc = &rtwdev->btc;
5762
5763 btc->cx.wl.dbcc_info.real_band[phy_idx] =
5764 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ?
5765 btc->cx.wl.dbcc_info.scan_band[phy_idx] :
5766 btc->cx.wl.dbcc_info.op_band[phy_idx];
5767 }
5768
_update_wl_info(struct rtw89_dev * rtwdev)5769 static void _update_wl_info(struct rtw89_dev *rtwdev)
5770 {
5771 struct rtw89_btc *btc = &rtwdev->btc;
5772 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5773 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
5774 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5775 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5776 u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
5777 u8 cnt_2g = 0, cnt_5g = 0, phy;
5778 u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0};
5779 bool b2g = false, b5g = false, client_joined = false;
5780
5781 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
5782
5783 for (i = 0; i < RTW89_PORT_NUM; i++) {
5784 /* check if role active? */
5785 if (!wl_linfo[i].active)
5786 continue;
5787
5788 cnt_active++;
5789 wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role;
5790 wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid;
5791 wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy;
5792 wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band;
5793 wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
5794 wl_rinfo->active_role[cnt_active - 1].connected = 0;
5795
5796 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
5797
5798 phy = wl_linfo[i].phy;
5799
5800 /* check dbcc role */
5801 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
5802 wl_dinfo->role[phy] = wl_linfo[i].role;
5803 wl_dinfo->op_band[phy] = wl_linfo[i].band;
5804 _update_dbcc_band(rtwdev, phy);
5805 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
5806 }
5807
5808 if (wl_linfo[i].connected == MLME_NO_LINK) {
5809 continue;
5810 } else if (wl_linfo[i].connected == MLME_LINKING) {
5811 cnt_connecting++;
5812 } else {
5813 cnt_connect++;
5814 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
5815 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
5816 wl_linfo[i].client_cnt > 1)
5817 client_joined = true;
5818 }
5819
5820 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
5821 wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch;
5822 wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw;
5823 wl_rinfo->active_role[cnt_active - 1].connected = 1;
5824
5825 /* only care 2 roles + BT coex */
5826 if (wl_linfo[i].band != RTW89_BAND_2G) {
5827 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
5828 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
5829 cnt_5g++;
5830 b5g = true;
5831 } else {
5832 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
5833 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
5834 cnt_2g++;
5835 b2g = true;
5836 }
5837 }
5838
5839 wl_rinfo->connect_cnt = cnt_connect;
5840
5841 /* Be careful to change the following sequence!! */
5842 if (cnt_connect == 0) {
5843 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
5844 wl_rinfo->role_map.role.none = 1;
5845 } else if (!b2g && b5g) {
5846 wl_rinfo->link_mode = BTC_WLINK_5G;
5847 } else if (wl_rinfo->role_map.role.nan) {
5848 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
5849 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
5850 wl_rinfo->link_mode = BTC_WLINK_OTHER;
5851 } else if (b2g && b5g && cnt_connect == 2) {
5852 if (rtwdev->dbcc_en) {
5853 switch (wl_dinfo->role[RTW89_PHY_0]) {
5854 case RTW89_WIFI_ROLE_STATION:
5855 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
5856 break;
5857 case RTW89_WIFI_ROLE_P2P_GO:
5858 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
5859 break;
5860 case RTW89_WIFI_ROLE_P2P_CLIENT:
5861 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
5862 break;
5863 case RTW89_WIFI_ROLE_AP:
5864 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
5865 break;
5866 default:
5867 wl_rinfo->link_mode = BTC_WLINK_OTHER;
5868 break;
5869 }
5870 } else {
5871 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
5872 }
5873 } else if (!b5g && cnt_connect == 2) {
5874 if (wl_rinfo->role_map.role.station &&
5875 (wl_rinfo->role_map.role.p2p_go ||
5876 wl_rinfo->role_map.role.p2p_gc ||
5877 wl_rinfo->role_map.role.ap)) {
5878 if (wl_2g_ch[0] == wl_2g_ch[1])
5879 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
5880 else
5881 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
5882 } else {
5883 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
5884 }
5885 } else if (!b5g && cnt_connect == 1) {
5886 if (wl_rinfo->role_map.role.station)
5887 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
5888 else if (wl_rinfo->role_map.role.ap)
5889 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
5890 else if (wl_rinfo->role_map.role.p2p_go)
5891 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
5892 else if (wl_rinfo->role_map.role.p2p_gc)
5893 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
5894 else
5895 wl_rinfo->link_mode = BTC_WLINK_OTHER;
5896 }
5897
5898 /* if no client_joined, don't care P2P-GO/AP role */
5899 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
5900 if (!client_joined) {
5901 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
5902 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
5903 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
5904 wl_rinfo->connect_cnt = 1;
5905 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
5906 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
5907 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
5908 wl_rinfo->connect_cnt = 0;
5909 }
5910 }
5911 }
5912
5913 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5914 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
5915 cnt_connect, cnt_connecting, wl_rinfo->link_mode);
5916
5917 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
5918 }
5919
_update_wl_info_v1(struct rtw89_dev * rtwdev)5920 static void _update_wl_info_v1(struct rtw89_dev *rtwdev)
5921 {
5922 struct rtw89_btc *btc = &rtwdev->btc;
5923 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5924 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
5925 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
5926 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5927 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
5928 u8 cnt_2g = 0, cnt_5g = 0, phy;
5929 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
5930 bool b2g = false, b5g = false, client_joined = false;
5931 u8 i;
5932
5933 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
5934
5935 for (i = 0; i < RTW89_PORT_NUM; i++) {
5936 if (!wl_linfo[i].active)
5937 continue;
5938
5939 cnt_active++;
5940 wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role;
5941 wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid;
5942 wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy;
5943 wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band;
5944 wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
5945 wl_rinfo->active_role_v1[cnt_active - 1].connected = 0;
5946
5947 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
5948
5949 phy = wl_linfo[i].phy;
5950
5951 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
5952 wl_dinfo->role[phy] = wl_linfo[i].role;
5953 wl_dinfo->op_band[phy] = wl_linfo[i].band;
5954 _update_dbcc_band(rtwdev, phy);
5955 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
5956 }
5957
5958 if (wl_linfo[i].connected == MLME_NO_LINK) {
5959 continue;
5960 } else if (wl_linfo[i].connected == MLME_LINKING) {
5961 cnt_connecting++;
5962 } else {
5963 cnt_connect++;
5964 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
5965 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
5966 wl_linfo[i].client_cnt > 1)
5967 client_joined = true;
5968 }
5969
5970 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
5971 wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch;
5972 wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw;
5973 wl_rinfo->active_role_v1[cnt_active - 1].connected = 1;
5974
5975 /* only care 2 roles + BT coex */
5976 if (wl_linfo[i].band != RTW89_BAND_2G) {
5977 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
5978 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
5979 cnt_5g++;
5980 b5g = true;
5981 } else {
5982 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
5983 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
5984 cnt_2g++;
5985 b2g = true;
5986 }
5987 }
5988
5989 wl_rinfo->connect_cnt = cnt_connect;
5990
5991 /* Be careful to change the following sequence!! */
5992 if (cnt_connect == 0) {
5993 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
5994 wl_rinfo->role_map.role.none = 1;
5995 } else if (!b2g && b5g) {
5996 wl_rinfo->link_mode = BTC_WLINK_5G;
5997 } else if (wl_rinfo->role_map.role.nan) {
5998 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
5999 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
6000 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6001 } else if (b2g && b5g && cnt_connect == 2) {
6002 if (rtwdev->dbcc_en) {
6003 switch (wl_dinfo->role[RTW89_PHY_0]) {
6004 case RTW89_WIFI_ROLE_STATION:
6005 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6006 break;
6007 case RTW89_WIFI_ROLE_P2P_GO:
6008 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6009 break;
6010 case RTW89_WIFI_ROLE_P2P_CLIENT:
6011 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6012 break;
6013 case RTW89_WIFI_ROLE_AP:
6014 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6015 break;
6016 default:
6017 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6018 break;
6019 }
6020 } else {
6021 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
6022 }
6023 } else if (!b5g && cnt_connect == 2) {
6024 if (wl_rinfo->role_map.role.station &&
6025 (wl_rinfo->role_map.role.p2p_go ||
6026 wl_rinfo->role_map.role.p2p_gc ||
6027 wl_rinfo->role_map.role.ap)) {
6028 if (wl_2g_ch[0] == wl_2g_ch[1])
6029 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
6030 else
6031 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6032 } else {
6033 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6034 }
6035 } else if (!b5g && cnt_connect == 1) {
6036 if (wl_rinfo->role_map.role.station)
6037 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6038 else if (wl_rinfo->role_map.role.ap)
6039 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6040 else if (wl_rinfo->role_map.role.p2p_go)
6041 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6042 else if (wl_rinfo->role_map.role.p2p_gc)
6043 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6044 else
6045 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6046 }
6047
6048 /* if no client_joined, don't care P2P-GO/AP role */
6049 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6050 if (!client_joined) {
6051 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6052 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6053 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6054 wl_rinfo->connect_cnt = 1;
6055 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6056 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6057 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6058 wl_rinfo->connect_cnt = 0;
6059 }
6060 }
6061 }
6062
6063 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6064 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6065 cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6066
6067 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6068 }
6069
_update_wl_info_v2(struct rtw89_dev * rtwdev)6070 static void _update_wl_info_v2(struct rtw89_dev *rtwdev)
6071 {
6072 struct rtw89_btc *btc = &rtwdev->btc;
6073 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6074 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6075 struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2;
6076 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6077 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
6078 u8 cnt_2g = 0, cnt_5g = 0, phy;
6079 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
6080 bool b2g = false, b5g = false, client_joined = false;
6081 u8 i;
6082
6083 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6084
6085 for (i = 0; i < RTW89_PORT_NUM; i++) {
6086 if (!wl_linfo[i].active)
6087 continue;
6088
6089 cnt_active++;
6090 wl_rinfo->active_role_v2[cnt_active - 1].role = wl_linfo[i].role;
6091 wl_rinfo->active_role_v2[cnt_active - 1].pid = wl_linfo[i].pid;
6092 wl_rinfo->active_role_v2[cnt_active - 1].phy = wl_linfo[i].phy;
6093 wl_rinfo->active_role_v2[cnt_active - 1].band = wl_linfo[i].band;
6094 wl_rinfo->active_role_v2[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
6095 wl_rinfo->active_role_v2[cnt_active - 1].connected = 0;
6096
6097 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
6098
6099 phy = wl_linfo[i].phy;
6100
6101 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
6102 wl_dinfo->role[phy] = wl_linfo[i].role;
6103 wl_dinfo->op_band[phy] = wl_linfo[i].band;
6104 _update_dbcc_band(rtwdev, phy);
6105 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6106 }
6107
6108 if (wl_linfo[i].connected == MLME_NO_LINK) {
6109 continue;
6110 } else if (wl_linfo[i].connected == MLME_LINKING) {
6111 cnt_connecting++;
6112 } else {
6113 cnt_connect++;
6114 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6115 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6116 wl_linfo[i].client_cnt > 1)
6117 client_joined = true;
6118 }
6119
6120 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
6121 wl_rinfo->active_role_v2[cnt_active - 1].ch = wl_linfo[i].ch;
6122 wl_rinfo->active_role_v2[cnt_active - 1].bw = wl_linfo[i].bw;
6123 wl_rinfo->active_role_v2[cnt_active - 1].connected = 1;
6124
6125 /* only care 2 roles + BT coex */
6126 if (wl_linfo[i].band != RTW89_BAND_2G) {
6127 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
6128 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
6129 cnt_5g++;
6130 b5g = true;
6131 } else {
6132 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
6133 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
6134 cnt_2g++;
6135 b2g = true;
6136 }
6137 }
6138
6139 wl_rinfo->connect_cnt = cnt_connect;
6140
6141 /* Be careful to change the following sequence!! */
6142 if (cnt_connect == 0) {
6143 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6144 wl_rinfo->role_map.role.none = 1;
6145 } else if (!b2g && b5g) {
6146 wl_rinfo->link_mode = BTC_WLINK_5G;
6147 } else if (wl_rinfo->role_map.role.nan) {
6148 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
6149 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
6150 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6151 } else if (b2g && b5g && cnt_connect == 2) {
6152 if (rtwdev->dbcc_en) {
6153 switch (wl_dinfo->role[RTW89_PHY_0]) {
6154 case RTW89_WIFI_ROLE_STATION:
6155 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6156 break;
6157 case RTW89_WIFI_ROLE_P2P_GO:
6158 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6159 break;
6160 case RTW89_WIFI_ROLE_P2P_CLIENT:
6161 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6162 break;
6163 case RTW89_WIFI_ROLE_AP:
6164 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6165 break;
6166 default:
6167 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6168 break;
6169 }
6170 } else {
6171 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
6172 }
6173 } else if (!b5g && cnt_connect == 2) {
6174 if (wl_rinfo->role_map.role.station &&
6175 (wl_rinfo->role_map.role.p2p_go ||
6176 wl_rinfo->role_map.role.p2p_gc ||
6177 wl_rinfo->role_map.role.ap)) {
6178 if (wl_2g_ch[0] == wl_2g_ch[1])
6179 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
6180 else
6181 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6182 } else {
6183 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6184 }
6185 } else if (!b5g && cnt_connect == 1) {
6186 if (wl_rinfo->role_map.role.station)
6187 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6188 else if (wl_rinfo->role_map.role.ap)
6189 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6190 else if (wl_rinfo->role_map.role.p2p_go)
6191 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6192 else if (wl_rinfo->role_map.role.p2p_gc)
6193 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6194 else
6195 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6196 }
6197
6198 /* if no client_joined, don't care P2P-GO/AP role */
6199 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6200 if (!client_joined) {
6201 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6202 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6203 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6204 wl_rinfo->connect_cnt = 1;
6205 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6206 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6207 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6208 wl_rinfo->connect_cnt = 0;
6209 }
6210 }
6211 }
6212
6213 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6214 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6215 cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6216
6217 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6218 }
6219
6220 #define BTC_CHK_HANG_MAX 3
6221 #define BTC_SCB_INV_VALUE GENMASK(31, 0)
6222
_get_role_link_mode(u8 role)6223 static u8 _get_role_link_mode(u8 role)
6224 {
6225 switch (role) {
6226 case RTW89_WIFI_ROLE_STATION:
6227 return BTC_WLINK_2G_STA;
6228 case RTW89_WIFI_ROLE_P2P_GO:
6229 return BTC_WLINK_2G_GO;
6230 case RTW89_WIFI_ROLE_P2P_CLIENT:
6231 return BTC_WLINK_2G_GC;
6232 case RTW89_WIFI_ROLE_AP:
6233 return BTC_WLINK_2G_AP;
6234 default:
6235 return BTC_WLINK_OTHER;
6236 }
6237 }
6238
_chk_role_ch_group(const struct rtw89_btc_chdef * r1,const struct rtw89_btc_chdef * r2)6239 static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1,
6240 const struct rtw89_btc_chdef *r2)
6241 {
6242 if (r1->chan != r2->chan) { /* primary ch is different */
6243 return false;
6244 } else if (r1->bw == RTW89_CHANNEL_WIDTH_40 &&
6245 r2->bw == RTW89_CHANNEL_WIDTH_40) {
6246 if (r1->offset != r2->offset)
6247 return false;
6248 }
6249 return true;
6250 }
6251
_chk_dbcc(struct rtw89_dev * rtwdev,struct rtw89_btc_chdef * ch,u8 * phy,u8 * role,u8 * dbcc_2g_phy)6252 static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch,
6253 u8 *phy, u8 *role, u8 *dbcc_2g_phy)
6254 {
6255 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6256 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
6257 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8;
6258 bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false;
6259 u8 j, k, dbcc_2g_cid, dbcc_2g_cid2, connect_cnt;
6260
6261 if (rtwdev->btc.ver->fwlrole == 7)
6262 connect_cnt = rinfo_v7->connect_cnt;
6263 else if (rtwdev->btc.ver->fwlrole == 8)
6264 connect_cnt = rinfo_v8->connect_cnt;
6265 else
6266 return BTC_WLINK_NOLINK;
6267
6268 /* find out the 2G-PHY by connect-id ->ch */
6269 for (j = 0; j < connect_cnt; j++) {
6270 if (ch[j].center_ch <= 14) {
6271 is_2g_ch_exist = true;
6272 break;
6273 }
6274 }
6275
6276 /* If no any 2G-port exist, it's impossible because 5G-exclude */
6277 if (!is_2g_ch_exist)
6278 return BTC_WLINK_OTHER;
6279
6280 dbcc_2g_cid = j;
6281 *dbcc_2g_phy = phy[dbcc_2g_cid];
6282
6283 /* connect_cnt <= 2 */
6284 if (connect_cnt < BTC_TDMA_WLROLE_MAX)
6285 return (_get_role_link_mode((role[dbcc_2g_cid])));
6286
6287 /* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */
6288 for (k = 0; k < connect_cnt; k++) {
6289 if (k == dbcc_2g_cid)
6290 continue;
6291
6292 if (phy[k] == *dbcc_2g_phy) {
6293 is_multi_role_in_2g_phy = true;
6294 dbcc_2g_cid2 = k;
6295 break;
6296 }
6297 }
6298
6299 /* Single-role in 2G-PHY */
6300 if (!is_multi_role_in_2g_phy)
6301 return (_get_role_link_mode(role[dbcc_2g_cid]));
6302
6303 /* 2-role in 2G-PHY */
6304 if (ch[dbcc_2g_cid2].center_ch > 14)
6305 return BTC_WLINK_25G_MCC;
6306 else if (_chk_role_ch_group(&ch[dbcc_2g_cid], &ch[dbcc_2g_cid2]))
6307 return BTC_WLINK_2G_SCC;
6308 else
6309 return BTC_WLINK_2G_MCC;
6310 }
6311
_update_role_link_mode(struct rtw89_dev * rtwdev,bool client_joined,u32 noa)6312 static void _update_role_link_mode(struct rtw89_dev *rtwdev,
6313 bool client_joined, u32 noa)
6314 {
6315 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &rtwdev->btc.cx.wl.role_info_v8;
6316 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &rtwdev->btc.cx.wl.role_info_v7;
6317 u8 role_ver = rtwdev->btc.ver->fwlrole;
6318 u32 type = BTC_WLMROLE_NONE, dur = 0;
6319 u8 link_mode, connect_cnt;
6320 u32 wl_role;
6321
6322 if (role_ver == 7) {
6323 wl_role = rinfo_v7->role_map;
6324 link_mode = rinfo_v7->link_mode;
6325 connect_cnt = rinfo_v7->connect_cnt;
6326 } else if (role_ver == 8) {
6327 wl_role = rinfo_v8->role_map;
6328 link_mode = rinfo_v8->link_mode;
6329 connect_cnt = rinfo_v8->connect_cnt;
6330 } else {
6331 return;
6332 }
6333
6334 /* if no client_joined, don't care P2P-GO/AP role */
6335 if (((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
6336 (wl_role & BIT(RTW89_WIFI_ROLE_AP))) && !client_joined) {
6337 if (link_mode == BTC_WLINK_2G_SCC) {
6338 if (role_ver == 7) {
6339 rinfo_v7->link_mode = BTC_WLINK_2G_STA;
6340 rinfo_v7->connect_cnt--;
6341 } else if (role_ver == 8) {
6342 rinfo_v8->link_mode = BTC_WLINK_2G_STA;
6343 rinfo_v8->connect_cnt--;
6344 }
6345 } else if (link_mode == BTC_WLINK_2G_GO ||
6346 link_mode == BTC_WLINK_2G_AP) {
6347 if (role_ver == 7) {
6348 rinfo_v7->link_mode = BTC_WLINK_NOLINK;
6349 rinfo_v7->connect_cnt--;
6350 } else if (role_ver == 8) {
6351 rinfo_v8->link_mode = BTC_WLINK_NOLINK;
6352 rinfo_v8->connect_cnt--;
6353 }
6354 }
6355 }
6356
6357 /* Identify 2-Role type */
6358 if (connect_cnt >= 2 &&
6359 (link_mode == BTC_WLINK_2G_SCC ||
6360 link_mode == BTC_WLINK_2G_MCC ||
6361 link_mode == BTC_WLINK_25G_MCC ||
6362 link_mode == BTC_WLINK_5G)) {
6363 if ((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
6364 (wl_role & BIT(RTW89_WIFI_ROLE_AP)))
6365 type = noa ? BTC_WLMROLE_STA_GO_NOA : BTC_WLMROLE_STA_GO;
6366 else if (wl_role & BIT(RTW89_WIFI_ROLE_P2P_CLIENT))
6367 type = noa ? BTC_WLMROLE_STA_GC_NOA : BTC_WLMROLE_STA_GC;
6368 else
6369 type = BTC_WLMROLE_STA_STA;
6370
6371 dur = noa;
6372 }
6373
6374 if (role_ver == 7) {
6375 rinfo_v7->mrole_type = type;
6376 rinfo_v7->mrole_noa_duration = dur;
6377 } else if (role_ver == 8) {
6378 rinfo_v8->mrole_type = type;
6379 rinfo_v8->mrole_noa_duration = dur;
6380 }
6381 }
6382
_update_wl_info_v7(struct rtw89_dev * rtwdev,u8 rid)6383 static void _update_wl_info_v7(struct rtw89_dev *rtwdev, u8 rid)
6384 {
6385 struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER];
6386 struct rtw89_btc *btc = &rtwdev->btc;
6387 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6388 struct rtw89_btc_wl_role_info_v7 *wl_rinfo = &wl->role_info_v7;
6389 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6390 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6391 struct rtw89_btc_wl_active_role_v7 *act_role = NULL;
6392 u8 i, mode, cnt = 0, cnt_2g = 0, cnt_5g = 0, phy_now = RTW89_PHY_MAX, phy_dbcc;
6393 bool b2g = false, b5g = false, client_joined = false, client_inc_2g = false;
6394 u8 client_cnt_last[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6395 u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6396 u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6397 u8 mac = RTW89_MAC_0, dbcc_2g_phy = RTW89_PHY_0;
6398 u32 noa_duration = 0;
6399
6400 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6401
6402 for (i = 0; i < RTW89_PORT_NUM; i++) {
6403 if (!wl_linfo[i].active || wl_linfo[i].phy >= RTW89_PHY_MAX)
6404 continue;
6405
6406 act_role = &wl_rinfo->active_role[i];
6407 act_role->role = wl_linfo[i].role;
6408
6409 /* check if role connect? */
6410 if (wl_linfo[i].connected == MLME_NO_LINK) {
6411 act_role->connected = 0;
6412 continue;
6413 } else if (wl_linfo[i].connected == MLME_LINKING) {
6414 continue;
6415 }
6416
6417 cnt++;
6418 act_role->connected = 1;
6419 act_role->pid = wl_linfo[i].pid;
6420 act_role->phy = wl_linfo[i].phy;
6421 act_role->band = wl_linfo[i].band;
6422 act_role->ch = wl_linfo[i].ch;
6423 act_role->bw = wl_linfo[i].bw;
6424 act_role->noa = wl_linfo[i].noa;
6425 act_role->noa_dur = wl_linfo[i].noa_duration;
6426 cid_ch[cnt - 1] = wl_linfo[i].chdef;
6427 cid_phy[cnt - 1] = wl_linfo[i].phy;
6428 cid_role[cnt - 1] = wl_linfo[i].role;
6429 wl_rinfo->role_map |= BIT(wl_linfo[i].role);
6430
6431 if (rid == i)
6432 phy_now = act_role->phy;
6433
6434 if (wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6435 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) {
6436 if (wl_linfo[i].client_cnt > 1)
6437 client_joined = true;
6438 if (client_cnt_last[i] < wl_linfo[i].client_cnt &&
6439 wl_linfo[i].chdef.band == RTW89_BAND_2G)
6440 client_inc_2g = true;
6441 act_role->client_cnt = wl_linfo[i].client_cnt;
6442 } else {
6443 act_role->client_cnt = 0;
6444 }
6445
6446 if (act_role->noa && act_role->noa_dur > 0)
6447 noa_duration = act_role->noa_dur;
6448
6449 if (rtwdev->dbcc_en) {
6450 phy_dbcc = wl_linfo[i].phy;
6451 wl_dinfo->role[phy_dbcc] |= BIT(wl_linfo[i].role);
6452 wl_dinfo->op_band[phy_dbcc] = wl_linfo[i].chdef.band;
6453 }
6454
6455 if (wl_linfo[i].chdef.band != RTW89_BAND_2G) {
6456 cnt_5g++;
6457 b5g = true;
6458 } else {
6459 if (((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6460 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6461 client_joined) ||
6462 wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_CLIENT)
6463 wl_rinfo->p2p_2g = 1;
6464
6465 if ((wl_linfo[i].mode & BIT(BTC_WL_MODE_11B)) ||
6466 (wl_linfo[i].mode & BIT(BTC_WL_MODE_11G)))
6467 wl->bg_mode = 1;
6468 else if (wl_linfo[i].mode & BIT(BTC_WL_MODE_HE))
6469 wl->he_mode = true;
6470
6471 cnt_2g++;
6472 b2g = true;
6473 }
6474
6475 if (act_role->band == RTW89_BAND_5G && act_role->ch >= 100)
6476 wl->is_5g_hi_channel = 1;
6477 else
6478 wl->is_5g_hi_channel = 0;
6479 }
6480
6481 wl_rinfo->connect_cnt = cnt;
6482 wl->client_cnt_inc_2g = client_inc_2g;
6483
6484 if (cnt == 0) {
6485 mode = BTC_WLINK_NOLINK;
6486 wl_rinfo->role_map = BIT(RTW89_WIFI_ROLE_NONE);
6487 } else if (!b2g && b5g) {
6488 mode = BTC_WLINK_5G;
6489 } else if (wl_rinfo->role_map & BIT(RTW89_WIFI_ROLE_NAN)) {
6490 mode = BTC_WLINK_2G_NAN;
6491 } else if (cnt > BTC_TDMA_WLROLE_MAX) {
6492 mode = BTC_WLINK_OTHER;
6493 } else if (rtwdev->dbcc_en) {
6494 mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, &dbcc_2g_phy);
6495
6496 /* correct 2G-located PHY band for gnt ctrl */
6497 if (dbcc_2g_phy < RTW89_PHY_MAX)
6498 wl_dinfo->op_band[dbcc_2g_phy] = RTW89_BAND_2G;
6499 } else if (b2g && b5g && cnt == 2) {
6500 mode = BTC_WLINK_25G_MCC;
6501 } else if (!b5g && cnt == 2) { /* cnt_connect = 2 */
6502 if (_chk_role_ch_group(&cid_ch[0], &cid_ch[cnt - 1]))
6503 mode = BTC_WLINK_2G_SCC;
6504 else
6505 mode = BTC_WLINK_2G_MCC;
6506 } else if (!b5g && cnt == 1) { /* cnt_connect = 1 */
6507 mode = _get_role_link_mode(cid_role[0]);
6508 } else {
6509 mode = BTC_WLINK_NOLINK;
6510 }
6511
6512 wl_rinfo->link_mode = mode;
6513 _update_role_link_mode(rtwdev, client_joined, noa_duration);
6514
6515 /* todo DBCC related event */
6516 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] wl_info phy_now=%d\n", phy_now);
6517 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6518 "[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g);
6519
6520 if (wl_rinfo->dbcc_en != rtwdev->dbcc_en) {
6521 wl_rinfo->dbcc_chg = 1;
6522 wl_rinfo->dbcc_en = rtwdev->dbcc_en;
6523 btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++;
6524 }
6525
6526 if (rtwdev->dbcc_en) {
6527 wl_rinfo->dbcc_2g_phy = dbcc_2g_phy;
6528
6529 if (dbcc_2g_phy == RTW89_PHY_1)
6530 mac = RTW89_MAC_1;
6531
6532 _update_dbcc_band(rtwdev, RTW89_PHY_0);
6533 _update_dbcc_band(rtwdev, RTW89_PHY_1);
6534 }
6535 _wl_req_mac(rtwdev, mac);
6536 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6537 }
6538
_update_wl_info_v8(struct rtw89_dev * rtwdev,u8 role_id,u8 rlink_id,enum btc_role_state state)6539 static void _update_wl_info_v8(struct rtw89_dev *rtwdev, u8 role_id, u8 rlink_id,
6540 enum btc_role_state state)
6541 {
6542 struct rtw89_btc *btc = &rtwdev->btc;
6543 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6544 struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER];
6545 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
6546 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6547 bool client_joined = false, b2g = false, b5g = false;
6548 u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6549 u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6550 u8 dbcc_en = 0, pta_req_band = RTW89_MAC_0;
6551 u8 i, j, cnt = 0, cnt_2g = 0, cnt_5g = 0;
6552 struct rtw89_btc_wl_link_info *wl_linfo;
6553 struct rtw89_btc_wl_rlink *rlink = NULL;
6554 u8 dbcc_2g_phy = RTW89_PHY_0;
6555 u8 mode = BTC_WLINK_NOLINK;
6556 u32 noa_dur = 0;
6557
6558 if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id > RTW89_MAC_1)
6559 return;
6560
6561 /* Extract wl->link_info[role_id][rlink_id] to wl->role_info
6562 * role_id: role index
6563 * rlink_id: rlink index (= HW-band index)
6564 * pid: port_index
6565 */
6566
6567 wl_linfo = &wl->rlink_info[role_id][rlink_id];
6568 if (wl_linfo->connected == MLME_LINKING)
6569 return;
6570
6571 rlink = &wl_rinfo->rlink[role_id][rlink_id];
6572 rlink->role = wl_linfo->role;
6573 rlink->active = wl_linfo->active; /* Doze or not */
6574 rlink->pid = wl_linfo->pid;
6575 rlink->phy = wl_linfo->phy;
6576 rlink->rf_band = wl_linfo->band;
6577 rlink->ch = wl_linfo->ch;
6578 rlink->bw = wl_linfo->bw;
6579 rlink->noa = wl_linfo->noa;
6580 rlink->noa_dur = wl_linfo->noa_duration / 1000;
6581 rlink->client_cnt = wl_linfo->client_cnt;
6582 rlink->mode = wl_linfo->mode;
6583
6584 switch (wl_linfo->connected) {
6585 case MLME_NO_LINK:
6586 rlink->connected = 0;
6587 if (rlink->role == RTW89_WIFI_ROLE_STATION)
6588 btc->dm.leak_ap = 0;
6589 break;
6590 case MLME_LINKED:
6591 rlink->connected = 1;
6592 break;
6593 default:
6594 return;
6595 }
6596
6597 wl->is_5g_hi_channel = false;
6598 wl->bg_mode = false;
6599 wl_rinfo->role_map = 0;
6600 wl_rinfo->p2p_2g = 0;
6601 memset(cid_ch, 0, sizeof(cid_ch));
6602
6603 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
6604 for (j = RTW89_MAC_0; j <= RTW89_MAC_1; j++) {
6605 rlink = &wl_rinfo->rlink[i][j];
6606
6607 if (!rlink->active || !rlink->connected)
6608 continue;
6609
6610 cnt++;
6611 wl_rinfo->role_map |= BIT(rlink->role);
6612
6613 /* only if client connect for p2p-Go/AP */
6614 if ((rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
6615 rlink->role == RTW89_WIFI_ROLE_AP) &&
6616 rlink->client_cnt > 1)
6617 client_joined = true;
6618
6619 /* Identufy if P2P-Go (GO/GC/AP) exist at 2G band*/
6620 if (rlink->rf_band == RTW89_BAND_2G &&
6621 (client_joined || rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT))
6622 wl_rinfo->p2p_2g = 1;
6623
6624 /* only one noa-role exist */
6625 if (rlink->noa && rlink->noa_dur > 0)
6626 noa_dur = rlink->noa_dur;
6627
6628 /* for WL 5G-Rx interfered with BT issue */
6629 if (rlink->rf_band == RTW89_BAND_5G && rlink->ch >= 100)
6630 wl->is_5g_hi_channel = 1;
6631
6632 if ((rlink->mode & BIT(BTC_WL_MODE_11B)) ||
6633 (rlink->mode & BIT(BTC_WL_MODE_11G)))
6634 wl->bg_mode = 1;
6635
6636 if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT)
6637 continue;
6638
6639 cid_ch[cnt - 1] = wl_linfo->chdef;
6640 cid_phy[cnt - 1] = rlink->phy;
6641 cid_role[cnt - 1] = rlink->role;
6642
6643 if (rlink->rf_band != RTW89_BAND_2G) {
6644 cnt_5g++;
6645 b5g = true;
6646 } else {
6647 cnt_2g++;
6648 b2g = true;
6649 }
6650 }
6651 }
6652
6653 if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) {
6654 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6655 "[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g);
6656 rtw89_warn(rtwdev, "not support MLO feature yet");
6657 } else {
6658 dbcc_en = rtwdev->dbcc_en;
6659
6660 /* Be careful to change the following sequence!! */
6661 if (cnt == 0) {
6662 mode = BTC_WLINK_NOLINK;
6663 } else if (!b2g && b5g) {
6664 mode = BTC_WLINK_5G;
6665 } else if (wl_rinfo->role_map & BIT(RTW89_WIFI_ROLE_NAN)) {
6666 mode = BTC_WLINK_2G_NAN;
6667 } else if (cnt > BTC_TDMA_WLROLE_MAX) {
6668 mode = BTC_WLINK_OTHER;
6669 } else if (dbcc_en) {
6670 mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role,
6671 &dbcc_2g_phy);
6672 } else if (b2g && b5g && cnt == 2) {
6673 mode = BTC_WLINK_25G_MCC;
6674 } else if (!b5g && cnt == 2) { /* cnt_connect = 2 */
6675 if (_chk_role_ch_group(&cid_ch[0], &cid_ch[cnt - 1]))
6676 mode = BTC_WLINK_2G_SCC;
6677 else
6678 mode = BTC_WLINK_2G_MCC;
6679 } else if (!b5g && cnt == 1) { /* cnt_connect = 1 */
6680 mode = _get_role_link_mode(cid_role[0]);
6681 }
6682 }
6683
6684 wl_rinfo->link_mode = mode;
6685 wl_rinfo->connect_cnt = cnt;
6686 if (wl_rinfo->connect_cnt == 0)
6687 wl_rinfo->role_map = BIT(RTW89_WIFI_ROLE_NONE);
6688 _update_role_link_mode(rtwdev, client_joined, noa_dur);
6689
6690 wl_rinfo->dbcc_2g_phy = dbcc_2g_phy;
6691 if (wl_rinfo->dbcc_en != dbcc_en) {
6692 wl_rinfo->dbcc_en = dbcc_en;
6693 wl_rinfo->dbcc_chg = 1;
6694 btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++;
6695 } else {
6696 wl_rinfo->dbcc_chg = 0;
6697 }
6698
6699 if (wl_rinfo->dbcc_en) {
6700 memset(wl_dinfo, 0, sizeof(struct rtw89_btc_wl_dbcc_info));
6701
6702 if (mode == BTC_WLINK_5G) {
6703 pta_req_band = RTW89_PHY_0;
6704 wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_5G;
6705 wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_2G;
6706 } else if (wl_rinfo->dbcc_2g_phy == RTW89_PHY_1) {
6707 pta_req_band = RTW89_PHY_1;
6708 wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_5G;
6709 wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_2G;
6710 } else {
6711 pta_req_band = RTW89_PHY_0;
6712 wl_dinfo->op_band[RTW89_PHY_0] = RTW89_BAND_2G;
6713 wl_dinfo->op_band[RTW89_PHY_1] = RTW89_BAND_5G;
6714 }
6715 _update_dbcc_band(rtwdev, RTW89_PHY_0);
6716 _update_dbcc_band(rtwdev, RTW89_PHY_1);
6717 }
6718
6719 wl_rinfo->pta_req_band = pta_req_band;
6720 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6721 }
6722
rtw89_coex_act1_work(struct work_struct * work)6723 void rtw89_coex_act1_work(struct work_struct *work)
6724 {
6725 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
6726 coex_act1_work.work);
6727 struct rtw89_btc *btc = &rtwdev->btc;
6728 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
6729 struct rtw89_btc_cx *cx = &btc->cx;
6730 struct rtw89_btc_wl_info *wl = &cx->wl;
6731
6732 mutex_lock(&rtwdev->mutex);
6733 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
6734 dm->cnt_notify[BTC_NCNT_TIMER]++;
6735 if (wl->status.map._4way)
6736 wl->status.map._4way = false;
6737 if (wl->status.map.connecting)
6738 wl->status.map.connecting = false;
6739
6740 _run_coex(rtwdev, BTC_RSN_ACT1_WORK);
6741 mutex_unlock(&rtwdev->mutex);
6742 }
6743
rtw89_coex_bt_devinfo_work(struct work_struct * work)6744 void rtw89_coex_bt_devinfo_work(struct work_struct *work)
6745 {
6746 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
6747 coex_bt_devinfo_work.work);
6748 struct rtw89_btc *btc = &rtwdev->btc;
6749 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
6750 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
6751
6752 mutex_lock(&rtwdev->mutex);
6753 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
6754 dm->cnt_notify[BTC_NCNT_TIMER]++;
6755 a2dp->play_latency = 0;
6756 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK);
6757 mutex_unlock(&rtwdev->mutex);
6758 }
6759
rtw89_coex_rfk_chk_work(struct work_struct * work)6760 void rtw89_coex_rfk_chk_work(struct work_struct *work)
6761 {
6762 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
6763 coex_rfk_chk_work.work);
6764 struct rtw89_btc *btc = &rtwdev->btc;
6765 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
6766 struct rtw89_btc_cx *cx = &btc->cx;
6767 struct rtw89_btc_wl_info *wl = &cx->wl;
6768
6769 mutex_lock(&rtwdev->mutex);
6770 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
6771 dm->cnt_notify[BTC_NCNT_TIMER]++;
6772 if (wl->rfk_info.state != BTC_WRFK_STOP) {
6773 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6774 "[BTC], %s(): RFK timeout\n", __func__);
6775 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++;
6776 dm->error.map.wl_rfk_timeout = true;
6777 wl->rfk_info.state = BTC_WRFK_STOP;
6778 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
6779 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK);
6780 }
6781 mutex_unlock(&rtwdev->mutex);
6782 }
6783
_update_bt_scbd(struct rtw89_dev * rtwdev,bool only_update)6784 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update)
6785 {
6786 const struct rtw89_chip_info *chip = rtwdev->chip;
6787 struct rtw89_btc *btc = &rtwdev->btc;
6788 struct rtw89_btc_cx *cx = &btc->cx;
6789 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
6790 u32 val;
6791 bool status_change = false;
6792
6793 if (!chip->scbd)
6794 return;
6795
6796 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
6797
6798 val = _read_scbd(rtwdev);
6799 if (val == BTC_SCB_INV_VALUE) {
6800 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6801 "[BTC], %s(): return by invalid scbd value\n",
6802 __func__);
6803 return;
6804 }
6805
6806 if (!(val & BTC_BSCB_ON))
6807 bt->enable.now = 0;
6808 else
6809 bt->enable.now = 1;
6810
6811 if (bt->enable.now != bt->enable.last)
6812 status_change = true;
6813
6814 /* reset bt info if bt re-enable */
6815 if (bt->enable.now && !bt->enable.last) {
6816 _reset_btc_var(rtwdev, BTC_RESET_BTINFO);
6817 cx->cnt_bt[BTC_BCNT_REENABLE]++;
6818 bt->enable.now = 1;
6819 }
6820
6821 bt->enable.last = bt->enable.now;
6822 bt->scbd = val;
6823 bt->mbx_avl = !!(val & BTC_BSCB_ACT);
6824
6825 if (bt->whql_test != !!(val & BTC_BSCB_WHQL))
6826 status_change = true;
6827
6828 bt->whql_test = !!(val & BTC_BSCB_WHQL);
6829 bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE;
6830 bt->link_info.a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT);
6831
6832 bt->lna_constrain = !!(val & BTC_BSCB_BT_LNAB0) +
6833 !!(val & BTC_BSCB_BT_LNAB1) * 2 + 4;
6834
6835 /* if rfk run 1->0 */
6836 if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN))
6837 status_change = true;
6838
6839 bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN);
6840 bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ);
6841 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
6842 bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT);
6843 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
6844
6845 if (!only_update && status_change)
6846 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
6847 }
6848
_chk_wl_rfk_request(struct rtw89_dev * rtwdev)6849 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev)
6850 {
6851 struct rtw89_btc *btc = &rtwdev->btc;
6852 struct rtw89_btc_cx *cx = &btc->cx;
6853 struct rtw89_btc_bt_info *bt = &cx->bt;
6854
6855 _update_bt_scbd(rtwdev, true);
6856
6857 cx->cnt_wl[BTC_WCNT_RFK_REQ]++;
6858
6859 if ((bt->rfk_info.map.run || bt->rfk_info.map.req) &&
6860 !bt->rfk_info.map.timeout) {
6861 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++;
6862 } else {
6863 cx->cnt_wl[BTC_WCNT_RFK_GO]++;
6864 return true;
6865 }
6866 return false;
6867 }
6868
6869 static
_run_coex(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason)6870 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
6871 {
6872 struct rtw89_btc *btc = &rtwdev->btc;
6873 const struct rtw89_btc_ver *ver = btc->ver;
6874 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
6875 struct rtw89_btc_cx *cx = &btc->cx;
6876 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6877 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
6878 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
6879 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
6880 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
6881 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
6882 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
6883 u8 mode, igno_bt, always_freerun;
6884
6885 lockdep_assert_held(&rtwdev->mutex);
6886
6887 dm->run_reason = reason;
6888 _update_dm_step(rtwdev, reason);
6889 _update_btc_state_map(rtwdev);
6890
6891 if (ver->fwlrole == 0)
6892 mode = wl_rinfo->link_mode;
6893 else if (ver->fwlrole == 1)
6894 mode = wl_rinfo_v1->link_mode;
6895 else if (ver->fwlrole == 2)
6896 mode = wl_rinfo_v2->link_mode;
6897 else if (ver->fwlrole == 7)
6898 mode = wl_rinfo_v7->link_mode;
6899 else if (ver->fwlrole == 8)
6900 mode = wl_rinfo_v8->link_mode;
6901 else
6902 return;
6903
6904 if (ver->fcxctrl == 7) {
6905 igno_bt = btc->ctrl.ctrl_v7.igno_bt;
6906 always_freerun = btc->ctrl.ctrl_v7.always_freerun;
6907 } else {
6908 igno_bt = btc->ctrl.ctrl.igno_bt;
6909 always_freerun = btc->ctrl.ctrl.always_freerun;
6910 }
6911
6912 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
6913 __func__, reason, mode);
6914 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
6915 __func__, dm->wl_only, dm->bt_only);
6916
6917 /* Be careful to change the following function sequence!! */
6918 if (btc->manual_ctrl) {
6919 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6920 "[BTC], %s(): return for Manual CTRL!!\n",
6921 __func__);
6922 return;
6923 }
6924
6925 if (igno_bt &&
6926 (reason == BTC_RSN_UPDATE_BT_INFO ||
6927 reason == BTC_RSN_UPDATE_BT_SCBD)) {
6928 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6929 "[BTC], %s(): return for Stop Coex DM!!\n",
6930 __func__);
6931 return;
6932 }
6933
6934 if (!wl->status.map.init_ok) {
6935 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6936 "[BTC], %s(): return for WL init fail!!\n",
6937 __func__);
6938 return;
6939 }
6940
6941 if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
6942 wl->status.map.lps_pre == wl->status.map.lps) {
6943 if (reason == BTC_RSN_NTFY_POWEROFF ||
6944 reason == BTC_RSN_NTFY_RADIO_STATE) {
6945 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6946 "[BTC], %s(): return for WL rf off state no change!!\n",
6947 __func__);
6948 return;
6949 }
6950 if (wl->status.map.rf_off == 1 ||
6951 wl->status.map.lps == BTC_LPS_RF_OFF) {
6952 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6953 "[BTC], %s(): return for WL rf off state!!\n",
6954 __func__);
6955 return;
6956 }
6957 }
6958
6959 dm->freerun = false;
6960 dm->cnt_dm[BTC_DCNT_RUN]++;
6961 dm->fddt_train = BTC_FDDT_DISABLE;
6962 bt->scan_rx_low_pri = false;
6963 igno_bt = false;
6964
6965 dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */
6966
6967 if (always_freerun) {
6968 _action_freerun(rtwdev);
6969 igno_bt = true;
6970 goto exit;
6971 }
6972
6973 if (dm->wl_only) {
6974 _action_wl_only(rtwdev);
6975 igno_bt = true;
6976 goto exit;
6977 }
6978
6979 if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) {
6980 _action_wl_off(rtwdev, mode);
6981 igno_bt = true;
6982 goto exit;
6983 }
6984
6985 if (reason == BTC_RSN_NTFY_INIT) {
6986 _action_wl_init(rtwdev);
6987 goto exit;
6988 }
6989
6990 if (!cx->bt.enable.now && !cx->other.type) {
6991 _action_bt_off(rtwdev);
6992 goto exit;
6993 }
6994
6995 if (cx->bt.whql_test) {
6996 _action_bt_whql(rtwdev);
6997 goto exit;
6998 }
6999
7000 if (wl->rfk_info.state != BTC_WRFK_STOP) {
7001 _action_wl_rfk(rtwdev);
7002 goto exit;
7003 }
7004
7005 if (wl->status.val & btc_scanning_map.val) {
7006 _action_wl_scan(rtwdev);
7007 bt->scan_rx_low_pri = true;
7008 goto exit;
7009 }
7010
7011 switch (mode) {
7012 case BTC_WLINK_NOLINK:
7013 _action_wl_nc(rtwdev);
7014 break;
7015 case BTC_WLINK_2G_STA:
7016 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
7017 bt->scan_rx_low_pri = true;
7018 _action_wl_2g_sta(rtwdev);
7019 break;
7020 case BTC_WLINK_2G_AP:
7021 bt->scan_rx_low_pri = true;
7022 _action_wl_2g_ap(rtwdev);
7023 break;
7024 case BTC_WLINK_2G_GO:
7025 bt->scan_rx_low_pri = true;
7026 _action_wl_2g_go(rtwdev);
7027 break;
7028 case BTC_WLINK_2G_GC:
7029 bt->scan_rx_low_pri = true;
7030 _action_wl_2g_gc(rtwdev);
7031 break;
7032 case BTC_WLINK_2G_SCC:
7033 bt->scan_rx_low_pri = true;
7034 if (ver->fwlrole == 0)
7035 _action_wl_2g_scc(rtwdev);
7036 else if (ver->fwlrole == 1)
7037 _action_wl_2g_scc_v1(rtwdev);
7038 else if (ver->fwlrole == 2 || ver->fwlrole == 7)
7039 _action_wl_2g_scc_v2(rtwdev);
7040 else if (ver->fwlrole == 8)
7041 _action_wl_2g_scc_v8(rtwdev);
7042 break;
7043 case BTC_WLINK_2G_MCC:
7044 bt->scan_rx_low_pri = true;
7045 _action_wl_2g_mcc(rtwdev);
7046 break;
7047 case BTC_WLINK_25G_MCC:
7048 bt->scan_rx_low_pri = true;
7049 _action_wl_25g_mcc(rtwdev);
7050 break;
7051 case BTC_WLINK_5G:
7052 _action_wl_5g(rtwdev);
7053 break;
7054 case BTC_WLINK_2G_NAN:
7055 _action_wl_2g_nan(rtwdev);
7056 break;
7057 default:
7058 _action_wl_other(rtwdev);
7059 break;
7060 }
7061
7062 exit:
7063 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__);
7064 if (ver->fcxctrl == 7)
7065 btc->ctrl.ctrl_v7.igno_bt = igno_bt;
7066 else
7067 btc->ctrl.ctrl.igno_bt = igno_bt;
7068 _action_common(rtwdev);
7069 }
7070
rtw89_btc_ntfy_poweron(struct rtw89_dev * rtwdev)7071 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
7072 {
7073 struct rtw89_btc *btc = &rtwdev->btc;
7074
7075 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
7076 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++;
7077 }
7078
rtw89_btc_ntfy_poweroff(struct rtw89_dev * rtwdev)7079 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
7080 {
7081 struct rtw89_btc *btc = &rtwdev->btc;
7082 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7083
7084 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
7085 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
7086
7087 btc->cx.wl.status.map.rf_off = 1;
7088 btc->cx.wl.status.map.busy = 0;
7089 wl->status.map.lps = BTC_LPS_OFF;
7090
7091 _write_scbd(rtwdev, BTC_WSCB_ALL, false);
7092 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
7093
7094 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
7095
7096 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
7097 }
7098
_set_init_info(struct rtw89_dev * rtwdev)7099 static void _set_init_info(struct rtw89_dev *rtwdev)
7100 {
7101 const struct rtw89_chip_info *chip = rtwdev->chip;
7102 struct rtw89_btc *btc = &rtwdev->btc;
7103 const struct rtw89_btc_ver *ver = btc->ver;
7104 struct rtw89_btc_dm *dm = &btc->dm;
7105 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7106
7107 if (ver->fcxinit == 7) {
7108 dm->init_info.init_v7.wl_only = (u8)dm->wl_only;
7109 dm->init_info.init_v7.bt_only = (u8)dm->bt_only;
7110 dm->init_info.init_v7.wl_init_ok = (u8)wl->status.map.init_ok;
7111 dm->init_info.init_v7.cx_other = btc->cx.other.type;
7112 dm->init_info.init_v7.wl_guard_ch = chip->afh_guard_ch;
7113 dm->init_info.init_v7.module = btc->mdinfo.md_v7;
7114 } else {
7115 dm->init_info.init.wl_only = (u8)dm->wl_only;
7116 dm->init_info.init.bt_only = (u8)dm->bt_only;
7117 dm->init_info.init.wl_init_ok = (u8)wl->status.map.init_ok;
7118 dm->init_info.init.dbcc_en = rtwdev->dbcc_en;
7119 dm->init_info.init.cx_other = btc->cx.other.type;
7120 dm->init_info.init.wl_guard_ch = chip->afh_guard_ch;
7121 dm->init_info.init.module = btc->mdinfo.md;
7122 }
7123 }
7124
rtw89_btc_ntfy_init(struct rtw89_dev * rtwdev,u8 mode)7125 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
7126 {
7127 struct rtw89_btc *btc = &rtwdev->btc;
7128 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7129 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7130 const struct rtw89_chip_info *chip = rtwdev->chip;
7131 const struct rtw89_btc_ver *ver = btc->ver;
7132
7133 _reset_btc_var(rtwdev, BTC_RESET_ALL);
7134 btc->dm.run_reason = BTC_RSN_NONE;
7135 btc->dm.run_action = BTC_ACT_NONE;
7136 if (ver->fcxctrl == 7)
7137 btc->ctrl.ctrl_v7.igno_bt = true;
7138 else
7139 btc->ctrl.ctrl.igno_bt = true;
7140
7141 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7142 "[BTC], %s(): mode=%d\n", __func__, mode);
7143
7144 wl->coex_mode = mode;
7145 dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
7146 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0;
7147 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0;
7148 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0;
7149
7150 chip->ops->btc_set_rfe(rtwdev);
7151 chip->ops->btc_init_cfg(rtwdev);
7152
7153 if (!wl->status.map.init_ok) {
7154 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7155 "[BTC], %s(): return for WL init fail!!\n",
7156 __func__);
7157 dm->error.map.init = true;
7158 return;
7159 }
7160
7161 _write_scbd(rtwdev,
7162 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
7163 _update_bt_scbd(rtwdev, true);
7164 if (rtw89_mac_get_ctrl_path(rtwdev)) {
7165 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7166 "[BTC], %s(): PTA owner warning!!\n",
7167 __func__);
7168 dm->error.map.pta_owner = true;
7169 }
7170
7171 _set_init_info(rtwdev);
7172 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR);
7173 btc_fw_set_monreg(rtwdev);
7174 rtw89_btc_fw_set_slots(rtwdev);
7175 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
7176 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
7177
7178 _run_coex(rtwdev, BTC_RSN_NTFY_INIT);
7179 }
7180
rtw89_btc_ntfy_scan_start(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)7181 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
7182 {
7183 struct rtw89_btc *btc = &rtwdev->btc;
7184 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7185
7186 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7187 "[BTC], %s(): phy_idx=%d, band=%d\n",
7188 __func__, phy_idx, band);
7189
7190 if (phy_idx >= RTW89_PHY_MAX)
7191 return;
7192
7193 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
7194 wl->status.map.scan = true;
7195 wl->scan_info.band[phy_idx] = band;
7196 wl->scan_info.phy_map |= BIT(phy_idx);
7197 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
7198
7199 if (rtwdev->dbcc_en) {
7200 wl->dbcc_info.scan_band[phy_idx] = band;
7201 _update_dbcc_band(rtwdev, phy_idx);
7202 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7203 }
7204
7205 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START);
7206 }
7207
rtw89_btc_ntfy_scan_finish(struct rtw89_dev * rtwdev,u8 phy_idx)7208 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
7209 {
7210 struct rtw89_btc *btc = &rtwdev->btc;
7211 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7212
7213 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7214 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
7215 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
7216
7217 wl->status.map.scan = false;
7218 wl->scan_info.phy_map &= ~BIT(phy_idx);
7219 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
7220
7221 if (rtwdev->dbcc_en) {
7222 _update_dbcc_band(rtwdev, phy_idx);
7223 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7224 }
7225
7226 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
7227 }
7228
rtw89_btc_ntfy_switch_band(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)7229 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
7230 {
7231 struct rtw89_btc *btc = &rtwdev->btc;
7232 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7233
7234 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7235 "[BTC], %s(): phy_idx=%d, band=%d\n",
7236 __func__, phy_idx, band);
7237
7238 if (phy_idx >= RTW89_PHY_MAX)
7239 return;
7240
7241 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
7242
7243 if (rtwdev->dbcc_en) {
7244 wl->dbcc_info.scan_band[phy_idx] = band;
7245 _update_dbcc_band(rtwdev, phy_idx);
7246 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7247 }
7248 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND);
7249 }
7250
rtw89_btc_ntfy_specific_packet(struct rtw89_dev * rtwdev,enum btc_pkt_type pkt_type)7251 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev,
7252 enum btc_pkt_type pkt_type)
7253 {
7254 struct rtw89_btc *btc = &rtwdev->btc;
7255 struct rtw89_btc_cx *cx = &btc->cx;
7256 struct rtw89_btc_wl_info *wl = &cx->wl;
7257 struct rtw89_btc_bt_link_info *b = &cx->bt.link_info;
7258 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
7259 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
7260 u32 cnt;
7261 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD;
7262 bool delay_work = false;
7263
7264 switch (pkt_type) {
7265 case PACKET_DHCP:
7266 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP];
7267 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7268 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt);
7269 wl->status.map.connecting = true;
7270 delay_work = true;
7271 break;
7272 case PACKET_EAPOL:
7273 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
7274 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7275 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt);
7276 wl->status.map._4way = true;
7277 delay_work = true;
7278 if (hfp->exist || hid->exist)
7279 delay /= 2;
7280 break;
7281 case PACKET_EAPOL_END:
7282 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
7283 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7284 "[BTC], %s(): EAPOL_End cnt=%d\n",
7285 __func__, cnt);
7286 wl->status.map._4way = false;
7287 cancel_delayed_work(&rtwdev->coex_act1_work);
7288 break;
7289 case PACKET_ARP:
7290 cnt = ++cx->cnt_wl[BTC_WCNT_ARP];
7291 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7292 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt);
7293 return;
7294 case PACKET_ICMP:
7295 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7296 "[BTC], %s(): ICMP pkt\n", __func__);
7297 return;
7298 default:
7299 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7300 "[BTC], %s(): unknown packet type %d\n",
7301 __func__, pkt_type);
7302 return;
7303 }
7304
7305 if (delay_work) {
7306 cancel_delayed_work(&rtwdev->coex_act1_work);
7307 ieee80211_queue_delayed_work(rtwdev->hw,
7308 &rtwdev->coex_act1_work, delay);
7309 }
7310
7311 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
7312 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET);
7313 }
7314
rtw89_btc_ntfy_eapol_packet_work(struct work_struct * work)7315 void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work)
7316 {
7317 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7318 btc.eapol_notify_work);
7319
7320 mutex_lock(&rtwdev->mutex);
7321 rtw89_leave_ps_mode(rtwdev);
7322 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL);
7323 mutex_unlock(&rtwdev->mutex);
7324 }
7325
rtw89_btc_ntfy_arp_packet_work(struct work_struct * work)7326 void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work)
7327 {
7328 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7329 btc.arp_notify_work);
7330
7331 mutex_lock(&rtwdev->mutex);
7332 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP);
7333 mutex_unlock(&rtwdev->mutex);
7334 }
7335
rtw89_btc_ntfy_dhcp_packet_work(struct work_struct * work)7336 void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work)
7337 {
7338 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7339 btc.dhcp_notify_work);
7340
7341 mutex_lock(&rtwdev->mutex);
7342 rtw89_leave_ps_mode(rtwdev);
7343 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP);
7344 mutex_unlock(&rtwdev->mutex);
7345 }
7346
rtw89_btc_ntfy_icmp_packet_work(struct work_struct * work)7347 void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work)
7348 {
7349 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7350 btc.icmp_notify_work);
7351
7352 mutex_lock(&rtwdev->mutex);
7353 rtw89_leave_ps_mode(rtwdev);
7354 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP);
7355 mutex_unlock(&rtwdev->mutex);
7356 }
7357
_update_bt_rssi_level(struct rtw89_dev * rtwdev,u8 rssi)7358 static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi)
7359 {
7360 const struct rtw89_chip_info *chip = rtwdev->chip;
7361 struct rtw89_btc *btc = &rtwdev->btc;
7362 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
7363 u8 *rssi_st, rssi_th, rssi_level = 0;
7364 u8 i;
7365
7366 /* for rssi locate in which {40, 36, 31, 28}
7367 * if rssi >= 40% (-60dBm) --> rssi_level = 4
7368 * if 36% <= rssi < 40% --> rssi_level = 3
7369 * if 31% <= rssi < 36% --> rssi_level = 2
7370 * if 28% <= rssi < 31% --> rssi_level = 1
7371 * if rssi < 28% --> rssi_level = 0
7372 */
7373
7374 /* check if rssi across bt_rssi_thres boundary */
7375 for (i = 0; i < BTC_BT_RSSI_THMAX; i++) {
7376 rssi_th = chip->bt_rssi_thres[i];
7377 rssi_st = &bt->link_info.rssi_state[i];
7378
7379 *rssi_st = _update_rssi_state(rtwdev, *rssi_st, rssi, rssi_th);
7380
7381 if (BTC_RSSI_HIGH(*rssi_st)) {
7382 rssi_level = BTC_BT_RSSI_THMAX - i;
7383 break;
7384 }
7385 }
7386 return rssi_level;
7387 }
7388
_update_zb_coex_tbl(struct rtw89_dev * rtwdev)7389 static void _update_zb_coex_tbl(struct rtw89_dev *rtwdev)
7390 {
7391 u8 mode = rtwdev->btc.cx.wl.role_info.link_mode;
7392 u32 zb_tbl0 = 0xda5a5a5a, zb_tbl1 = 0xda5a5a5a;
7393
7394 if (mode == BTC_WLINK_5G || rtwdev->btc.dm.freerun) {
7395 zb_tbl0 = 0xffffffff;
7396 zb_tbl1 = 0xffffffff;
7397 } else if (mode == BTC_WLINK_25G_MCC) {
7398 zb_tbl0 = 0xffffffff; /* for E5G slot */
7399 zb_tbl1 = 0xda5a5a5a; /* for E2G slot */
7400 }
7401 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_0, zb_tbl0);
7402 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_1, zb_tbl1);
7403 }
7404
7405 #define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4)
7406
_update_bt_info(struct rtw89_dev * rtwdev,u8 * buf,u32 len)7407 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
7408 {
7409 const struct rtw89_chip_info *chip = rtwdev->chip;
7410 struct rtw89_btc *btc = &rtwdev->btc;
7411 struct rtw89_btc_cx *cx = &btc->cx;
7412 struct rtw89_btc_bt_info *bt = &cx->bt;
7413 struct rtw89_btc_bt_link_info *b = &bt->link_info;
7414 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
7415 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
7416 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
7417 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc;
7418 union btc_btinfo btinfo;
7419
7420 if (buf[BTC_BTINFO_L1] != 6)
7421 return;
7422
7423 if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) {
7424 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7425 "[BTC], %s(): return by bt-info duplicate!!\n",
7426 __func__);
7427 cx->cnt_bt[BTC_BCNT_INFOSAME]++;
7428 return;
7429 }
7430
7431 memcpy(bt->raw_info, buf, BTC_BTINFO_MAX);
7432
7433 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7434 "[BTC], %s(): bt_info[2]=0x%02x\n",
7435 __func__, bt->raw_info[2]);
7436
7437 b->profile_cnt.last = b->profile_cnt.now;
7438 b->profile_cnt.now = 0;
7439 hid->type = 0;
7440
7441 /* parse raw info low-Byte2 */
7442 btinfo.val = bt->raw_info[BTC_BTINFO_L2];
7443 b->status.map.connect = btinfo.lb2.connect;
7444 b->status.map.sco_busy = btinfo.lb2.sco_busy;
7445 b->status.map.acl_busy = btinfo.lb2.acl_busy;
7446 b->status.map.inq_pag = btinfo.lb2.inq_pag;
7447 bt->inq_pag.now = btinfo.lb2.inq_pag;
7448 cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
7449
7450 hfp->exist = btinfo.lb2.hfp;
7451 b->profile_cnt.now += (u8)hfp->exist;
7452 hid->exist = btinfo.lb2.hid;
7453 b->profile_cnt.now += (u8)hid->exist;
7454 a2dp->exist = btinfo.lb2.a2dp;
7455 b->profile_cnt.now += (u8)a2dp->exist;
7456 pan->exist = btinfo.lb2.pan;
7457 b->profile_cnt.now += (u8)pan->exist;
7458 btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK);
7459
7460 /* parse raw info low-Byte3 */
7461 btinfo.val = bt->raw_info[BTC_BTINFO_L3];
7462 if (btinfo.lb3.retry != 0)
7463 cx->cnt_bt[BTC_BCNT_RETRY]++;
7464 b->cqddr = btinfo.lb3.cqddr;
7465 cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
7466 bt->inq = btinfo.lb3.inq;
7467 cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
7468 bt->pag = btinfo.lb3.pag;
7469
7470 b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
7471 /* parse raw info high-Byte0 */
7472 btinfo.val = bt->raw_info[BTC_BTINFO_H0];
7473 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/
7474 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi);
7475 bt->rssi_level = _update_bt_rssi_level(rtwdev, b->rssi);
7476 btc->dm.trx_info.bt_rssi = bt->rssi_level;
7477
7478 /* parse raw info high-Byte1 */
7479 btinfo.val = bt->raw_info[BTC_BTINFO_H1];
7480 b->status.map.ble_connect = btinfo.hb1.ble_connect;
7481 if (btinfo.hb1.ble_connect) {
7482 if (hid->exist)
7483 hid->type |= BTC_HID_BLE;
7484 else if (btinfo.hb1.voice)
7485 hid->type |= BTC_HID_RCU_VOICE;
7486 else
7487 hid->type |= BTC_HID_RCU;
7488 }
7489
7490 cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
7491 bt->reinit = btinfo.hb1.reinit;
7492 cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
7493 b->relink.now = btinfo.hb1.relink;
7494 cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
7495 bt->igno_wl = btinfo.hb1.igno_wl;
7496
7497 if (bt->igno_wl && !cx->wl.status.map.rf_off)
7498 _set_bt_ignore_wlan_act(rtwdev, false);
7499
7500 bt->ble_scan_en = btinfo.hb1.ble_scan;
7501
7502 cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
7503 b->role_sw = btinfo.hb1.role_sw;
7504
7505 b->multi_link.now = btinfo.hb1.multi_link;
7506
7507 /* parse raw info high-Byte2 */
7508 btinfo.val = bt->raw_info[BTC_BTINFO_H2];
7509 pan->active = !!btinfo.hb2.pan_active;
7510
7511 cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
7512 b->afh_update = btinfo.hb2.afh_update;
7513 a2dp->active = btinfo.hb2.a2dp_active;
7514 b->slave_role = btinfo.hb2.slave;
7515 hid->slot_info = btinfo.hb2.hid_slot;
7516 hid->pair_cnt = btinfo.hb2.hid_cnt;
7517 if (!b->status.map.ble_connect || hid->pair_cnt > 1)
7518 hid->type |= (hid->slot_info == BTC_HID_218 ?
7519 BTC_HID_218 : BTC_HID_418);
7520 /* parse raw info high-Byte3 */
7521 btinfo.val = bt->raw_info[BTC_BTINFO_H3];
7522 a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
7523
7524 if (b->tx_3m != (u32)btinfo.hb3.tx_3m)
7525 cx->cnt_bt[BTC_BCNT_RATECHG]++;
7526 b->tx_3m = (u32)btinfo.hb3.tx_3m;
7527
7528 a2dp->sink = btinfo.hb3.a2dp_sink;
7529
7530 if (!a2dp->exist_last && a2dp->exist) {
7531 a2dp->vendor_id = 0;
7532 a2dp->flush_time = 0;
7533 a2dp->play_latency = 1;
7534 ieee80211_queue_delayed_work(rtwdev->hw,
7535 &rtwdev->coex_bt_devinfo_work,
7536 RTW89_COEX_BT_DEVINFO_WORK_PERIOD);
7537 }
7538
7539 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
7540 }
7541
rtw89_btc_ntfy_role_info(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,struct rtw89_sta_link * rtwsta_link,enum btc_role_state state)7542 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev,
7543 struct rtw89_vif_link *rtwvif_link,
7544 struct rtw89_sta_link *rtwsta_link,
7545 enum btc_role_state state)
7546 {
7547 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
7548 rtwvif_link->chanctx_idx);
7549 struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
7550 struct ieee80211_bss_conf *bss_conf;
7551 struct ieee80211_link_sta *link_sta;
7552 struct rtw89_btc *btc = &rtwdev->btc;
7553 const struct rtw89_btc_ver *ver = btc->ver;
7554 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7555 struct rtw89_btc_wl_link_info r = {0};
7556 struct rtw89_btc_wl_link_info *wlinfo = NULL;
7557 u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type;
7558
7559 rcu_read_lock();
7560
7561 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
7562
7563 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
7564 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7565 "[BTC], role is STA=%d\n",
7566 vif->type == NL80211_IFTYPE_STATION);
7567 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif_link->port);
7568 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
7569 chan->band_type, chan->channel, chan->band_width);
7570 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
7571 state == BTC_ROLE_MSTS_STA_CONN_END);
7572 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7573 "[BTC], bcn_period=%d dtim_period=%d\n",
7574 bss_conf->beacon_int, bss_conf->dtim_period);
7575
7576 if (rtwsta_link) {
7577 link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
7578
7579 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
7580 rtwsta_link->mac_id);
7581
7582 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7583 "[BTC], STA support HE=%d VHT=%d HT=%d\n",
7584 link_sta->he_cap.has_he,
7585 link_sta->vht_cap.vht_supported,
7586 link_sta->ht_cap.ht_supported);
7587 if (link_sta->he_cap.has_he)
7588 mode |= BIT(BTC_WL_MODE_HE);
7589 if (link_sta->vht_cap.vht_supported)
7590 mode |= BIT(BTC_WL_MODE_VHT);
7591 if (link_sta->ht_cap.ht_supported)
7592 mode |= BIT(BTC_WL_MODE_HT);
7593
7594 r.mode = mode;
7595 }
7596
7597 if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) {
7598 rcu_read_unlock();
7599 return;
7600 }
7601
7602 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7603 "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role);
7604
7605 r.role = rtwvif_link->wifi_role;
7606 r.phy = rtwvif_link->phy_idx;
7607 r.pid = rtwvif_link->port;
7608 r.active = true;
7609 r.connected = MLME_LINKED;
7610 r.bcn_period = bss_conf->beacon_int;
7611 r.dtim_period = bss_conf->dtim_period;
7612 r.band = chan->band_type;
7613 r.ch = chan->channel;
7614 r.bw = chan->band_width;
7615 r.chdef.band = chan->band_type;
7616 r.chdef.center_ch = chan->channel;
7617 r.chdef.bw = chan->band_width;
7618 r.chdef.chan = chan->primary_channel;
7619 ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr);
7620
7621 rcu_read_unlock();
7622
7623 if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION)
7624 r.mac_id = rtwsta_link->mac_id;
7625
7626 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
7627
7628 wlinfo = &wl->link_info[r.pid];
7629
7630 rlink_id = 0; /* to do */
7631 if (ver->fwlrole == 0) {
7632 *wlinfo = r;
7633 _update_wl_info(rtwdev);
7634 } else if (ver->fwlrole == 1) {
7635 *wlinfo = r;
7636 _update_wl_info_v1(rtwdev);
7637 } else if (ver->fwlrole == 2) {
7638 *wlinfo = r;
7639 _update_wl_info_v2(rtwdev);
7640 } else if (ver->fwlrole == 7) {
7641 *wlinfo = r;
7642 _update_wl_info_v7(rtwdev, r.pid);
7643 } else if (ver->fwlrole == 8) {
7644 wlinfo = &wl->rlink_info[r.pid][rlink_id];
7645 *wlinfo = r;
7646 link_mode_ori = wl->role_info_v8.link_mode;
7647 pta_req_mac_ori = wl->pta_req_mac;
7648 _update_wl_info_v8(rtwdev, r.pid, rlink_id, state);
7649
7650 if (wl->role_info_v8.link_mode != link_mode_ori) {
7651 wl->role_info_v8.link_mode_chg = 1;
7652 if (ver->fcxinit == 7)
7653 wa_type = btc->mdinfo.md_v7.wa_type;
7654 else
7655 wa_type = btc->mdinfo.md.wa_type;
7656
7657 if (wa_type & BTC_WA_HFP_ZB)
7658 _update_zb_coex_tbl(rtwdev);
7659 }
7660
7661 if (wl->pta_req_mac != pta_req_mac_ori)
7662 wl->pta_reg_mac_chg = 1;
7663 }
7664
7665 if (wlinfo->role == RTW89_WIFI_ROLE_STATION &&
7666 wlinfo->connected == MLME_NO_LINK)
7667 btc->dm.leak_ap = 0;
7668
7669 if (state == BTC_ROLE_MSTS_STA_CONN_START)
7670 wl->status.map.connecting = 1;
7671 else
7672 wl->status.map.connecting = 0;
7673
7674 if (state == BTC_ROLE_MSTS_STA_DIS_CONN)
7675 wl->status.map._4way = false;
7676
7677 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
7678 }
7679
rtw89_btc_ntfy_radio_state(struct rtw89_dev * rtwdev,enum btc_rfctrl rf_state)7680 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state)
7681 {
7682 const struct rtw89_chip_info *chip = rtwdev->chip;
7683 struct rtw89_btc *btc = &rtwdev->btc;
7684 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7685 u32 val;
7686
7687 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
7688 __func__, rf_state);
7689 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
7690
7691 switch (rf_state) {
7692 case BTC_RFCTRL_WL_OFF:
7693 wl->status.map.rf_off = 1;
7694 wl->status.map.lps = BTC_LPS_OFF;
7695 wl->status.map.busy = 0;
7696 break;
7697 case BTC_RFCTRL_FW_CTRL:
7698 wl->status.map.rf_off = 0;
7699 wl->status.map.lps = BTC_LPS_RF_OFF;
7700 wl->status.map.busy = 0;
7701 break;
7702 case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */
7703 wl->status.map.rf_off = 0;
7704 wl->status.map.lps = BTC_LPS_RF_ON;
7705 wl->status.map.busy = 0;
7706 break;
7707 case BTC_RFCTRL_WL_ON:
7708 default:
7709 wl->status.map.rf_off = 0;
7710 wl->status.map.lps = BTC_LPS_OFF;
7711 break;
7712 }
7713
7714 if (rf_state == BTC_RFCTRL_WL_ON) {
7715 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, true);
7716 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG;
7717 _write_scbd(rtwdev, val, true);
7718 _update_bt_scbd(rtwdev, true);
7719 chip->ops->btc_init_cfg(rtwdev);
7720 } else {
7721 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false);
7722 if (rf_state == BTC_RFCTRL_FW_CTRL)
7723 _write_scbd(rtwdev, BTC_WSCB_ACTIVE, false);
7724 else if (rf_state == BTC_RFCTRL_WL_OFF)
7725 _write_scbd(rtwdev, BTC_WSCB_ALL, false);
7726 else
7727 _write_scbd(rtwdev, BTC_WSCB_ACTIVE, false);
7728
7729 if (rf_state == BTC_RFCTRL_LPS_WL_ON &&
7730 wl->status.map.lps_pre != BTC_LPS_OFF)
7731 _update_bt_scbd(rtwdev, true);
7732 }
7733
7734 btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
7735 btc->dm.tdma_instant_excute = 1;
7736
7737 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
7738 wl->status.map.rf_off_pre = wl->status.map.rf_off;
7739 wl->status.map.lps_pre = wl->status.map.lps;
7740 }
7741
_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_path,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)7742 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path,
7743 enum btc_wl_rfk_type type,
7744 enum btc_wl_rfk_state state)
7745 {
7746 struct rtw89_btc *btc = &rtwdev->btc;
7747 struct rtw89_btc_cx *cx = &btc->cx;
7748 struct rtw89_btc_wl_info *wl = &cx->wl;
7749 bool result = BTC_WRFK_REJECT;
7750
7751 wl->rfk_info.type = type;
7752 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path);
7753 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path);
7754 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path);
7755
7756 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7757 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
7758 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
7759 type, state);
7760
7761 switch (state) {
7762 case BTC_WRFK_START:
7763 result = _chk_wl_rfk_request(rtwdev);
7764 wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP;
7765
7766 _write_scbd(rtwdev, BTC_WSCB_WLRFK, result);
7767
7768 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
7769 break;
7770 case BTC_WRFK_ONESHOT_START:
7771 case BTC_WRFK_ONESHOT_STOP:
7772 if (wl->rfk_info.state == BTC_WRFK_STOP) {
7773 result = BTC_WRFK_REJECT;
7774 } else {
7775 result = BTC_WRFK_ALLOW;
7776 wl->rfk_info.state = state;
7777 }
7778 break;
7779 case BTC_WRFK_STOP:
7780 result = BTC_WRFK_ALLOW;
7781 wl->rfk_info.state = BTC_WRFK_STOP;
7782
7783 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
7784 cancel_delayed_work(&rtwdev->coex_rfk_chk_work);
7785 break;
7786 default:
7787 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7788 "[BTC], %s() warning state=%d\n", __func__, state);
7789 break;
7790 }
7791
7792 if (result == BTC_WRFK_ALLOW) {
7793 if (wl->rfk_info.state == BTC_WRFK_START ||
7794 wl->rfk_info.state == BTC_WRFK_STOP)
7795 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK);
7796
7797 if (wl->rfk_info.state == BTC_WRFK_START)
7798 ieee80211_queue_delayed_work(rtwdev->hw,
7799 &rtwdev->coex_rfk_chk_work,
7800 RTW89_COEX_RFK_CHK_WORK_PERIOD);
7801 }
7802
7803 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7804 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
7805 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
7806
7807 return result == BTC_WRFK_ALLOW;
7808 }
7809
rtw89_btc_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_map,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)7810 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
7811 enum btc_wl_rfk_type type,
7812 enum btc_wl_rfk_state state)
7813 {
7814 u8 band;
7815 bool allow;
7816 int ret;
7817
7818 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map);
7819
7820 rtw89_debug(rtwdev, RTW89_DBG_RFK,
7821 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n",
7822 band == RTW89_BAND_2G ? "2G" :
7823 band == RTW89_BAND_5G ? "5G" : "6G",
7824 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)),
7825 type,
7826 FIELD_GET(BTC_RFK_PATH_MAP, phy_map),
7827 state == BTC_WRFK_STOP ? "RFK_STOP" :
7828 state == BTC_WRFK_START ? "RFK_START" :
7829 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" :
7830 "ONE-SHOT_STOP");
7831
7832 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) {
7833 _ntfy_wl_rfk(rtwdev, phy_map, type, state);
7834 return;
7835 }
7836
7837 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false,
7838 rtwdev, phy_map, type, state);
7839 if (ret) {
7840 rtw89_warn(rtwdev, "RFK notify timeout\n");
7841 rtwdev->is_bt_iqk_timeout = true;
7842 }
7843 }
7844 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk);
7845
7846 struct rtw89_btc_wl_sta_iter_data {
7847 struct rtw89_dev *rtwdev;
7848 u8 busy_all;
7849 u8 dir_all;
7850 u8 rssi_map_all;
7851 bool is_sta_change;
7852 bool is_traffic_change;
7853 };
7854
7855 static
__rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link * rtwvif_link,struct rtw89_sta_link * rtwsta_link,struct rtw89_btc_wl_sta_iter_data * iter_data)7856 void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link,
7857 struct rtw89_sta_link *rtwsta_link,
7858 struct rtw89_btc_wl_sta_iter_data *iter_data)
7859 {
7860 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
7861 struct rtw89_dev *rtwdev = iter_data->rtwdev;
7862 struct rtw89_btc *btc = &rtwdev->btc;
7863 struct rtw89_btc_dm *dm = &btc->dm;
7864 const struct rtw89_btc_ver *ver = btc->ver;
7865 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7866 struct rtw89_btc_wl_link_info *link_info = NULL;
7867 struct rtw89_traffic_stats *link_info_t = NULL;
7868 struct rtw89_traffic_stats *stats = &rtwvif->stats;
7869 const struct rtw89_chip_info *chip = rtwdev->chip;
7870 struct rtw89_btc_wl_role_info *r;
7871 struct rtw89_btc_wl_role_info_v1 *r1;
7872 u32 last_tx_rate, last_rx_rate;
7873 u16 last_tx_lvl, last_rx_lvl;
7874 u8 port = rtwvif_link->port;
7875 u8 rssi;
7876 u8 busy = 0;
7877 u8 dir = 0;
7878 u8 rssi_map = 0;
7879 u8 i = 0;
7880 bool is_sta_change = false, is_traffic_change = false;
7881
7882 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR;
7883 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
7884
7885 link_info = &wl->link_info[port];
7886 link_info->stat.traffic = *stats;
7887 link_info_t = &link_info->stat.traffic;
7888
7889 if (link_info->connected == MLME_NO_LINK) {
7890 link_info->rx_rate_drop_cnt = 0;
7891 return;
7892 }
7893
7894 link_info->stat.rssi = rssi;
7895 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) {
7896 link_info->rssi_state[i] =
7897 _update_rssi_state(rtwdev,
7898 link_info->rssi_state[i],
7899 link_info->stat.rssi,
7900 chip->wl_rssi_thres[i]);
7901 if (BTC_RSSI_LOW(link_info->rssi_state[i]))
7902 rssi_map |= BIT(i);
7903
7904 if (btc->ant_type == BTC_ANT_DEDICATED &&
7905 BTC_RSSI_CHANGE(link_info->rssi_state[i]))
7906 is_sta_change = true;
7907 }
7908 iter_data->rssi_map_all |= rssi_map;
7909
7910 last_tx_rate = link_info_t->tx_rate;
7911 last_rx_rate = link_info_t->rx_rate;
7912 last_tx_lvl = (u16)link_info_t->tx_tfc_lv;
7913 last_rx_lvl = (u16)link_info_t->rx_tfc_lv;
7914
7915 if (stats->tx_tfc_lv != RTW89_TFC_IDLE ||
7916 stats->rx_tfc_lv != RTW89_TFC_IDLE)
7917 busy = 1;
7918
7919 if (stats->tx_tfc_lv > stats->rx_tfc_lv)
7920 dir = RTW89_TFC_UL;
7921 else
7922 dir = RTW89_TFC_DL;
7923
7924 link_info = &wl->link_info[port];
7925 if (link_info->busy != busy || link_info->dir != dir) {
7926 is_sta_change = true;
7927 link_info->busy = busy;
7928 link_info->dir = dir;
7929 }
7930
7931 iter_data->busy_all |= busy;
7932 iter_data->dir_all |= BIT(dir);
7933
7934 if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
7935 last_rx_rate > RTW89_HW_RATE_CCK2 &&
7936 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
7937 link_info->rx_rate_drop_cnt++;
7938
7939 if (last_tx_rate != rtwsta_link->ra_report.hw_rate ||
7940 last_rx_rate != rtwsta_link->rx_hw_rate ||
7941 last_tx_lvl != link_info_t->tx_tfc_lv ||
7942 last_rx_lvl != link_info_t->rx_tfc_lv)
7943 is_traffic_change = true;
7944
7945 link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate;
7946 link_info_t->rx_rate = rtwsta_link->rx_hw_rate;
7947
7948 if (link_info->role == RTW89_WIFI_ROLE_STATION ||
7949 link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) {
7950 dm->trx_info.tx_rate = link_info_t->tx_rate;
7951 dm->trx_info.rx_rate = link_info_t->rx_rate;
7952 }
7953
7954 if (ver->fwlrole == 0) {
7955 r = &wl->role_info;
7956 r->active_role[port].tx_lvl = stats->tx_tfc_lv;
7957 r->active_role[port].rx_lvl = stats->rx_tfc_lv;
7958 r->active_role[port].tx_rate = rtwsta_link->ra_report.hw_rate;
7959 r->active_role[port].rx_rate = rtwsta_link->rx_hw_rate;
7960 } else if (ver->fwlrole == 1) {
7961 r1 = &wl->role_info_v1;
7962 r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv;
7963 r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv;
7964 r1->active_role_v1[port].tx_rate = rtwsta_link->ra_report.hw_rate;
7965 r1->active_role_v1[port].rx_rate = rtwsta_link->rx_hw_rate;
7966 } else if (ver->fwlrole == 2) {
7967 dm->trx_info.tx_lvl = stats->tx_tfc_lv;
7968 dm->trx_info.rx_lvl = stats->rx_tfc_lv;
7969 dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate;
7970 dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate;
7971 }
7972
7973 dm->trx_info.tx_tp = link_info_t->tx_throughput;
7974 dm->trx_info.rx_tp = link_info_t->rx_throughput;
7975
7976 /* Trigger coex-run if 0x10980 reg-value is diff with coex setup */
7977 if ((dm->wl_btg_rx_rb != dm->wl_btg_rx &&
7978 dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) ||
7979 (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
7980 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND))
7981 iter_data->is_sta_change = true;
7982
7983 if (is_sta_change)
7984 iter_data->is_sta_change = true;
7985
7986 if (is_traffic_change)
7987 iter_data->is_traffic_change = true;
7988 }
7989
rtw89_btc_ntfy_wl_sta_iter(void * data,struct ieee80211_sta * sta)7990 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
7991 {
7992 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
7993 struct rtw89_btc_wl_sta_iter_data *iter_data =
7994 (struct rtw89_btc_wl_sta_iter_data *)data;
7995 struct rtw89_vif_link *rtwvif_link;
7996 struct rtw89_sta_link *rtwsta_link;
7997 unsigned int link_id;
7998
7999 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
8000 rtwvif_link = rtwsta_link->rtwvif_link;
8001 __rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data);
8002 }
8003 }
8004
8005 #define BTC_NHM_CHK_INTVL 20
8006
rtw89_btc_ntfy_wl_sta(struct rtw89_dev * rtwdev)8007 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
8008 {
8009 struct rtw89_btc *btc = &rtwdev->btc;
8010 struct rtw89_btc_dm *dm = &btc->dm;
8011 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8012 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev};
8013 u8 i;
8014
8015 ieee80211_iterate_stations_atomic(rtwdev->hw,
8016 rtw89_btc_ntfy_wl_sta_iter,
8017 &data);
8018
8019 wl->rssi_level = 0;
8020 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++;
8021 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) {
8022 /* set RSSI level 4 ~ 0 if rssi bit map match */
8023 if (data.rssi_map_all & BIT(i - 1)) {
8024 wl->rssi_level = i;
8025 break;
8026 }
8027 }
8028
8029 if (dm->trx_info.wl_rssi != wl->rssi_level)
8030 dm->trx_info.wl_rssi = wl->rssi_level;
8031
8032 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n",
8033 __func__, !!wl->status.map.busy);
8034
8035 _write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy));
8036
8037 if (data.is_traffic_change)
8038 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
8039 if (data.is_sta_change) {
8040 wl->status.map.busy = data.busy_all;
8041 wl->status.map.traffic_dir = data.dir_all;
8042 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA);
8043 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >=
8044 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) {
8045 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
8046 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
8047 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] <
8048 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) {
8049 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
8050 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
8051 }
8052 }
8053
rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev * rtwdev,u8 func)8054 static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func)
8055 {
8056 struct rtw89_btc *btc = &rtwdev->btc;
8057 const struct rtw89_btc_ver *ver = btc->ver;
8058
8059 switch (func) {
8060 case BTF_EVNT_RPT:
8061 case BTF_EVNT_BT_INFO:
8062 case BTF_EVNT_BT_SCBD:
8063 case BTF_EVNT_BT_REG:
8064 case BTF_EVNT_CX_RUNINFO:
8065 case BTF_EVNT_BT_PSD:
8066 return func;
8067 case BTF_EVNT_BT_DEV_INFO:
8068 if (ver->fwc2hfunc == 0)
8069 return BTF_EVNT_BUF_OVERFLOW;
8070 else
8071 return BTF_EVNT_BT_DEV_INFO;
8072 case BTF_EVNT_BT_LEAUDIO_INFO:
8073 if (ver->fwc2hfunc == 0)
8074 return BTF_EVNT_C2H_LOOPBACK;
8075 else if (ver->fwc2hfunc == 1)
8076 return BTF_EVNT_BUF_OVERFLOW;
8077 else if (ver->fwc2hfunc == 2)
8078 return func;
8079 else
8080 return BTF_EVNT_MAX;
8081 case BTF_EVNT_BUF_OVERFLOW:
8082 if (ver->fwc2hfunc == 0)
8083 return BTF_EVNT_MAX;
8084 else if (ver->fwc2hfunc == 1)
8085 return BTF_EVNT_C2H_LOOPBACK;
8086 else if (ver->fwc2hfunc == 2)
8087 return func;
8088 else
8089 return BTF_EVNT_MAX;
8090 case BTF_EVNT_C2H_LOOPBACK:
8091 if (ver->fwc2hfunc == 2)
8092 return func;
8093 else
8094 return BTF_EVNT_MAX;
8095 case BTF_EVNT_MAX:
8096 default:
8097 return BTF_EVNT_MAX;
8098 }
8099 }
8100
rtw89_btc_c2h_handle(struct rtw89_dev * rtwdev,struct sk_buff * skb,u32 len,u8 class,u8 func)8101 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
8102 u32 len, u8 class, u8 func)
8103 {
8104 struct rtw89_btc *btc = &rtwdev->btc;
8105 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
8106 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN];
8107
8108 len -= RTW89_C2H_HEADER_LEN;
8109
8110 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8111 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n",
8112 __func__, len, class, func);
8113
8114 if (class != BTFC_FW_EVENT)
8115 return;
8116
8117 func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func);
8118
8119 switch (func) {
8120 case BTF_EVNT_BUF_OVERFLOW:
8121 pfwinfo->event[func]++;
8122 break;
8123 case BTF_EVNT_RPT:
8124 pfwinfo->event[func]++;
8125 /* Don't need rtw89_leave_ps_mode() */
8126 btc_fw_event(rtwdev, func, buf, len);
8127 break;
8128 case BTF_EVNT_BT_INFO:
8129 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8130 "[BTC], handle C2H BT INFO with data %8ph\n", buf);
8131 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++;
8132 _update_bt_info(rtwdev, buf, len);
8133 break;
8134 case BTF_EVNT_BT_SCBD:
8135 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8136 "[BTC], handle C2H BT SCBD with data %8ph\n", buf);
8137 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++;
8138 _update_bt_scbd(rtwdev, false);
8139 break;
8140 case BTF_EVNT_BT_PSD:
8141 break;
8142 case BTF_EVNT_BT_REG:
8143 btc->dbg.rb_done = true;
8144 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf));
8145
8146 break;
8147 case BTF_EVNT_C2H_LOOPBACK:
8148 btc->dbg.rb_done = true;
8149 btc->dbg.rb_val = buf[0];
8150 break;
8151 case BTF_EVNT_CX_RUNINFO:
8152 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
8153 break;
8154 }
8155 }
8156
8157 #define BTC_CX_FW_OFFLOAD 0
8158
_show_cx_info(struct rtw89_dev * rtwdev,struct seq_file * m)8159 static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m)
8160 {
8161 union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo;
8162 const struct rtw89_chip_info *chip = rtwdev->chip;
8163 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
8164 struct rtw89_hal *hal = &rtwdev->hal;
8165 struct rtw89_btc *btc = &rtwdev->btc;
8166 struct rtw89_btc_dm *dm = &btc->dm;
8167 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
8168 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8169 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
8170 u8 cv, rfe, iso, ant_num, ant_single_pos;
8171
8172 if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
8173 return;
8174
8175 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
8176
8177 seq_printf(m, "========== [BTC COEX INFO (%d)] ==========\n",
8178 chip->chip_id);
8179
8180 ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION);
8181 ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION);
8182 ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION);
8183 id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION);
8184 seq_printf(m, " %-15s : Coex:%d.%d.%d(branch:%d), ",
8185 "[coex_version]", ver_main, ver_sub, ver_hotfix, id_branch);
8186
8187 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
8188 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex);
8189 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex);
8190 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex);
8191 seq_printf(m, "WL_FW_coex:%d.%d.%d(branch:%d)",
8192 ver_main, ver_sub, ver_hotfix, id_branch);
8193
8194 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired);
8195 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired);
8196 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
8197 seq_printf(m, "(%s, desired:%d.%d.%d), ",
8198 (wl->ver_info.fw_coex >= chip->wlcx_desired ?
8199 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
8200
8201 seq_printf(m, "BT_FW_coex:%d(%s, desired:%d)\n",
8202 bt->ver_info.fw_coex,
8203 (bt->ver_info.fw_coex >= chip->btcx_desired ?
8204 "Match" : "Mismatch"), chip->btcx_desired);
8205
8206 if (bt->enable.now && bt->ver_info.fw == 0)
8207 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true);
8208 else
8209 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false);
8210
8211 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw);
8212 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw);
8213 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw);
8214 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw);
8215 seq_printf(m, " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n",
8216 "[sub_module]",
8217 ver_main, ver_sub, ver_hotfix, id_branch,
8218 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM");
8219
8220 if (ver->fcxinit == 7) {
8221 cv = md->md_v7.kt_ver;
8222 rfe = md->md_v7.rfe_type;
8223 iso = md->md_v7.ant.isolation;
8224 ant_num = md->md_v7.ant.num;
8225 ant_single_pos = md->md_v7.ant.single_pos;
8226 } else {
8227 cv = md->md.cv;
8228 rfe = md->md.rfe_type;
8229 iso = md->md.ant.isolation;
8230 ant_num = md->md.ant.num;
8231 ant_single_pos = md->md.ant.single_pos;
8232 }
8233
8234 seq_printf(m, " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s",
8235 "[hw_info]", cv, rfe, iso, ant_num,
8236 ant_num > 1 ? "" :
8237 ant_single_pos ? "1Ant_Pos:S1, " : "1Ant_Pos:S0, ");
8238
8239 seq_printf(m, "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n",
8240 btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss,
8241 hal->rx_nss);
8242 }
8243
_show_wl_role_info(struct rtw89_dev * rtwdev,struct seq_file * m)8244 static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m)
8245 {
8246 struct rtw89_btc *btc = &rtwdev->btc;
8247 struct rtw89_btc_wl_link_info *plink = NULL;
8248 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8249 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
8250 struct rtw89_traffic_stats *t;
8251 u8 i;
8252
8253 if (rtwdev->dbcc_en) {
8254 seq_printf(m,
8255 " %-15s : PHY0_band(op:%d/scan:%d/real:%d), ",
8256 "[dbcc_info]", wl_dinfo->op_band[RTW89_PHY_0],
8257 wl_dinfo->scan_band[RTW89_PHY_0],
8258 wl_dinfo->real_band[RTW89_PHY_0]);
8259 seq_printf(m,
8260 "PHY1_band(op:%d/scan:%d/real:%d)\n",
8261 wl_dinfo->op_band[RTW89_PHY_1],
8262 wl_dinfo->scan_band[RTW89_PHY_1],
8263 wl_dinfo->real_band[RTW89_PHY_1]);
8264 }
8265
8266 for (i = 0; i < RTW89_PORT_NUM; i++) {
8267 if (btc->ver->fwlrole == 8)
8268 plink = &btc->cx.wl.rlink_info[i][0];
8269 else
8270 plink = &btc->cx.wl.link_info[i];
8271
8272 if (!plink->active)
8273 continue;
8274
8275 seq_printf(m,
8276 " [port_%d] : role=%d(phy-%d), connect=%d(client_cnt=%d), mode=%d, center_ch=%d, bw=%d",
8277 plink->pid, (u32)plink->role, plink->phy,
8278 (u32)plink->connected, plink->client_cnt - 1,
8279 (u32)plink->mode, plink->ch, (u32)plink->bw);
8280
8281 if (plink->connected == MLME_NO_LINK)
8282 continue;
8283
8284 seq_printf(m,
8285 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n",
8286 plink->mac_id, plink->tx_time, plink->tx_retry);
8287
8288 seq_printf(m,
8289 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
8290 plink->pid, 110 - plink->stat.rssi,
8291 plink->stat.rssi, plink->busy,
8292 plink->dir == RTW89_TFC_UL ? "UL" : "DL");
8293
8294 t = &plink->stat.traffic;
8295
8296 seq_printf(m,
8297 "tx[rate:%d/busy_level:%d], ",
8298 (u32)t->tx_rate, t->tx_tfc_lv);
8299
8300 seq_printf(m, "rx[rate:%d/busy_level:%d/drop:%d]\n",
8301 (u32)t->rx_rate,
8302 t->rx_tfc_lv, plink->rx_rate_drop_cnt);
8303 }
8304 }
8305
_show_wl_info(struct rtw89_dev * rtwdev,struct seq_file * m)8306 static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m)
8307 {
8308 struct rtw89_btc *btc = &rtwdev->btc;
8309 const struct rtw89_btc_ver *ver = btc->ver;
8310 struct rtw89_btc_cx *cx = &btc->cx;
8311 struct rtw89_btc_wl_info *wl = &cx->wl;
8312 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
8313 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
8314 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
8315 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
8316 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
8317 u8 mode;
8318
8319 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
8320 return;
8321
8322 seq_puts(m, "========== [WL Status] ==========\n");
8323
8324 if (ver->fwlrole == 0)
8325 mode = wl_rinfo->link_mode;
8326 else if (ver->fwlrole == 1)
8327 mode = wl_rinfo_v1->link_mode;
8328 else if (ver->fwlrole == 2)
8329 mode = wl_rinfo_v2->link_mode;
8330 else if (ver->fwlrole == 7)
8331 mode = wl_rinfo_v7->link_mode;
8332 else if (ver->fwlrole == 8)
8333 mode = wl_rinfo_v8->link_mode;
8334 else
8335 return;
8336
8337 seq_printf(m, " %-15s : link_mode:%d, ", "[status]", mode);
8338
8339 seq_printf(m,
8340 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ",
8341 wl->status.map.rf_off, wl->status.map.lps,
8342 wl->status.map.scan ? "Y" : "N",
8343 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
8344
8345 seq_printf(m,
8346 "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n",
8347 wl->status.map.connecting ? "Y" : "N",
8348 wl->status.map.roaming ? "Y" : "N",
8349 wl->status.map._4way ? "Y" : "N",
8350 wl->status.map.init_ok ? "Y" : "N");
8351
8352 _show_wl_role_info(rtwdev, m);
8353 }
8354
8355 enum btc_bt_a2dp_type {
8356 BTC_A2DP_LEGACY = 0,
8357 BTC_A2DP_TWS_SNIFF = 1,
8358 BTC_A2DP_TWS_RELAY = 2,
8359 };
8360
_show_bt_profile_info(struct rtw89_dev * rtwdev,struct seq_file * m)8361 static void _show_bt_profile_info(struct rtw89_dev *rtwdev, struct seq_file *m)
8362 {
8363 struct rtw89_btc *btc = &rtwdev->btc;
8364 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
8365 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
8366 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
8367 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
8368 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
8369
8370 if (hfp.exist) {
8371 seq_printf(m, " %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
8372 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"),
8373 bt_linfo->sut_pwr_level[0],
8374 bt_linfo->golden_rx_shift[0]);
8375 }
8376
8377 if (hid.exist) {
8378 seq_printf(m,
8379 "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n",
8380 "[HID]",
8381 hid.type & BTC_HID_218 ? "2/18," : "",
8382 hid.type & BTC_HID_418 ? "4/18," : "",
8383 hid.type & BTC_HID_BLE ? "BLE," : "",
8384 hid.type & BTC_HID_RCU ? "RCU," : "",
8385 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "",
8386 hid.pair_cnt, bt_linfo->sut_pwr_level[1],
8387 bt_linfo->golden_rx_shift[1]);
8388 }
8389
8390 if (a2dp.exist) {
8391 seq_printf(m,
8392 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
8393 "[A2DP]",
8394 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS",
8395 a2dp.bitpool, a2dp.flush_time);
8396
8397 seq_printf(m,
8398 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n",
8399 a2dp.vendor_id, a2dp.device_name,
8400 bt_linfo->sut_pwr_level[2],
8401 bt_linfo->golden_rx_shift[2]);
8402 }
8403
8404 if (pan.exist) {
8405 seq_printf(m, " %-15s : sut_pwr:%d, golden-rx:%d\n",
8406 "[PAN]",
8407 bt_linfo->sut_pwr_level[3],
8408 bt_linfo->golden_rx_shift[3]);
8409 }
8410 }
8411
_show_bt_info(struct rtw89_dev * rtwdev,struct seq_file * m)8412 static void _show_bt_info(struct rtw89_dev *rtwdev, struct seq_file *m)
8413 {
8414 struct rtw89_btc *btc = &rtwdev->btc;
8415 const struct rtw89_btc_ver *ver = btc->ver;
8416 struct rtw89_btc_cx *cx = &btc->cx;
8417 struct rtw89_btc_bt_info *bt = &cx->bt;
8418 struct rtw89_btc_wl_info *wl = &cx->wl;
8419 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
8420 union rtw89_btc_module_info *md = &btc->mdinfo;
8421 u8 *afh = bt_linfo->afh_map;
8422 u8 *afh_le = bt_linfo->afh_map_le;
8423 u8 bt_pos;
8424
8425 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
8426 return;
8427
8428 if (ver->fcxinit == 7)
8429 bt_pos = md->md_v7.bt_pos;
8430 else
8431 bt_pos = md->md.bt_pos;
8432
8433 seq_puts(m, "========== [BT Status] ==========\n");
8434
8435 seq_printf(m, " %-15s : enable:%s, btg:%s%s, connect:%s, ",
8436 "[status]", bt->enable.now ? "Y" : "N",
8437 bt->btg_type ? "Y" : "N",
8438 (bt->enable.now && (bt->btg_type != bt_pos) ?
8439 "(efuse-mismatch!!)" : ""),
8440 (bt_linfo->status.map.connect ? "Y" : "N"));
8441
8442 seq_printf(m, "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n",
8443 bt->igno_wl ? "Y" : "N",
8444 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val);
8445
8446 seq_printf(m, " %-15s : profile:%s%s%s%s%s ",
8447 "[profile]",
8448 (bt_linfo->profile_cnt.now == 0) ? "None," : "",
8449 bt_linfo->hfp_desc.exist ? "HFP," : "",
8450 bt_linfo->hid_desc.exist ? "HID," : "",
8451 bt_linfo->a2dp_desc.exist ?
8452 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "",
8453 bt_linfo->pan_desc.exist ? "PAN," : "");
8454
8455 seq_printf(m,
8456 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n",
8457 bt_linfo->multi_link.now ? "Y" : "N",
8458 bt_linfo->slave_role ? "Slave" : "Master",
8459 bt_linfo->status.map.ble_connect ? "Y" : "N",
8460 bt_linfo->cqddr ? "Y" : "N",
8461 bt_linfo->a2dp_desc.active ? "Y" : "N",
8462 bt_linfo->pan_desc.active ? "Y" : "N");
8463
8464 seq_printf(m,
8465 " %-15s : rssi:%ddBm(lvl:%d), tx_rate:%dM, %s%s%s",
8466 "[link]", bt_linfo->rssi - 100,
8467 bt->rssi_level,
8468 bt_linfo->tx_3m ? 3 : 2,
8469 bt_linfo->status.map.inq_pag ? " inq-page!!" : "",
8470 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "",
8471 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : "");
8472
8473 seq_printf(m,
8474 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
8475 bt_linfo->relink.now ? " ReLink!!" : "",
8476 afh[0], afh[1], afh[2], afh[3], afh[4],
8477 afh[5], afh[6], afh[7], afh[8], afh[9]);
8478
8479 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
8480 seq_printf(m,
8481 "LE[%02x%02x_%02x_%02x%02x]",
8482 afh_le[0], afh_le[1], afh_le[2],
8483 afh_le[3], afh_le[4]);
8484
8485 seq_printf(m, "wl_ch_map[en:%d/ch:%d/bw:%d]\n",
8486 wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw);
8487
8488 seq_printf(m,
8489 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
8490 "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY],
8491 cx->cnt_bt[BTC_BCNT_RELINK], cx->cnt_bt[BTC_BCNT_RATECHG],
8492 cx->cnt_bt[BTC_BCNT_REINIT], cx->cnt_bt[BTC_BCNT_REENABLE]);
8493
8494 seq_printf(m,
8495 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n",
8496 cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH],
8497 cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ],
8498 cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]);
8499
8500 _show_bt_profile_info(rtwdev, m);
8501
8502 seq_printf(m,
8503 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n",
8504 "[bt_info]", bt->raw_info[2], bt->raw_info[3],
8505 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6],
8506 bt->raw_info[7],
8507 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
8508 cx->cnt_bt[BTC_BCNT_INFOUPDATE],
8509 cx->cnt_bt[BTC_BCNT_INFOSAME]);
8510
8511 seq_printf(m,
8512 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)",
8513 "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX],
8514 cx->cnt_bt[BTC_BCNT_HIPRI_TX], cx->cnt_bt[BTC_BCNT_LOPRI_RX],
8515 cx->cnt_bt[BTC_BCNT_LOPRI_TX], cx->cnt_bt[BTC_BCNT_POLUT]);
8516
8517 if (!bt->scan_info_update) {
8518 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, true);
8519 seq_puts(m, "\n");
8520 } else {
8521 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, false);
8522 if (ver->fcxbtscan == 1) {
8523 seq_printf(m,
8524 "(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)",
8525 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win),
8526 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl),
8527 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win),
8528 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl),
8529 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win),
8530 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl),
8531 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win),
8532 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl));
8533 } else if (ver->fcxbtscan == 2) {
8534 seq_printf(m,
8535 "(BG:%d-%d/INIT:%d-%d/LE:%d-%d)",
8536 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win),
8537 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl),
8538 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win),
8539 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl),
8540 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win),
8541 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl));
8542 }
8543 seq_puts(m, "\n");
8544 }
8545
8546 if (bt_linfo->profile_cnt.now || bt_linfo->status.map.ble_connect)
8547 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, true);
8548 else
8549 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, false);
8550
8551 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
8552 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, true);
8553 else
8554 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, false);
8555
8556 if (bt_linfo->a2dp_desc.exist &&
8557 (bt_linfo->a2dp_desc.flush_time == 0 ||
8558 bt_linfo->a2dp_desc.vendor_id == 0 ||
8559 bt_linfo->a2dp_desc.play_latency == 1))
8560 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, true);
8561 else
8562 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, false);
8563 }
8564
8565 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e
8566 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
8567 #define CASE_BTC_POLICY_STR(e) \
8568 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
8569 #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e
8570 #define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e
8571 #define CASE_BTC_INIT(e) case BTC_MODE_## e: return #e
8572 #define CASE_BTC_ANTPATH_STR(e) case BTC_ANT_##e: return #e
8573 #define CASE_BTC_POLUT_STR(e) case BTC_PLT_## e: return #e
8574 #define CASE_BTC_REGTYPE_STR(e) case REG_## e: return #e
8575 #define CASE_BTC_GDBG_STR(e) case BTC_DBG_## e: return #e
8576
id_to_polut(u32 id)8577 static const char *id_to_polut(u32 id)
8578 {
8579 switch (id) {
8580 CASE_BTC_POLUT_STR(NONE);
8581 CASE_BTC_POLUT_STR(GNT_BT_TX);
8582 CASE_BTC_POLUT_STR(GNT_BT_RX);
8583 CASE_BTC_POLUT_STR(GNT_WL);
8584 CASE_BTC_POLUT_STR(BT);
8585 CASE_BTC_POLUT_STR(ALL);
8586 default:
8587 return "unknown";
8588 }
8589 }
8590
id_to_regtype(u32 id)8591 static const char *id_to_regtype(u32 id)
8592 {
8593 switch (id) {
8594 CASE_BTC_REGTYPE_STR(MAC);
8595 CASE_BTC_REGTYPE_STR(BB);
8596 CASE_BTC_REGTYPE_STR(RF);
8597 CASE_BTC_REGTYPE_STR(BT_RF);
8598 CASE_BTC_REGTYPE_STR(BT_MODEM);
8599 CASE_BTC_REGTYPE_STR(BT_BLUEWIZE);
8600 CASE_BTC_REGTYPE_STR(BT_VENDOR);
8601 CASE_BTC_REGTYPE_STR(BT_LE);
8602 default:
8603 return "unknown";
8604 }
8605 }
8606
id_to_gdbg(u32 id)8607 static const char *id_to_gdbg(u32 id)
8608 {
8609 switch (id) {
8610 CASE_BTC_GDBG_STR(GNT_BT);
8611 CASE_BTC_GDBG_STR(GNT_WL);
8612 CASE_BTC_GDBG_STR(BCN_EARLY);
8613 CASE_BTC_GDBG_STR(WL_NULL0);
8614 CASE_BTC_GDBG_STR(WL_NULL1);
8615 CASE_BTC_GDBG_STR(WL_RXISR);
8616 CASE_BTC_GDBG_STR(TDMA_ENTRY);
8617 CASE_BTC_GDBG_STR(A2DP_EMPTY);
8618 CASE_BTC_GDBG_STR(BT_RETRY);
8619 CASE_BTC_GDBG_STR(BT_RELINK);
8620 CASE_BTC_GDBG_STR(SLOT_WL);
8621 CASE_BTC_GDBG_STR(SLOT_BT);
8622 CASE_BTC_GDBG_STR(WL_ERR);
8623 CASE_BTC_GDBG_STR(WL_OK);
8624 CASE_BTC_GDBG_STR(SLOT_B2W);
8625 CASE_BTC_GDBG_STR(SLOT_W1);
8626 CASE_BTC_GDBG_STR(SLOT_W2);
8627 CASE_BTC_GDBG_STR(SLOT_W2B);
8628 CASE_BTC_GDBG_STR(SLOT_B1);
8629 CASE_BTC_GDBG_STR(SLOT_B2);
8630 CASE_BTC_GDBG_STR(SLOT_B3);
8631 CASE_BTC_GDBG_STR(SLOT_B4);
8632 CASE_BTC_GDBG_STR(SLOT_LK);
8633 CASE_BTC_GDBG_STR(SLOT_E2G);
8634 CASE_BTC_GDBG_STR(SLOT_E5G);
8635 CASE_BTC_GDBG_STR(SLOT_EBT);
8636 CASE_BTC_GDBG_STR(SLOT_WLK);
8637 CASE_BTC_GDBG_STR(SLOT_B1FDD);
8638 CASE_BTC_GDBG_STR(BT_CHANGE);
8639 CASE_BTC_GDBG_STR(WL_CCA);
8640 CASE_BTC_GDBG_STR(BT_LEAUDIO);
8641 CASE_BTC_GDBG_STR(USER_DEF);
8642 default:
8643 return "unknown";
8644 }
8645 }
8646
steps_to_str(u16 step)8647 static const char *steps_to_str(u16 step)
8648 {
8649 switch (step) {
8650 CASE_BTC_RSN_STR(NONE);
8651 CASE_BTC_RSN_STR(NTFY_INIT);
8652 CASE_BTC_RSN_STR(NTFY_SWBAND);
8653 CASE_BTC_RSN_STR(NTFY_WL_STA);
8654 CASE_BTC_RSN_STR(NTFY_RADIO_STATE);
8655 CASE_BTC_RSN_STR(UPDATE_BT_SCBD);
8656 CASE_BTC_RSN_STR(NTFY_WL_RFK);
8657 CASE_BTC_RSN_STR(UPDATE_BT_INFO);
8658 CASE_BTC_RSN_STR(NTFY_SCAN_START);
8659 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH);
8660 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET);
8661 CASE_BTC_RSN_STR(NTFY_POWEROFF);
8662 CASE_BTC_RSN_STR(NTFY_ROLE_INFO);
8663 CASE_BTC_RSN_STR(CMD_SET_COEX);
8664 CASE_BTC_RSN_STR(ACT1_WORK);
8665 CASE_BTC_RSN_STR(BT_DEVINFO_WORK);
8666 CASE_BTC_RSN_STR(RFK_CHK_WORK);
8667
8668 CASE_BTC_ACT_STR(NONE);
8669 CASE_BTC_ACT_STR(WL_ONLY);
8670 CASE_BTC_ACT_STR(WL_5G);
8671 CASE_BTC_ACT_STR(WL_OTHER);
8672 CASE_BTC_ACT_STR(WL_IDLE);
8673 CASE_BTC_ACT_STR(WL_NC);
8674 CASE_BTC_ACT_STR(WL_RFK);
8675 CASE_BTC_ACT_STR(WL_INIT);
8676 CASE_BTC_ACT_STR(WL_OFF);
8677 CASE_BTC_ACT_STR(FREERUN);
8678 CASE_BTC_ACT_STR(BT_WHQL);
8679 CASE_BTC_ACT_STR(BT_RFK);
8680 CASE_BTC_ACT_STR(BT_OFF);
8681 CASE_BTC_ACT_STR(BT_IDLE);
8682 CASE_BTC_ACT_STR(BT_HFP);
8683 CASE_BTC_ACT_STR(BT_HID);
8684 CASE_BTC_ACT_STR(BT_A2DP);
8685 CASE_BTC_ACT_STR(BT_A2DPSINK);
8686 CASE_BTC_ACT_STR(BT_PAN);
8687 CASE_BTC_ACT_STR(BT_A2DP_HID);
8688 CASE_BTC_ACT_STR(BT_A2DP_PAN);
8689 CASE_BTC_ACT_STR(BT_PAN_HID);
8690 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID);
8691 CASE_BTC_ACT_STR(WL_25G_MCC);
8692 CASE_BTC_ACT_STR(WL_2G_MCC);
8693 CASE_BTC_ACT_STR(WL_2G_SCC);
8694 CASE_BTC_ACT_STR(WL_2G_AP);
8695 CASE_BTC_ACT_STR(WL_2G_GO);
8696 CASE_BTC_ACT_STR(WL_2G_GC);
8697 CASE_BTC_ACT_STR(WL_2G_NAN);
8698
8699 CASE_BTC_POLICY_STR(OFF_BT);
8700 CASE_BTC_POLICY_STR(OFF_WL);
8701 CASE_BTC_POLICY_STR(OFF_EQ0);
8702 CASE_BTC_POLICY_STR(OFF_EQ1);
8703 CASE_BTC_POLICY_STR(OFF_EQ2);
8704 CASE_BTC_POLICY_STR(OFF_EQ3);
8705 CASE_BTC_POLICY_STR(OFF_EQ4);
8706 CASE_BTC_POLICY_STR(OFF_EQ5);
8707 CASE_BTC_POLICY_STR(OFF_BWB0);
8708 CASE_BTC_POLICY_STR(OFF_BWB1);
8709 CASE_BTC_POLICY_STR(OFF_BWB2);
8710 CASE_BTC_POLICY_STR(OFF_BWB3);
8711 CASE_BTC_POLICY_STR(OFF_WL2);
8712 CASE_BTC_POLICY_STR(OFFB_BWB0);
8713 CASE_BTC_POLICY_STR(OFFE_DEF);
8714 CASE_BTC_POLICY_STR(OFFE_DEF2);
8715 CASE_BTC_POLICY_STR(OFFE_2GBWISOB);
8716 CASE_BTC_POLICY_STR(OFFE_2GISOB);
8717 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB);
8718 CASE_BTC_POLICY_STR(OFFE_WL);
8719 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2);
8720 CASE_BTC_POLICY_STR(FIX_TD3030);
8721 CASE_BTC_POLICY_STR(FIX_TD5050);
8722 CASE_BTC_POLICY_STR(FIX_TD2030);
8723 CASE_BTC_POLICY_STR(FIX_TD4010);
8724 CASE_BTC_POLICY_STR(FIX_TD7010);
8725 CASE_BTC_POLICY_STR(FIX_TD2060);
8726 CASE_BTC_POLICY_STR(FIX_TD3060);
8727 CASE_BTC_POLICY_STR(FIX_TD2080);
8728 CASE_BTC_POLICY_STR(FIX_TDW1B1);
8729 CASE_BTC_POLICY_STR(FIX_TD4010ISO);
8730 CASE_BTC_POLICY_STR(FIX_TD4010ISO_DL);
8731 CASE_BTC_POLICY_STR(FIX_TD4010ISO_UL);
8732 CASE_BTC_POLICY_STR(PFIX_TD3030);
8733 CASE_BTC_POLICY_STR(PFIX_TD5050);
8734 CASE_BTC_POLICY_STR(PFIX_TD2030);
8735 CASE_BTC_POLICY_STR(PFIX_TD2060);
8736 CASE_BTC_POLICY_STR(PFIX_TD3070);
8737 CASE_BTC_POLICY_STR(PFIX_TD2080);
8738 CASE_BTC_POLICY_STR(PFIX_TDW1B1);
8739 CASE_BTC_POLICY_STR(AUTO_TD50B1);
8740 CASE_BTC_POLICY_STR(AUTO_TD60B1);
8741 CASE_BTC_POLICY_STR(AUTO_TD20B1);
8742 CASE_BTC_POLICY_STR(AUTO_TDW1B1);
8743 CASE_BTC_POLICY_STR(PAUTO_TD50B1);
8744 CASE_BTC_POLICY_STR(PAUTO_TD60B1);
8745 CASE_BTC_POLICY_STR(PAUTO_TD20B1);
8746 CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
8747 CASE_BTC_POLICY_STR(AUTO2_TD3050);
8748 CASE_BTC_POLICY_STR(AUTO2_TD3070);
8749 CASE_BTC_POLICY_STR(AUTO2_TD5050);
8750 CASE_BTC_POLICY_STR(AUTO2_TD6060);
8751 CASE_BTC_POLICY_STR(AUTO2_TD2080);
8752 CASE_BTC_POLICY_STR(AUTO2_TDW1B4);
8753 CASE_BTC_POLICY_STR(PAUTO2_TD3050);
8754 CASE_BTC_POLICY_STR(PAUTO2_TD3070);
8755 CASE_BTC_POLICY_STR(PAUTO2_TD5050);
8756 CASE_BTC_POLICY_STR(PAUTO2_TD6060);
8757 CASE_BTC_POLICY_STR(PAUTO2_TD2080);
8758 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4);
8759 default:
8760 return "unknown step";
8761 }
8762 }
8763
id_to_slot(u32 id)8764 static const char *id_to_slot(u32 id)
8765 {
8766 switch (id) {
8767 CASE_BTC_SLOT_STR(OFF);
8768 CASE_BTC_SLOT_STR(B2W);
8769 CASE_BTC_SLOT_STR(W1);
8770 CASE_BTC_SLOT_STR(W2);
8771 CASE_BTC_SLOT_STR(W2B);
8772 CASE_BTC_SLOT_STR(B1);
8773 CASE_BTC_SLOT_STR(B2);
8774 CASE_BTC_SLOT_STR(B3);
8775 CASE_BTC_SLOT_STR(B4);
8776 CASE_BTC_SLOT_STR(LK);
8777 CASE_BTC_SLOT_STR(BLK);
8778 CASE_BTC_SLOT_STR(E2G);
8779 CASE_BTC_SLOT_STR(E5G);
8780 CASE_BTC_SLOT_STR(EBT);
8781 CASE_BTC_SLOT_STR(ENULL);
8782 CASE_BTC_SLOT_STR(WLK);
8783 CASE_BTC_SLOT_STR(W1FDD);
8784 CASE_BTC_SLOT_STR(B1FDD);
8785 default:
8786 return "unknown";
8787 }
8788 }
8789
id_to_evt(u32 id)8790 static const char *id_to_evt(u32 id)
8791 {
8792 switch (id) {
8793 CASE_BTC_EVT_STR(TDMA_ENTRY);
8794 CASE_BTC_EVT_STR(WL_TMR);
8795 CASE_BTC_EVT_STR(B1_TMR);
8796 CASE_BTC_EVT_STR(B2_TMR);
8797 CASE_BTC_EVT_STR(B3_TMR);
8798 CASE_BTC_EVT_STR(B4_TMR);
8799 CASE_BTC_EVT_STR(W2B_TMR);
8800 CASE_BTC_EVT_STR(B2W_TMR);
8801 CASE_BTC_EVT_STR(BCN_EARLY);
8802 CASE_BTC_EVT_STR(A2DP_EMPTY);
8803 CASE_BTC_EVT_STR(LK_END);
8804 CASE_BTC_EVT_STR(RX_ISR);
8805 CASE_BTC_EVT_STR(RX_FC0);
8806 CASE_BTC_EVT_STR(RX_FC1);
8807 CASE_BTC_EVT_STR(BT_RELINK);
8808 CASE_BTC_EVT_STR(BT_RETRY);
8809 CASE_BTC_EVT_STR(E2G);
8810 CASE_BTC_EVT_STR(E5G);
8811 CASE_BTC_EVT_STR(EBT);
8812 CASE_BTC_EVT_STR(ENULL);
8813 CASE_BTC_EVT_STR(DRV_WLK);
8814 CASE_BTC_EVT_STR(BCN_OK);
8815 CASE_BTC_EVT_STR(BT_CHANGE);
8816 CASE_BTC_EVT_STR(EBT_EXTEND);
8817 CASE_BTC_EVT_STR(E2G_NULL1);
8818 CASE_BTC_EVT_STR(B1FDD_TMR);
8819 default:
8820 return "unknown";
8821 }
8822 }
8823
id_to_mode(u8 id)8824 static const char *id_to_mode(u8 id)
8825 {
8826 switch (id) {
8827 CASE_BTC_INIT(NORMAL);
8828 CASE_BTC_INIT(WL);
8829 CASE_BTC_INIT(BT);
8830 CASE_BTC_INIT(WLOFF);
8831 default:
8832 return "unknown";
8833 }
8834 }
8835
id_to_ant(u32 id)8836 static const char *id_to_ant(u32 id)
8837 {
8838 switch (id) {
8839 CASE_BTC_ANTPATH_STR(WPOWERON);
8840 CASE_BTC_ANTPATH_STR(WINIT);
8841 CASE_BTC_ANTPATH_STR(WONLY);
8842 CASE_BTC_ANTPATH_STR(WOFF);
8843 CASE_BTC_ANTPATH_STR(W2G);
8844 CASE_BTC_ANTPATH_STR(W5G);
8845 CASE_BTC_ANTPATH_STR(W25G);
8846 CASE_BTC_ANTPATH_STR(FREERUN);
8847 CASE_BTC_ANTPATH_STR(WRFK);
8848 CASE_BTC_ANTPATH_STR(BRFK);
8849 CASE_BTC_ANTPATH_STR(MAX);
8850 default:
8851 return "unknown";
8852 }
8853 }
8854
8855 static
seq_print_segment(struct seq_file * m,const char * prefix,u16 * data,u8 len,u8 seg_len,u8 start_idx,u8 ring_len)8856 void seq_print_segment(struct seq_file *m, const char *prefix, u16 *data,
8857 u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
8858 {
8859 u8 i;
8860 u8 cur_index;
8861
8862 for (i = 0; i < len ; i++) {
8863 if ((i % seg_len) == 0)
8864 seq_printf(m, " %-15s : ", prefix);
8865 cur_index = (start_idx + i) % ring_len;
8866 if (i % 3 == 0)
8867 seq_printf(m, "-> %-20s",
8868 steps_to_str(*(data + cur_index)));
8869 else if (i % 3 == 1)
8870 seq_printf(m, "-> %-15s",
8871 steps_to_str(*(data + cur_index)));
8872 else
8873 seq_printf(m, "-> %-13s",
8874 steps_to_str(*(data + cur_index)));
8875 if (i == (len - 1) || (i % seg_len) == (seg_len - 1))
8876 seq_puts(m, "\n");
8877 }
8878 }
8879
_show_dm_step(struct rtw89_dev * rtwdev,struct seq_file * m)8880 static void _show_dm_step(struct rtw89_dev *rtwdev, struct seq_file *m)
8881 {
8882 struct rtw89_btc *btc = &rtwdev->btc;
8883 struct rtw89_btc_dm *dm = &btc->dm;
8884 u8 start_idx;
8885 u8 len;
8886
8887 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos;
8888 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0;
8889
8890 seq_print_segment(m, "[dm_steps]", dm->dm_step.step, len, 6, start_idx,
8891 ARRAY_SIZE(dm->dm_step.step));
8892 }
8893
_show_dm_info(struct rtw89_dev * rtwdev,struct seq_file * m)8894 static void _show_dm_info(struct rtw89_dev *rtwdev, struct seq_file *m)
8895 {
8896 struct rtw89_btc *btc = &rtwdev->btc;
8897 const struct rtw89_btc_ver *ver = btc->ver;
8898 struct rtw89_btc_dm *dm = &btc->dm;
8899 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8900 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
8901 u8 igno_bt;
8902
8903 if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
8904 return;
8905
8906 seq_printf(m, "========== [Mechanism Status %s] ==========\n",
8907 (btc->manual_ctrl ? "(Manual)" : "(Auto)"));
8908
8909 seq_printf(m,
8910 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, init_mode:%s, run_cnt:%d\n",
8911 "[status]",
8912 btc->ant_type == BTC_ANT_SHARED ? "shared" : "dedicated",
8913 steps_to_str(dm->run_reason),
8914 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT),
8915 id_to_ant(FIELD_GET(GENMASK(7, 0), dm->set_ant_path)),
8916 id_to_mode(wl->coex_mode),
8917 dm->cnt_dm[BTC_DCNT_RUN]);
8918
8919 _show_dm_step(rtwdev, m);
8920
8921 if (ver->fcxctrl == 7)
8922 igno_bt = btc->ctrl.ctrl_v7.igno_bt;
8923 else
8924 igno_bt = btc->ctrl.ctrl.igno_bt;
8925
8926 seq_printf(m, " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ",
8927 "[dm_flag]", dm->wl_only, dm->bt_only, igno_bt,
8928 dm->freerun, btc->lps, dm->wl_mimo_ps);
8929
8930 seq_printf(m, "leak_ap:%d, fw_offload:%s%s\n", dm->leak_ap,
8931 (BTC_CX_FW_OFFLOAD ? "Y" : "N"),
8932 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
8933 "" : "(Mismatch!!)"));
8934
8935 if (dm->rf_trx_para.wl_tx_power == 0xff)
8936 seq_printf(m,
8937 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ",
8938 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level);
8939
8940 else
8941 seq_printf(m,
8942 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ",
8943 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level,
8944 dm->rf_trx_para.wl_tx_power);
8945
8946 seq_printf(m,
8947 "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n",
8948 dm->rf_trx_para.wl_rx_gain, dm->rf_trx_para.bt_tx_power,
8949 dm->rf_trx_para.bt_rx_gain,
8950 (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx);
8951
8952 seq_printf(m,
8953 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n",
8954 "[dm_ctrl]", dm->wl_tx_limit.enable, dm->wl_tx_limit.tx_time,
8955 dm->wl_tx_limit.tx_retry, btc->bt_req_len, bt->scan_rx_low_pri);
8956 }
8957
_show_error(struct rtw89_dev * rtwdev,struct seq_file * m)8958 static void _show_error(struct rtw89_dev *rtwdev, struct seq_file *m)
8959 {
8960 struct rtw89_btc *btc = &rtwdev->btc;
8961 const struct rtw89_btc_ver *ver = btc->ver;
8962 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
8963 union rtw89_btc_fbtc_cysta_info *pcysta;
8964 u32 except_cnt, exception_map;
8965
8966 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
8967 if (ver->fcxcysta == 2) {
8968 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
8969 except_cnt = le32_to_cpu(pcysta->v2.except_cnt);
8970 exception_map = le32_to_cpu(pcysta->v2.exception);
8971 } else if (ver->fcxcysta == 3) {
8972 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
8973 except_cnt = le32_to_cpu(pcysta->v3.except_cnt);
8974 exception_map = le32_to_cpu(pcysta->v3.except_map);
8975 } else if (ver->fcxcysta == 4) {
8976 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
8977 except_cnt = pcysta->v4.except_cnt;
8978 exception_map = le32_to_cpu(pcysta->v4.except_map);
8979 } else if (ver->fcxcysta == 5) {
8980 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
8981 except_cnt = pcysta->v5.except_cnt;
8982 exception_map = le32_to_cpu(pcysta->v5.except_map);
8983 } else if (ver->fcxcysta == 7) {
8984 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
8985 except_cnt = pcysta->v7.except_cnt;
8986 exception_map = le32_to_cpu(pcysta->v7.except_map);
8987 } else {
8988 return;
8989 }
8990
8991 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 &&
8992 !pfwinfo->len_mismch && !pfwinfo->fver_mismch)
8993 return;
8994
8995 seq_printf(m, " %-15s : ", "[error]");
8996
8997 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
8998 seq_printf(m,
8999 "overflow-cnt: %d, ",
9000 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
9001 }
9002
9003 if (pfwinfo->len_mismch) {
9004 seq_printf(m,
9005 "len-mismatch: 0x%x, ",
9006 pfwinfo->len_mismch);
9007 }
9008
9009 if (pfwinfo->fver_mismch) {
9010 seq_printf(m,
9011 "fver-mismatch: 0x%x, ",
9012 pfwinfo->fver_mismch);
9013 }
9014
9015 /* cycle statistics exceptions */
9016 if (exception_map || except_cnt) {
9017 seq_printf(m,
9018 "exception-type: 0x%x, exception-cnt = %d",
9019 exception_map, except_cnt);
9020 }
9021 seq_puts(m, "\n");
9022 }
9023
_show_fbtc_tdma(struct rtw89_dev * rtwdev,struct seq_file * m)9024 static void _show_fbtc_tdma(struct rtw89_dev *rtwdev, struct seq_file *m)
9025 {
9026 struct rtw89_btc *btc = &rtwdev->btc;
9027 const struct rtw89_btc_ver *ver = btc->ver;
9028 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9029 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9030 struct rtw89_btc_fbtc_tdma *t = NULL;
9031
9032 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
9033 if (!pcinfo->valid)
9034 return;
9035
9036 if (ver->fcxtdma == 1)
9037 t = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
9038 else
9039 t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma;
9040
9041 seq_printf(m,
9042 " %-15s : ", "[tdma_policy]");
9043 seq_printf(m,
9044 "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ",
9045 (u32)t->type,
9046 t->rxflctrl, t->txpause);
9047
9048 seq_printf(m,
9049 "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ",
9050 t->wtgle_n, t->leak_n, t->ext_ctrl);
9051
9052 seq_printf(m,
9053 "policy_type:%d",
9054 (u32)btc->policy_type);
9055
9056 seq_puts(m, "\n");
9057 }
9058
_show_fbtc_slots(struct rtw89_dev * rtwdev,struct seq_file * m)9059 static void _show_fbtc_slots(struct rtw89_dev *rtwdev, struct seq_file *m)
9060 {
9061 struct rtw89_btc *btc = &rtwdev->btc;
9062 struct rtw89_btc_dm *dm = &btc->dm;
9063 u16 dur, cxtype;
9064 u32 tbl;
9065 u8 i = 0;
9066
9067 for (i = 0; i < CXST_MAX; i++) {
9068 if (btc->ver->fcxslots == 1) {
9069 dur = le16_to_cpu(dm->slot_now.v1[i].dur);
9070 tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl);
9071 cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype);
9072 } else if (btc->ver->fcxslots == 7) {
9073 dur = le16_to_cpu(dm->slot_now.v7[i].dur);
9074 tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl);
9075 cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype);
9076 } else {
9077 return;
9078 }
9079
9080 if (i % 5 == 0)
9081 seq_printf(m,
9082 " %-15s : %5s[%03d/0x%x/%d]",
9083 "[slot_list]",
9084 id_to_slot((u32)i),
9085 dur, tbl, cxtype);
9086 else
9087 seq_printf(m,
9088 ", %5s[%03d/0x%x/%d]",
9089 id_to_slot((u32)i),
9090 dur, tbl, cxtype);
9091
9092 if (i % 5 == 4)
9093 seq_puts(m, "\n");
9094 }
9095 seq_puts(m, "\n");
9096 }
9097
_show_fbtc_cysta_v2(struct rtw89_dev * rtwdev,struct seq_file * m)9098 static void _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, struct seq_file *m)
9099 {
9100 struct rtw89_btc *btc = &rtwdev->btc;
9101 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9102 struct rtw89_btc_dm *dm = &btc->dm;
9103 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
9104 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9105 struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL;
9106 union rtw89_btc_fbtc_rxflct r;
9107 u8 i, cnt = 0, slot_pair;
9108 u16 cycle, c_begin, c_end, store_index;
9109
9110 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9111 if (!pcinfo->valid)
9112 return;
9113
9114 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
9115 seq_printf(m,
9116 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
9117 "[cycle_cnt]",
9118 le16_to_cpu(pcysta_le32->cycles),
9119 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]),
9120 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]),
9121 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]),
9122 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK]));
9123
9124 for (i = 0; i < CXST_MAX; i++) {
9125 if (!le32_to_cpu(pcysta_le32->slot_cnt[i]))
9126 continue;
9127 seq_printf(m, ", %s:%d", id_to_slot((u32)i),
9128 le32_to_cpu(pcysta_le32->slot_cnt[i]));
9129 }
9130
9131 if (dm->tdma_now.rxflctrl) {
9132 seq_printf(m, ", leak_rx:%d",
9133 le32_to_cpu(pcysta_le32->leakrx_cnt));
9134 }
9135
9136 if (le32_to_cpu(pcysta_le32->collision_cnt)) {
9137 seq_printf(m, ", collision:%d",
9138 le32_to_cpu(pcysta_le32->collision_cnt));
9139 }
9140
9141 if (le32_to_cpu(pcysta_le32->skip_cnt)) {
9142 seq_printf(m, ", skip:%d",
9143 le32_to_cpu(pcysta_le32->skip_cnt));
9144 }
9145 seq_puts(m, "\n");
9146
9147 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9148 "[cycle_time]",
9149 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]),
9150 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]),
9151 le16_to_cpu(pcysta_le32->tavg_lk) / 1000,
9152 le16_to_cpu(pcysta_le32->tavg_lk) % 1000);
9153 seq_printf(m, ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
9154 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]),
9155 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]),
9156 le16_to_cpu(pcysta_le32->tmax_lk) / 1000,
9157 le16_to_cpu(pcysta_le32->tmax_lk) % 1000);
9158 seq_printf(m, ", maxdiff_t[wl:%d/bt:%d]\n",
9159 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]),
9160 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT]));
9161
9162 if (le16_to_cpu(pcysta_le32->cycles) <= 1)
9163 return;
9164
9165 /* 1 cycle record 1 wl-slot and 1 bt-slot */
9166 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
9167
9168 if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair)
9169 c_begin = 1;
9170 else
9171 c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1;
9172
9173 c_end = le16_to_cpu(pcysta_le32->cycles);
9174
9175 for (cycle = c_begin; cycle <= c_end; cycle++) {
9176 cnt++;
9177 store_index = ((cycle - 1) % slot_pair) * 2;
9178
9179 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1)
9180 seq_printf(m,
9181 " %-15s : ->b%02d->w%02d", "[cycle_step]",
9182 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
9183 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
9184 else
9185 seq_printf(m,
9186 "->b%02d->w%02d",
9187 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
9188 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
9189 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
9190 seq_puts(m, "\n");
9191 }
9192
9193 if (a2dp->exist) {
9194 seq_printf(m,
9195 " %-15s : a2dp_ept:%d, a2dp_late:%d",
9196 "[a2dp_t_sta]",
9197 le16_to_cpu(pcysta_le32->a2dpept),
9198 le16_to_cpu(pcysta_le32->a2dpeptto));
9199
9200 seq_printf(m,
9201 ", avg_t:%d, max_t:%d",
9202 le16_to_cpu(pcysta_le32->tavg_a2dpept),
9203 le16_to_cpu(pcysta_le32->tmax_a2dpept));
9204 r.val = dm->tdma_now.rxflctrl;
9205
9206 if (r.type && r.tgln_n) {
9207 seq_printf(m,
9208 ", cycle[PSTDMA:%d/TDMA:%d], ",
9209 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]),
9210 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF]));
9211
9212 seq_printf(m,
9213 "avg_t[PSTDMA:%d/TDMA:%d], ",
9214 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]),
9215 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF]));
9216
9217 seq_printf(m,
9218 "max_t[PSTDMA:%d/TDMA:%d]",
9219 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]),
9220 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF]));
9221 }
9222 seq_puts(m, "\n");
9223 }
9224 }
9225
_show_fbtc_cysta_v3(struct rtw89_dev * rtwdev,struct seq_file * m)9226 static void _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, struct seq_file *m)
9227 {
9228 struct rtw89_btc *btc = &rtwdev->btc;
9229 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
9230 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9231 struct rtw89_btc_dm *dm = &btc->dm;
9232 struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx;
9233 struct rtw89_btc_fbtc_cysta_v3 *pcysta;
9234 struct rtw89_btc_rpt_cmn_info *pcinfo;
9235 u8 i, cnt = 0, slot_pair, divide_cnt;
9236 u16 cycle, c_begin, c_end, store_index;
9237
9238 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9239 if (!pcinfo->valid)
9240 return;
9241
9242 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
9243 seq_printf(m,
9244 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
9245 "[cycle_cnt]",
9246 le16_to_cpu(pcysta->cycles),
9247 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
9248 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
9249 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
9250 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
9251
9252 for (i = 0; i < CXST_MAX; i++) {
9253 if (!le32_to_cpu(pcysta->slot_cnt[i]))
9254 continue;
9255
9256 seq_printf(m, ", %s:%d", id_to_slot(i),
9257 le32_to_cpu(pcysta->slot_cnt[i]));
9258 }
9259
9260 if (dm->tdma_now.rxflctrl)
9261 seq_printf(m, ", leak_rx:%d", le32_to_cpu(pcysta->leak_slot.cnt_rximr));
9262
9263 if (le32_to_cpu(pcysta->collision_cnt))
9264 seq_printf(m, ", collision:%d", le32_to_cpu(pcysta->collision_cnt));
9265
9266 if (le32_to_cpu(pcysta->skip_cnt))
9267 seq_printf(m, ", skip:%d", le32_to_cpu(pcysta->skip_cnt));
9268
9269 seq_puts(m, "\n");
9270
9271 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9272 "[cycle_time]",
9273 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
9274 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
9275 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
9276 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
9277 seq_printf(m,
9278 ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
9279 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
9280 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
9281 le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
9282 le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
9283 seq_printf(m,
9284 ", maxdiff_t[wl:%d/bt:%d]\n",
9285 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
9286 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
9287
9288 cycle = le16_to_cpu(pcysta->cycles);
9289 if (cycle <= 1)
9290 return;
9291
9292 /* 1 cycle record 1 wl-slot and 1 bt-slot */
9293 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
9294
9295 if (cycle <= slot_pair)
9296 c_begin = 1;
9297 else
9298 c_begin = cycle - slot_pair + 1;
9299
9300 c_end = cycle;
9301
9302 if (a2dp->exist)
9303 divide_cnt = 3;
9304 else
9305 divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
9306
9307 for (cycle = c_begin; cycle <= c_end; cycle++) {
9308 cnt++;
9309 store_index = ((cycle - 1) % slot_pair) * 2;
9310
9311 if (cnt % divide_cnt == 1)
9312 seq_printf(m, " %-15s : ", "[cycle_step]");
9313
9314 seq_printf(m, "->b%02d",
9315 le16_to_cpu(pcysta->slot_step_time[store_index]));
9316 if (a2dp->exist) {
9317 a2dp_trx = &pcysta->a2dp_trx[store_index];
9318 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
9319 a2dp_trx->empty_cnt,
9320 a2dp_trx->retry_cnt,
9321 a2dp_trx->tx_rate ? 3 : 2,
9322 a2dp_trx->tx_cnt,
9323 a2dp_trx->ack_cnt,
9324 a2dp_trx->nack_cnt);
9325 }
9326 seq_printf(m, "->w%02d",
9327 le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
9328 if (a2dp->exist) {
9329 a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
9330 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
9331 a2dp_trx->empty_cnt,
9332 a2dp_trx->retry_cnt,
9333 a2dp_trx->tx_rate ? 3 : 2,
9334 a2dp_trx->tx_cnt,
9335 a2dp_trx->ack_cnt,
9336 a2dp_trx->nack_cnt);
9337 }
9338 if (cnt % divide_cnt == 0 || cnt == c_end)
9339 seq_puts(m, "\n");
9340 }
9341
9342 if (a2dp->exist) {
9343 seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d",
9344 "[a2dp_t_sta]",
9345 le16_to_cpu(pcysta->a2dp_ept.cnt),
9346 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
9347
9348 seq_printf(m, ", avg_t:%d, max_t:%d",
9349 le16_to_cpu(pcysta->a2dp_ept.tavg),
9350 le16_to_cpu(pcysta->a2dp_ept.tmax));
9351
9352 seq_puts(m, "\n");
9353 }
9354 }
9355
_show_fbtc_cysta_v4(struct rtw89_dev * rtwdev,struct seq_file * m)9356 static void _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, struct seq_file *m)
9357 {
9358 struct rtw89_btc *btc = &rtwdev->btc;
9359 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
9360 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9361 struct rtw89_btc_dm *dm = &btc->dm;
9362 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
9363 struct rtw89_btc_fbtc_cysta_v4 *pcysta;
9364 struct rtw89_btc_rpt_cmn_info *pcinfo;
9365 u8 i, cnt = 0, slot_pair, divide_cnt;
9366 u16 cycle, c_begin, c_end, store_index;
9367
9368 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9369 if (!pcinfo->valid)
9370 return;
9371
9372 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
9373 seq_printf(m,
9374 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
9375 "[cycle_cnt]",
9376 le16_to_cpu(pcysta->cycles),
9377 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
9378 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
9379 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
9380 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
9381
9382 for (i = 0; i < CXST_MAX; i++) {
9383 if (!le16_to_cpu(pcysta->slot_cnt[i]))
9384 continue;
9385
9386 seq_printf(m, ", %s:%d", id_to_slot(i),
9387 le16_to_cpu(pcysta->slot_cnt[i]));
9388 }
9389
9390 if (dm->tdma_now.rxflctrl)
9391 seq_printf(m, ", leak_rx:%d",
9392 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
9393
9394 if (pcysta->collision_cnt)
9395 seq_printf(m, ", collision:%d", pcysta->collision_cnt);
9396
9397 if (le16_to_cpu(pcysta->skip_cnt))
9398 seq_printf(m, ", skip:%d",
9399 le16_to_cpu(pcysta->skip_cnt));
9400
9401 seq_puts(m, "\n");
9402
9403 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9404 "[cycle_time]",
9405 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
9406 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
9407 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
9408 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
9409 seq_printf(m,
9410 ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
9411 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
9412 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
9413 le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
9414 le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
9415 seq_printf(m,
9416 ", maxdiff_t[wl:%d/bt:%d]\n",
9417 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
9418 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
9419
9420 cycle = le16_to_cpu(pcysta->cycles);
9421 if (cycle <= 1)
9422 return;
9423
9424 /* 1 cycle record 1 wl-slot and 1 bt-slot */
9425 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
9426
9427 if (cycle <= slot_pair)
9428 c_begin = 1;
9429 else
9430 c_begin = cycle - slot_pair + 1;
9431
9432 c_end = cycle;
9433
9434 if (a2dp->exist)
9435 divide_cnt = 3;
9436 else
9437 divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
9438
9439 for (cycle = c_begin; cycle <= c_end; cycle++) {
9440 cnt++;
9441 store_index = ((cycle - 1) % slot_pair) * 2;
9442
9443 if (cnt % divide_cnt == 1)
9444 seq_printf(m, " %-15s : ", "[cycle_step]");
9445
9446 seq_printf(m, "->b%02d",
9447 le16_to_cpu(pcysta->slot_step_time[store_index]));
9448 if (a2dp->exist) {
9449 a2dp_trx = &pcysta->a2dp_trx[store_index];
9450 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
9451 a2dp_trx->empty_cnt,
9452 a2dp_trx->retry_cnt,
9453 a2dp_trx->tx_rate ? 3 : 2,
9454 a2dp_trx->tx_cnt,
9455 a2dp_trx->ack_cnt,
9456 a2dp_trx->nack_cnt);
9457 }
9458 seq_printf(m, "->w%02d",
9459 le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
9460 if (a2dp->exist) {
9461 a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
9462 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
9463 a2dp_trx->empty_cnt,
9464 a2dp_trx->retry_cnt,
9465 a2dp_trx->tx_rate ? 3 : 2,
9466 a2dp_trx->tx_cnt,
9467 a2dp_trx->ack_cnt,
9468 a2dp_trx->nack_cnt);
9469 }
9470 if (cnt % divide_cnt == 0 || cnt == c_end)
9471 seq_puts(m, "\n");
9472 }
9473
9474 if (a2dp->exist) {
9475 seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d",
9476 "[a2dp_t_sta]",
9477 le16_to_cpu(pcysta->a2dp_ept.cnt),
9478 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
9479
9480 seq_printf(m, ", avg_t:%d, max_t:%d",
9481 le16_to_cpu(pcysta->a2dp_ept.tavg),
9482 le16_to_cpu(pcysta->a2dp_ept.tmax));
9483
9484 seq_puts(m, "\n");
9485 }
9486 }
9487
_show_fbtc_cysta_v5(struct rtw89_dev * rtwdev,struct seq_file * m)9488 static void _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, struct seq_file *m)
9489 {
9490 struct rtw89_btc *btc = &rtwdev->btc;
9491 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
9492 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9493 struct rtw89_btc_dm *dm = &btc->dm;
9494 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
9495 struct rtw89_btc_fbtc_cysta_v5 *pcysta;
9496 struct rtw89_btc_rpt_cmn_info *pcinfo;
9497 u8 i, cnt = 0, slot_pair, divide_cnt;
9498 u16 cycle, c_begin, c_end, store_index;
9499
9500 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9501 if (!pcinfo->valid)
9502 return;
9503
9504 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
9505 seq_printf(m,
9506 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
9507 "[cycle_cnt]",
9508 le16_to_cpu(pcysta->cycles),
9509 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
9510 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
9511 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
9512 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
9513
9514 for (i = 0; i < CXST_MAX; i++) {
9515 if (!le16_to_cpu(pcysta->slot_cnt[i]))
9516 continue;
9517
9518 seq_printf(m, ", %s:%d", id_to_slot(i),
9519 le16_to_cpu(pcysta->slot_cnt[i]));
9520 }
9521
9522 if (dm->tdma_now.rxflctrl)
9523 seq_printf(m, ", leak_rx:%d",
9524 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
9525
9526 if (pcysta->collision_cnt)
9527 seq_printf(m, ", collision:%d", pcysta->collision_cnt);
9528
9529 if (le16_to_cpu(pcysta->skip_cnt))
9530 seq_printf(m, ", skip:%d",
9531 le16_to_cpu(pcysta->skip_cnt));
9532
9533 seq_puts(m, "\n");
9534
9535 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9536 "[cycle_time]",
9537 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
9538 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
9539 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
9540 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
9541 seq_printf(m,
9542 ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n",
9543 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
9544 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
9545 le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
9546 le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
9547
9548 cycle = le16_to_cpu(pcysta->cycles);
9549 if (cycle <= 1)
9550 return;
9551
9552 /* 1 cycle record 1 wl-slot and 1 bt-slot */
9553 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
9554
9555 if (cycle <= slot_pair)
9556 c_begin = 1;
9557 else
9558 c_begin = cycle - slot_pair + 1;
9559
9560 c_end = cycle;
9561
9562 if (a2dp->exist)
9563 divide_cnt = 3;
9564 else
9565 divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
9566
9567 if (c_begin > c_end)
9568 return;
9569
9570 for (cycle = c_begin; cycle <= c_end; cycle++) {
9571 cnt++;
9572 store_index = ((cycle - 1) % slot_pair) * 2;
9573
9574 if (cnt % divide_cnt == 1)
9575 seq_printf(m, " %-15s : ", "[cycle_step]");
9576
9577 seq_printf(m, "->b%02d",
9578 le16_to_cpu(pcysta->slot_step_time[store_index]));
9579 if (a2dp->exist) {
9580 a2dp_trx = &pcysta->a2dp_trx[store_index];
9581 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
9582 a2dp_trx->empty_cnt,
9583 a2dp_trx->retry_cnt,
9584 a2dp_trx->tx_rate ? 3 : 2,
9585 a2dp_trx->tx_cnt,
9586 a2dp_trx->ack_cnt,
9587 a2dp_trx->nack_cnt);
9588 }
9589 seq_printf(m, "->w%02d",
9590 le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
9591 if (a2dp->exist) {
9592 a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
9593 seq_printf(m, "(%d/%d/%dM/%d/%d/%d)",
9594 a2dp_trx->empty_cnt,
9595 a2dp_trx->retry_cnt,
9596 a2dp_trx->tx_rate ? 3 : 2,
9597 a2dp_trx->tx_cnt,
9598 a2dp_trx->ack_cnt,
9599 a2dp_trx->nack_cnt);
9600 }
9601 if (cnt % divide_cnt == 0 || cnt == c_end)
9602 seq_puts(m, "\n");
9603 }
9604
9605 if (a2dp->exist) {
9606 seq_printf(m, " %-15s : a2dp_ept:%d, a2dp_late:%d",
9607 "[a2dp_t_sta]",
9608 le16_to_cpu(pcysta->a2dp_ept.cnt),
9609 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
9610
9611 seq_printf(m, ", avg_t:%d, max_t:%d",
9612 le16_to_cpu(pcysta->a2dp_ept.tavg),
9613 le16_to_cpu(pcysta->a2dp_ept.tmax));
9614
9615 seq_puts(m, "\n");
9616 }
9617 }
9618
_show_fbtc_cysta_v7(struct rtw89_dev * rtwdev,struct seq_file * m)9619 static void _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, struct seq_file *m)
9620 {
9621 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt;
9622 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc;
9623 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
9624 struct rtw89_btc_fbtc_cysta_v7 *pcysta = NULL;
9625 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
9626 struct rtw89_btc_rpt_cmn_info *pcinfo;
9627 u16 cycle, c_begin, c_end, s_id;
9628 u8 i, cnt = 0, divide_cnt;
9629 u8 slot_pair;
9630
9631 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9632 if (!pcinfo->valid)
9633 return;
9634
9635 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
9636 seq_printf(m, "\n\r %-15s : cycle:%d", "[slot_stat]",
9637 le16_to_cpu(pcysta->cycles));
9638
9639 for (i = 0; i < CXST_MAX; i++) {
9640 if (!le16_to_cpu(pcysta->slot_cnt[i]))
9641 continue;
9642 seq_printf(m, ", %s:%d",
9643 id_to_slot(i), le16_to_cpu(pcysta->slot_cnt[i]));
9644 }
9645
9646 if (dm->tdma_now.rxflctrl)
9647 seq_printf(m, ", leak_rx:%d",
9648 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
9649
9650 if (pcysta->collision_cnt)
9651 seq_printf(m, ", collision:%d", pcysta->collision_cnt);
9652
9653 if (pcysta->skip_cnt)
9654 seq_printf(m, ", skip:%d", le16_to_cpu(pcysta->skip_cnt));
9655
9656 seq_printf(m, "\n\r %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9657 "[cycle_stat]",
9658 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
9659 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
9660 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
9661 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
9662 seq_printf(m, ", max_t[wl:%d/bt:%d(>%dms:%d)/lk:%d.%03d]",
9663 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
9664 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
9665 dm->bt_slot_flood, dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD],
9666 le16_to_cpu(pcysta->leak_slot.tamx) / 1000,
9667 le16_to_cpu(pcysta->leak_slot.tamx) % 1000);
9668 seq_printf(m, ", bcn[all:%d/ok:%d/in_bt:%d/in_bt_ok:%d]",
9669 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
9670 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
9671 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
9672 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
9673
9674 if (a2dp->exist) {
9675 seq_printf(m,
9676 "\n\r %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)",
9677 "[a2dp_stat]",
9678 le16_to_cpu(pcysta->a2dp_ept.cnt),
9679 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout),
9680 a2dp->no_empty_streak_2s, a2dp->no_empty_streak_max);
9681
9682 seq_printf(m, ", avg_t:%d, max_t:%d",
9683 le16_to_cpu(pcysta->a2dp_ept.tavg),
9684 le16_to_cpu(pcysta->a2dp_ept.tmax));
9685 }
9686
9687 if (le16_to_cpu(pcysta->cycles) <= 1)
9688 return;
9689
9690 /* 1 cycle = 1 wl-slot + 1 bt-slot */
9691 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
9692
9693 if (le16_to_cpu(pcysta->cycles) <= slot_pair)
9694 c_begin = 1;
9695 else
9696 c_begin = le16_to_cpu(pcysta->cycles) - slot_pair + 1;
9697
9698 c_end = le16_to_cpu(pcysta->cycles);
9699
9700 if (a2dp->exist)
9701 divide_cnt = 2;
9702 else
9703 divide_cnt = 6;
9704
9705 if (c_begin > c_end)
9706 return;
9707
9708 for (cycle = c_begin; cycle <= c_end; cycle++) {
9709 cnt++;
9710 s_id = ((cycle - 1) % slot_pair) * 2;
9711
9712 if (cnt % divide_cnt == 1) {
9713 if (a2dp->exist)
9714 seq_printf(m, "\n\r %-15s : ", "[slotT_wermtan]");
9715 else
9716 seq_printf(m, "\n\r %-15s : ", "[slotT_rxerr]");
9717 }
9718
9719 seq_printf(m, "->b%d", le16_to_cpu(pcysta->slot_step_time[s_id]));
9720
9721 if (a2dp->exist)
9722 seq_printf(m, "(%d/%d/%d/%dM/%d/%d/%d)",
9723 pcysta->wl_rx_err_ratio[s_id],
9724 pcysta->a2dp_trx[s_id].empty_cnt,
9725 pcysta->a2dp_trx[s_id].retry_cnt,
9726 (pcysta->a2dp_trx[s_id].tx_rate ? 3 : 2),
9727 pcysta->a2dp_trx[s_id].tx_cnt,
9728 pcysta->a2dp_trx[s_id].ack_cnt,
9729 pcysta->a2dp_trx[s_id].nack_cnt);
9730 else
9731 seq_printf(m, "(%d)", pcysta->wl_rx_err_ratio[s_id]);
9732
9733 seq_printf(m, "->w%d", le16_to_cpu(pcysta->slot_step_time[s_id + 1]));
9734
9735 if (a2dp->exist)
9736 seq_printf(m, "(%d/%d/%d/%dM/%d/%d/%d)",
9737 pcysta->wl_rx_err_ratio[s_id + 1],
9738 pcysta->a2dp_trx[s_id + 1].empty_cnt,
9739 pcysta->a2dp_trx[s_id + 1].retry_cnt,
9740 (pcysta->a2dp_trx[s_id + 1].tx_rate ? 3 : 2),
9741 pcysta->a2dp_trx[s_id + 1].tx_cnt,
9742 pcysta->a2dp_trx[s_id + 1].ack_cnt,
9743 pcysta->a2dp_trx[s_id + 1].nack_cnt);
9744 else
9745 seq_printf(m, "(%d)", pcysta->wl_rx_err_ratio[s_id + 1]);
9746 }
9747 }
9748
_show_fbtc_nullsta(struct rtw89_dev * rtwdev,struct seq_file * m)9749 static void _show_fbtc_nullsta(struct rtw89_dev *rtwdev, struct seq_file *m)
9750 {
9751 struct rtw89_btc *btc = &rtwdev->btc;
9752 const struct rtw89_btc_ver *ver = btc->ver;
9753 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9754 struct rtw89_btc_rpt_cmn_info *pcinfo;
9755 union rtw89_btc_fbtc_cynullsta_info *ns;
9756 u8 i = 0;
9757
9758 if (!btc->dm.tdma_now.rxflctrl)
9759 return;
9760
9761 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
9762 if (!pcinfo->valid)
9763 return;
9764
9765 ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
9766 if (ver->fcxnullsta == 1) {
9767 for (i = 0; i < 2; i++) {
9768 seq_printf(m, " %-15s : ", "[NULL-STA]");
9769 seq_printf(m, "null-%d", i);
9770 seq_printf(m, "[ok:%d/",
9771 le32_to_cpu(ns->v1.result[i][1]));
9772 seq_printf(m, "fail:%d/",
9773 le32_to_cpu(ns->v1.result[i][0]));
9774 seq_printf(m, "on_time:%d/",
9775 le32_to_cpu(ns->v1.result[i][2]));
9776 seq_printf(m, "retry:%d/",
9777 le32_to_cpu(ns->v1.result[i][3]));
9778 seq_printf(m, "avg_t:%d.%03d/",
9779 le32_to_cpu(ns->v1.avg_t[i]) / 1000,
9780 le32_to_cpu(ns->v1.avg_t[i]) % 1000);
9781 seq_printf(m, "max_t:%d.%03d]\n",
9782 le32_to_cpu(ns->v1.max_t[i]) / 1000,
9783 le32_to_cpu(ns->v1.max_t[i]) % 1000);
9784 }
9785 } else if (ver->fcxnullsta == 7) {
9786 for (i = 0; i < 2; i++) {
9787 seq_printf(m, " %-15s : ", "[NULL-STA]");
9788 seq_printf(m, "null-%d", i);
9789 seq_printf(m, "[Tx:%d/",
9790 le32_to_cpu(ns->v7.result[i][4]));
9791 seq_printf(m, "[ok:%d/",
9792 le32_to_cpu(ns->v7.result[i][1]));
9793 seq_printf(m, "fail:%d/",
9794 le32_to_cpu(ns->v7.result[i][0]));
9795 seq_printf(m, "on_time:%d/",
9796 le32_to_cpu(ns->v7.result[i][2]));
9797 seq_printf(m, "retry:%d/",
9798 le32_to_cpu(ns->v7.result[i][3]));
9799 seq_printf(m, "avg_t:%d.%03d/",
9800 le32_to_cpu(ns->v7.tavg[i]) / 1000,
9801 le32_to_cpu(ns->v7.tavg[i]) % 1000);
9802 seq_printf(m, "max_t:%d.%03d]\n",
9803 le32_to_cpu(ns->v7.tmax[i]) / 1000,
9804 le32_to_cpu(ns->v7.tmax[i]) % 1000);
9805 }
9806 } else {
9807 for (i = 0; i < 2; i++) {
9808 seq_printf(m, " %-15s : ", "[NULL-STA]");
9809 seq_printf(m, "null-%d", i);
9810 seq_printf(m, "[Tx:%d/",
9811 le32_to_cpu(ns->v2.result[i][4]));
9812 seq_printf(m, "[ok:%d/",
9813 le32_to_cpu(ns->v2.result[i][1]));
9814 seq_printf(m, "fail:%d/",
9815 le32_to_cpu(ns->v2.result[i][0]));
9816 seq_printf(m, "on_time:%d/",
9817 le32_to_cpu(ns->v2.result[i][2]));
9818 seq_printf(m, "retry:%d/",
9819 le32_to_cpu(ns->v2.result[i][3]));
9820 seq_printf(m, "avg_t:%d.%03d/",
9821 le32_to_cpu(ns->v2.avg_t[i]) / 1000,
9822 le32_to_cpu(ns->v2.avg_t[i]) % 1000);
9823 seq_printf(m, "max_t:%d.%03d]\n",
9824 le32_to_cpu(ns->v2.max_t[i]) / 1000,
9825 le32_to_cpu(ns->v2.max_t[i]) % 1000);
9826 }
9827 }
9828 }
9829
_show_fbtc_step_v2(struct rtw89_dev * rtwdev,struct seq_file * m)9830 static void _show_fbtc_step_v2(struct rtw89_dev *rtwdev, struct seq_file *m)
9831 {
9832 struct rtw89_btc *btc = &rtwdev->btc;
9833 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9834 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9835 struct rtw89_btc_fbtc_steps_v2 *pstep = NULL;
9836 const struct rtw89_btc_ver *ver = btc->ver;
9837 u8 type, val, cnt = 0, state = 0;
9838 bool outloop = false;
9839 u16 i, diff_t, n_start = 0, n_stop = 0;
9840 u16 pos_old, pos_new, trace_step;
9841
9842 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
9843 if (!pcinfo->valid)
9844 return;
9845
9846 pstep = &pfwinfo->rpt_fbtc_step.finfo.v2;
9847 pos_old = le16_to_cpu(pstep->pos_old);
9848 pos_new = le16_to_cpu(pstep->pos_new);
9849
9850 if (pcinfo->req_fver != pstep->fver)
9851 return;
9852
9853 /* store step info by using ring instead of FIFO*/
9854 do {
9855 switch (state) {
9856 case 0:
9857 if (ver->fcxctrl == 7 || ver->fcxctrl == 1)
9858 trace_step = 50;
9859 else
9860 trace_step = btc->ctrl.ctrl.trace_step;
9861
9862 n_start = pos_old;
9863 if (pos_new >= pos_old)
9864 n_stop = pos_new;
9865 else
9866 n_stop = trace_step - 1;
9867
9868 state = 1;
9869 break;
9870 case 1:
9871 for (i = n_start; i <= n_stop; i++) {
9872 type = pstep->step[i].type;
9873 val = pstep->step[i].val;
9874 diff_t = le16_to_cpu(pstep->step[i].difft);
9875
9876 if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
9877 continue;
9878
9879 if (cnt % 10 == 0)
9880 seq_printf(m, " %-15s : ", "[steps]");
9881
9882 seq_printf(m, "-> %s(%02d)(%02d)",
9883 (type == CXSTEP_SLOT ? "SLT" :
9884 "EVT"), (u32)val, diff_t);
9885 if (cnt % 10 == 9)
9886 seq_puts(m, "\n");
9887 cnt++;
9888 }
9889
9890 state = 2;
9891 break;
9892 case 2:
9893 if (pos_new < pos_old && n_start != 0) {
9894 n_start = 0;
9895 n_stop = pos_new;
9896 state = 1;
9897 } else {
9898 outloop = true;
9899 }
9900 break;
9901 }
9902 } while (!outloop);
9903 }
9904
_show_fbtc_step_v3(struct rtw89_dev * rtwdev,struct seq_file * m)9905 static void _show_fbtc_step_v3(struct rtw89_dev *rtwdev, struct seq_file *m)
9906 {
9907 struct rtw89_btc *btc = &rtwdev->btc;
9908 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9909 struct rtw89_btc_rpt_cmn_info *pcinfo;
9910 struct rtw89_btc_fbtc_steps_v3 *pstep;
9911 u32 i, n_begin, n_end, array_idx, cnt = 0;
9912 u8 type, val;
9913 u16 diff_t;
9914
9915 if ((pfwinfo->rpt_en_map &
9916 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0)
9917 return;
9918
9919 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
9920 if (!pcinfo->valid)
9921 return;
9922
9923 pstep = &pfwinfo->rpt_fbtc_step.finfo.v3;
9924 if (pcinfo->req_fver != pstep->fver)
9925 return;
9926
9927 if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP)
9928 n_begin = 1;
9929 else
9930 n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1;
9931
9932 n_end = le32_to_cpu(pstep->cnt);
9933
9934 if (n_begin > n_end)
9935 return;
9936
9937 /* restore step info by using ring instead of FIFO */
9938 for (i = n_begin; i <= n_end; i++) {
9939 array_idx = (i - 1) % FCXDEF_STEP;
9940 type = pstep->step[array_idx].type;
9941 val = pstep->step[array_idx].val;
9942 diff_t = le16_to_cpu(pstep->step[array_idx].difft);
9943
9944 if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
9945 continue;
9946
9947 if (cnt % 10 == 0)
9948 seq_printf(m, " %-15s : ", "[steps]");
9949
9950 seq_printf(m, "-> %s(%02d)",
9951 (type == CXSTEP_SLOT ?
9952 id_to_slot((u32)val) :
9953 id_to_evt((u32)val)), diff_t);
9954
9955 if (cnt % 10 == 9)
9956 seq_puts(m, "\n");
9957
9958 cnt++;
9959 }
9960 }
9961
_show_fw_dm_msg(struct rtw89_dev * rtwdev,struct seq_file * m)9962 static void _show_fw_dm_msg(struct rtw89_dev *rtwdev, struct seq_file *m)
9963 {
9964 struct rtw89_btc *btc = &rtwdev->btc;
9965 const struct rtw89_btc_ver *ver = btc->ver;
9966
9967 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
9968 return;
9969
9970 _show_error(rtwdev, m);
9971 _show_fbtc_tdma(rtwdev, m);
9972 _show_fbtc_slots(rtwdev, m);
9973
9974 if (ver->fcxcysta == 2)
9975 _show_fbtc_cysta_v2(rtwdev, m);
9976 else if (ver->fcxcysta == 3)
9977 _show_fbtc_cysta_v3(rtwdev, m);
9978 else if (ver->fcxcysta == 4)
9979 _show_fbtc_cysta_v4(rtwdev, m);
9980 else if (ver->fcxcysta == 5)
9981 _show_fbtc_cysta_v5(rtwdev, m);
9982 else if (ver->fcxcysta == 7)
9983 _show_fbtc_cysta_v7(rtwdev, m);
9984
9985 _show_fbtc_nullsta(rtwdev, m);
9986
9987 if (ver->fcxstep == 2)
9988 _show_fbtc_step_v2(rtwdev, m);
9989 else if (ver->fcxstep == 3)
9990 _show_fbtc_step_v3(rtwdev, m);
9991
9992 }
9993
_get_gnt(struct rtw89_dev * rtwdev,struct rtw89_mac_ax_coex_gnt * gnt_cfg)9994 static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg)
9995 {
9996 const struct rtw89_chip_info *chip = rtwdev->chip;
9997 struct rtw89_mac_ax_gnt *gnt;
9998 u32 val, status;
9999
10000 if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B ||
10001 chip->chip_id == RTL8851B || chip->chip_id == RTL8852BT) {
10002 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
10003 rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status);
10004
10005 gnt = &gnt_cfg->band[0];
10006 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL);
10007 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA);
10008 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL);
10009 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA);
10010
10011 gnt = &gnt_cfg->band[1];
10012 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL);
10013 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA);
10014 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL);
10015 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA);
10016 } else if (chip->chip_id == RTL8852C) {
10017 val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL);
10018 status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1);
10019
10020 gnt = &gnt_cfg->band[0];
10021 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL);
10022 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0);
10023 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL);
10024 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0);
10025
10026 gnt = &gnt_cfg->band[1];
10027 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL);
10028 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1);
10029 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL);
10030 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1);
10031 } else {
10032 return;
10033 }
10034 }
10035
_show_gpio_dbg(struct rtw89_dev * rtwdev,struct seq_file * m)10036 static void _show_gpio_dbg(struct rtw89_dev *rtwdev, struct seq_file *m)
10037 {
10038 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
10039 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
10040 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10041 union rtw89_btc_fbtc_gpio_dbg *gdbg = NULL;
10042 u8 *gpio_map, i;
10043 u32 en_map;
10044
10045 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
10046 gdbg = &rtwdev->btc.fwinfo.rpt_fbtc_gpio_dbg.finfo;
10047 if (!pcinfo->valid) {
10048 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10049 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n",
10050 __func__);
10051 seq_puts(m, "\n");
10052 return;
10053 }
10054
10055 if (ver->fcxgpiodbg == 7) {
10056 en_map = le32_to_cpu(gdbg->v7.en_map);
10057 gpio_map = gdbg->v7.gpio_map;
10058 } else {
10059 en_map = le32_to_cpu(gdbg->v1.en_map);
10060 gpio_map = gdbg->v1.gpio_map;
10061 }
10062
10063 if (!en_map)
10064 return;
10065
10066 seq_printf(m, " %-15s : enable_map:0x%08x",
10067 "[gpio_dbg]", en_map);
10068
10069 for (i = 0; i < BTC_DBG_MAX1; i++) {
10070 if (!(en_map & BIT(i)))
10071 continue;
10072 seq_printf(m, ", %s->GPIO%d", id_to_gdbg(i), gpio_map[i]);
10073 }
10074 seq_puts(m, "\n");
10075 }
10076
_show_mreg_v1(struct rtw89_dev * rtwdev,struct seq_file * m)10077 static void _show_mreg_v1(struct rtw89_dev *rtwdev, struct seq_file *m)
10078 {
10079 const struct rtw89_chip_info *chip = rtwdev->chip;
10080 struct rtw89_btc *btc = &rtwdev->btc;
10081 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10082 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10083 struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL;
10084 struct rtw89_btc_cx *cx = &btc->cx;
10085 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
10086 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
10087 struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
10088 struct rtw89_mac_ax_gnt gnt;
10089 u8 i = 0, type = 0, cnt = 0;
10090 u32 val, offset;
10091
10092 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
10093 return;
10094
10095 seq_puts(m, "========== [HW Status] ==========\n");
10096
10097 seq_printf(m,
10098 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
10099 "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
10100 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
10101 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
10102
10103 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
10104 _get_gnt(rtwdev, &gnt_cfg);
10105
10106 gnt = gnt_cfg.band[0];
10107 seq_printf(m,
10108 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
10109 "[gnt_status]",
10110 chip->chip_id == RTL8852C ? "HW" :
10111 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
10112 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
10113 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt);
10114
10115 gnt = gnt_cfg.band[1];
10116 seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
10117 gnt.gnt_wl_sw_en ? "SW" : "HW",
10118 gnt.gnt_wl,
10119 gnt.gnt_bt_sw_en ? "SW" : "HW",
10120 gnt.gnt_bt);
10121
10122 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
10123 if (!pcinfo->valid) {
10124 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10125 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
10126 __func__);
10127 return;
10128 }
10129
10130 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
10131 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10132 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
10133 __func__, pmreg->reg_num);
10134
10135 for (i = 0; i < pmreg->reg_num; i++) {
10136 type = (u8)le16_to_cpu(chip->mon_reg[i].type);
10137 offset = le32_to_cpu(chip->mon_reg[i].offset);
10138 val = le32_to_cpu(pmreg->mreg_val[i]);
10139
10140 if (cnt % 6 == 0)
10141 seq_printf(m, " %-15s : %d_0x%04x=0x%08x",
10142 "[reg]", (u32)type, offset, val);
10143 else
10144 seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type,
10145 offset, val);
10146 if (cnt % 6 == 5)
10147 seq_puts(m, "\n");
10148 cnt++;
10149
10150 if (i >= pmreg->reg_num)
10151 seq_puts(m, "\n");
10152 }
10153 }
10154
_show_mreg_v2(struct rtw89_dev * rtwdev,struct seq_file * m)10155 static void _show_mreg_v2(struct rtw89_dev *rtwdev, struct seq_file *m)
10156 {
10157 const struct rtw89_chip_info *chip = rtwdev->chip;
10158 struct rtw89_btc *btc = &rtwdev->btc;
10159 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10160 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10161 struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL;
10162 struct rtw89_btc_cx *cx = &btc->cx;
10163 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
10164 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
10165 struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
10166 struct rtw89_mac_ax_gnt gnt;
10167 u8 i = 0, type = 0, cnt = 0;
10168 u32 val, offset;
10169
10170 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
10171 return;
10172
10173 seq_puts(m, "========== [HW Status] ==========\n");
10174
10175 seq_printf(m,
10176 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
10177 "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
10178 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
10179 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
10180
10181 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
10182 _get_gnt(rtwdev, &gnt_cfg);
10183
10184 gnt = gnt_cfg.band[0];
10185 seq_printf(m,
10186 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], polut_type:%s",
10187 "[gnt_status]",
10188 chip->chip_id == RTL8852C ? "HW" :
10189 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
10190 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
10191 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt,
10192 id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
10193
10194 gnt = gnt_cfg.band[1];
10195 seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
10196 gnt.gnt_wl_sw_en ? "SW" : "HW",
10197 gnt.gnt_wl,
10198 gnt.gnt_bt_sw_en ? "SW" : "HW",
10199 gnt.gnt_bt);
10200
10201 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
10202 if (!pcinfo->valid) {
10203 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10204 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
10205 __func__);
10206 return;
10207 }
10208
10209 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
10210 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10211 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
10212 __func__, pmreg->reg_num);
10213
10214 for (i = 0; i < pmreg->reg_num; i++) {
10215 type = (u8)le16_to_cpu(chip->mon_reg[i].type);
10216 offset = le32_to_cpu(chip->mon_reg[i].offset);
10217 val = le32_to_cpu(pmreg->mreg_val[i]);
10218
10219 if (cnt % 6 == 0)
10220 seq_printf(m, " %-15s : %d_0x%04x=0x%08x",
10221 "[reg]", (u32)type, offset, val);
10222 else
10223 seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type,
10224 offset, val);
10225 if (cnt % 6 == 5)
10226 seq_puts(m, "\n");
10227 cnt++;
10228
10229 if (i >= pmreg->reg_num)
10230 seq_puts(m, "\n");
10231 }
10232 }
10233
_show_mreg_v7(struct rtw89_dev * rtwdev,struct seq_file * m)10234 static void _show_mreg_v7(struct rtw89_dev *rtwdev, struct seq_file *m)
10235 {
10236 struct rtw89_btc *btc = &rtwdev->btc;
10237 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10238 struct rtw89_btc_fbtc_mreg_val_v7 *pmreg = NULL;
10239 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10240 struct rtw89_btc_cx *cx = &btc->cx;
10241 struct rtw89_btc_wl_info *wl = &cx->wl;
10242 struct rtw89_btc_bt_info *bt = &cx->bt;
10243 struct rtw89_mac_ax_gnt *gnt = NULL;
10244 struct rtw89_btc_dm *dm = &btc->dm;
10245 u8 i, type, cnt = 0;
10246 u32 val, offset;
10247
10248 if (!(dm->coex_info_map & BTC_COEX_INFO_MREG))
10249 return;
10250
10251 seq_puts(m, "\n\r========== [HW Status] ==========");
10252
10253 seq_printf(m,
10254 "\n\r %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)",
10255 "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
10256 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
10257 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
10258
10259 /* To avoid I/O if WL LPS or power-off */
10260 dm->pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
10261
10262 seq_printf(m,
10263 "\n\r %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s",
10264 "[gnt_status]",
10265 rtwdev->chip->para_ver & BTC_FEAT_PTA_ONOFF_CTRL ? "HW" :
10266 dm->pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
10267 wl->pta_req_mac, id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
10268
10269 gnt = &dm->gnt.band[RTW89_PHY_0];
10270
10271 seq_printf(m, ", phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]",
10272 gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl,
10273 gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt);
10274
10275 if (rtwdev->dbcc_en) {
10276 gnt = &dm->gnt.band[RTW89_PHY_1];
10277 seq_printf(m, ", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]",
10278 gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl,
10279 gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt);
10280 }
10281
10282 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
10283 if (!pcinfo->valid)
10284 return;
10285
10286 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
10287
10288 for (i = 0; i < pmreg->reg_num; i++) {
10289 type = (u8)le16_to_cpu(rtwdev->chip->mon_reg[i].type);
10290 offset = le32_to_cpu(rtwdev->chip->mon_reg[i].offset);
10291 val = le32_to_cpu(pmreg->mreg_val[i]);
10292
10293 if (cnt % 6 == 0)
10294 seq_printf(m, "\n\r %-15s : %s_0x%x=0x%x", "[reg]",
10295 id_to_regtype(type), offset, val);
10296 else
10297 seq_printf(m, ", %s_0x%x=0x%x",
10298 id_to_regtype(type), offset, val);
10299 cnt++;
10300 }
10301 seq_puts(m, "\n");
10302 }
10303
_show_summary_v1(struct rtw89_dev * rtwdev,struct seq_file * m)10304 static void _show_summary_v1(struct rtw89_dev *rtwdev, struct seq_file *m)
10305 {
10306 struct rtw89_btc *btc = &rtwdev->btc;
10307 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10308 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10309 struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL;
10310 struct rtw89_btc_cx *cx = &btc->cx;
10311 struct rtw89_btc_dm *dm = &btc->dm;
10312 struct rtw89_btc_wl_info *wl = &cx->wl;
10313 struct rtw89_btc_bt_info *bt = &cx->bt;
10314 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
10315 u8 i;
10316
10317 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
10318 return;
10319
10320 seq_puts(m, "========== [Statistics] ==========\n");
10321
10322 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
10323 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
10324 prptctrl = &pfwinfo->rpt_ctrl.finfo.v1;
10325
10326 seq_printf(m,
10327 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
10328 "[summary]", pfwinfo->cnt_h2c,
10329 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt,
10330 pfwinfo->cnt_c2h, prptctrl->c2h_cnt);
10331
10332 seq_printf(m,
10333 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
10334 pfwinfo->event[BTF_EVNT_RPT], prptctrl->rpt_cnt,
10335 prptctrl->rpt_enable, dm->error.val);
10336
10337 if (dm->error.map.wl_fw_hang)
10338 seq_puts(m, " (WL FW Hang!!)");
10339 seq_puts(m, "\n");
10340 seq_printf(m,
10341 " %-15s : send_ok:%d, send_fail:%d, recv:%d",
10342 "[mailbox]", prptctrl->mb_send_ok_cnt,
10343 prptctrl->mb_send_fail_cnt, prptctrl->mb_recv_cnt);
10344
10345 seq_printf(m,
10346 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n",
10347 prptctrl->mb_a2dp_empty_cnt,
10348 prptctrl->mb_a2dp_flct_cnt,
10349 prptctrl->mb_a2dp_full_cnt);
10350
10351 seq_printf(m,
10352 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
10353 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
10354 cx->cnt_wl[BTC_WCNT_RFK_GO],
10355 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
10356 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
10357
10358 seq_printf(m,
10359 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
10360 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
10361 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
10362 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
10363 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
10364 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
10365
10366 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
10367 bt->rfk_info.map.timeout = 1;
10368 else
10369 bt->rfk_info.map.timeout = 0;
10370
10371 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
10372 } else {
10373 seq_printf(m,
10374 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
10375 "[summary]", pfwinfo->cnt_h2c,
10376 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
10377 pfwinfo->event[BTF_EVNT_RPT],
10378 btc->fwinfo.rpt_en_map);
10379 seq_puts(m, " (WL FW report invalid!!)\n");
10380 }
10381
10382 for (i = 0; i < BTC_NCNT_NUM; i++)
10383 cnt_sum += dm->cnt_notify[i];
10384
10385 seq_printf(m,
10386 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
10387 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
10388 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
10389
10390 seq_printf(m,
10391 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
10392 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
10393 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
10394 cnt[BTC_NCNT_WL_STA]);
10395
10396 seq_printf(m,
10397 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
10398 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
10399 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
10400 cnt[BTC_NCNT_SPECIAL_PACKET]);
10401
10402 seq_printf(m,
10403 "timer=%d, control=%d, customerize=%d\n",
10404 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
10405 cnt[BTC_NCNT_CUSTOMERIZE]);
10406 }
10407
_show_summary_v4(struct rtw89_dev * rtwdev,struct seq_file * m)10408 static void _show_summary_v4(struct rtw89_dev *rtwdev, struct seq_file *m)
10409 {
10410 struct rtw89_btc *btc = &rtwdev->btc;
10411 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10412 struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl;
10413 struct rtw89_btc_rpt_cmn_info *pcinfo;
10414 struct rtw89_btc_cx *cx = &btc->cx;
10415 struct rtw89_btc_dm *dm = &btc->dm;
10416 struct rtw89_btc_wl_info *wl = &cx->wl;
10417 struct rtw89_btc_bt_info *bt = &cx->bt;
10418 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
10419 u8 i;
10420
10421 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
10422 return;
10423
10424 seq_puts(m, "========== [Statistics] ==========\n");
10425
10426 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
10427 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
10428 prptctrl = &pfwinfo->rpt_ctrl.finfo.v4;
10429
10430 seq_printf(m,
10431 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
10432 "[summary]", pfwinfo->cnt_h2c,
10433 pfwinfo->cnt_h2c_fail,
10434 le32_to_cpu(prptctrl->rpt_info.cnt_h2c),
10435 pfwinfo->cnt_c2h,
10436 le32_to_cpu(prptctrl->rpt_info.cnt_c2h));
10437
10438 seq_printf(m,
10439 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
10440 pfwinfo->event[BTF_EVNT_RPT],
10441 le32_to_cpu(prptctrl->rpt_info.cnt),
10442 le32_to_cpu(prptctrl->rpt_info.en),
10443 dm->error.val);
10444
10445 if (dm->error.map.wl_fw_hang)
10446 seq_puts(m, " (WL FW Hang!!)");
10447 seq_puts(m, "\n");
10448 seq_printf(m,
10449 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
10450 "[mailbox]",
10451 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
10452 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
10453 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
10454
10455 seq_printf(m,
10456 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
10457 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
10458 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
10459 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
10460 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
10461 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
10462
10463 seq_printf(m,
10464 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
10465 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
10466 cx->cnt_wl[BTC_WCNT_RFK_GO],
10467 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
10468 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
10469
10470 seq_printf(m,
10471 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
10472 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]),
10473 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]),
10474 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]),
10475 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]),
10476 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL]));
10477
10478 if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
10479 bt->rfk_info.map.timeout = 1;
10480 else
10481 bt->rfk_info.map.timeout = 0;
10482
10483 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
10484 } else {
10485 seq_printf(m,
10486 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
10487 "[summary]", pfwinfo->cnt_h2c,
10488 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
10489 pfwinfo->event[BTF_EVNT_RPT],
10490 btc->fwinfo.rpt_en_map);
10491 seq_puts(m, " (WL FW report invalid!!)\n");
10492 }
10493
10494 for (i = 0; i < BTC_NCNT_NUM; i++)
10495 cnt_sum += dm->cnt_notify[i];
10496
10497 seq_printf(m,
10498 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
10499 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
10500 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
10501
10502 seq_printf(m,
10503 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
10504 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
10505 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
10506 cnt[BTC_NCNT_WL_STA]);
10507
10508 seq_printf(m,
10509 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
10510 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
10511 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
10512 cnt[BTC_NCNT_SPECIAL_PACKET]);
10513
10514 seq_printf(m,
10515 "timer=%d, control=%d, customerize=%d\n",
10516 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
10517 cnt[BTC_NCNT_CUSTOMERIZE]);
10518 }
10519
_show_summary_v5(struct rtw89_dev * rtwdev,struct seq_file * m)10520 static void _show_summary_v5(struct rtw89_dev *rtwdev, struct seq_file *m)
10521 {
10522 struct rtw89_btc *btc = &rtwdev->btc;
10523 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10524 struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl;
10525 struct rtw89_btc_rpt_cmn_info *pcinfo;
10526 struct rtw89_btc_cx *cx = &btc->cx;
10527 struct rtw89_btc_dm *dm = &btc->dm;
10528 struct rtw89_btc_wl_info *wl = &cx->wl;
10529 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
10530 u8 i;
10531
10532 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
10533 return;
10534
10535 seq_puts(m, "========== [Statistics] ==========\n");
10536
10537 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
10538 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
10539 prptctrl = &pfwinfo->rpt_ctrl.finfo.v5;
10540
10541 seq_printf(m,
10542 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
10543 "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
10544 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
10545 pfwinfo->cnt_c2h,
10546 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
10547 le16_to_cpu(prptctrl->rpt_info.len_c2h));
10548
10549 seq_printf(m,
10550 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
10551 pfwinfo->event[BTF_EVNT_RPT],
10552 le16_to_cpu(prptctrl->rpt_info.cnt),
10553 le32_to_cpu(prptctrl->rpt_info.en));
10554
10555 if (dm->error.map.wl_fw_hang)
10556 seq_puts(m, " (WL FW Hang!!)");
10557 seq_puts(m, "\n");
10558 seq_printf(m,
10559 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
10560 "[mailbox]",
10561 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
10562 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
10563 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
10564
10565 seq_printf(m,
10566 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
10567 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
10568 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
10569 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
10570 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
10571 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
10572
10573 seq_printf(m,
10574 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
10575 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
10576 cx->cnt_wl[BTC_WCNT_RFK_GO],
10577 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
10578 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
10579
10580 seq_printf(m,
10581 ", bt_rfk[req:%d]",
10582 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
10583
10584 seq_printf(m,
10585 ", AOAC[RF_on:%d/RF_off:%d]",
10586 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
10587 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
10588 } else {
10589 seq_printf(m,
10590 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
10591 "[summary]", pfwinfo->cnt_h2c,
10592 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
10593 }
10594
10595 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
10596 pfwinfo->err[BTFRE_EXCEPTION]) {
10597 seq_puts(m, "\n");
10598 seq_printf(m,
10599 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
10600 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
10601 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
10602 pfwinfo->fver_mismch, pfwinfo->err[BTFRE_EXCEPTION],
10603 wl->status.map.lps, wl->status.map.rf_off);
10604 }
10605
10606 for (i = 0; i < BTC_NCNT_NUM; i++)
10607 cnt_sum += dm->cnt_notify[i];
10608
10609 seq_puts(m, "\n");
10610 seq_printf(m,
10611 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
10612 "[notify_cnt]",
10613 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
10614 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
10615
10616 seq_printf(m,
10617 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
10618 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
10619 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
10620 cnt[BTC_NCNT_WL_STA]);
10621
10622 seq_puts(m, "\n");
10623 seq_printf(m,
10624 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
10625 "[notify_cnt]",
10626 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
10627 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SPECIAL_PACKET]);
10628
10629 seq_printf(m,
10630 "timer=%d, control=%d, customerize=%d",
10631 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
10632 cnt[BTC_NCNT_CUSTOMERIZE]);
10633 }
10634
_show_summary_v105(struct rtw89_dev * rtwdev,struct seq_file * m)10635 static void _show_summary_v105(struct rtw89_dev *rtwdev, struct seq_file *m)
10636 {
10637 struct rtw89_btc *btc = &rtwdev->btc;
10638 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10639 struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl;
10640 struct rtw89_btc_rpt_cmn_info *pcinfo;
10641 struct rtw89_btc_cx *cx = &btc->cx;
10642 struct rtw89_btc_dm *dm = &btc->dm;
10643 struct rtw89_btc_wl_info *wl = &cx->wl;
10644 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
10645 u8 i;
10646
10647 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
10648 return;
10649
10650 seq_puts(m, "========== [Statistics] ==========\n");
10651
10652 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
10653 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
10654 prptctrl = &pfwinfo->rpt_ctrl.finfo.v105;
10655
10656 seq_printf(m,
10657 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
10658 "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
10659 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
10660 pfwinfo->cnt_c2h,
10661 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
10662 le16_to_cpu(prptctrl->rpt_info.len_c2h));
10663
10664 seq_printf(m,
10665 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
10666 pfwinfo->event[BTF_EVNT_RPT],
10667 le16_to_cpu(prptctrl->rpt_info.cnt),
10668 le32_to_cpu(prptctrl->rpt_info.en));
10669
10670 if (dm->error.map.wl_fw_hang)
10671 seq_puts(m, " (WL FW Hang!!)");
10672 seq_puts(m, "\n");
10673 seq_printf(m,
10674 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
10675 "[mailbox]",
10676 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
10677 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
10678 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
10679
10680 seq_printf(m,
10681 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
10682 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
10683 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
10684 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
10685 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
10686 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
10687
10688 seq_printf(m,
10689 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
10690 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
10691 cx->cnt_wl[BTC_WCNT_RFK_GO],
10692 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
10693 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
10694
10695 seq_printf(m,
10696 ", bt_rfk[req:%d]",
10697 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
10698
10699 seq_printf(m,
10700 ", AOAC[RF_on:%d/RF_off:%d]",
10701 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
10702 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
10703 } else {
10704 seq_printf(m,
10705 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
10706 "[summary]", pfwinfo->cnt_h2c,
10707 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
10708 }
10709
10710 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
10711 pfwinfo->err[BTFRE_EXCEPTION]) {
10712 seq_puts(m, "\n");
10713 seq_printf(m,
10714 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
10715 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
10716 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
10717 pfwinfo->fver_mismch, pfwinfo->err[BTFRE_EXCEPTION],
10718 wl->status.map.lps, wl->status.map.rf_off);
10719 }
10720
10721 for (i = 0; i < BTC_NCNT_NUM; i++)
10722 cnt_sum += dm->cnt_notify[i];
10723
10724 seq_puts(m, "\n");
10725 seq_printf(m,
10726 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
10727 "[notify_cnt]",
10728 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
10729 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
10730
10731 seq_printf(m,
10732 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
10733 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
10734 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
10735 cnt[BTC_NCNT_WL_STA]);
10736
10737 seq_puts(m, "\n");
10738 seq_printf(m,
10739 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
10740 "[notify_cnt]",
10741 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
10742 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SPECIAL_PACKET]);
10743
10744 seq_printf(m,
10745 "timer=%d, control=%d, customerize=%d",
10746 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
10747 cnt[BTC_NCNT_CUSTOMERIZE]);
10748 }
10749
_show_summary_v7(struct rtw89_dev * rtwdev,struct seq_file * m)10750 static void _show_summary_v7(struct rtw89_dev *rtwdev, struct seq_file *m)
10751 {
10752 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
10753 struct rtw89_btc_fbtc_rpt_ctrl_v7 *prptctrl = NULL;
10754 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10755 struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
10756 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
10757 struct rtw89_btc_wl_info *wl = &cx->wl;
10758 u32 *cnt = rtwdev->btc.dm.cnt_notify;
10759 u32 cnt_sum = 0;
10760 u8 i;
10761
10762 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
10763 return;
10764
10765 seq_printf(m, "%s", "\n\r========== [Statistics] ==========");
10766
10767 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
10768 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
10769 !wl->status.map.rf_off) {
10770 prptctrl = &pfwinfo->rpt_ctrl.finfo.v7;
10771
10772 seq_printf(m,
10773 "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d),"
10774 "c2h_cnt=%d(fw_send:%d, len:%d, max:%d), ",
10775 "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
10776 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), pfwinfo->cnt_c2h,
10777 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
10778 le16_to_cpu(prptctrl->rpt_info.len_c2h),
10779 rtwdev->btc.ver->info_buf);
10780
10781 seq_printf(m, "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
10782 pfwinfo->event[BTF_EVNT_RPT],
10783 le16_to_cpu(prptctrl->rpt_info.cnt),
10784 le32_to_cpu(prptctrl->rpt_info.en));
10785
10786 if (dm->error.map.wl_fw_hang)
10787 seq_puts(m, " (WL FW Hang!!)");
10788
10789 seq_printf(m, "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
10790 "[mailbox]", le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
10791 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
10792 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
10793
10794 seq_printf(m, "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)",
10795 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
10796 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
10797 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
10798 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
10799 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
10800
10801 seq_printf(m,
10802 "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
10803 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
10804 cx->cnt_wl[BTC_WCNT_RFK_GO],
10805 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
10806 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT],
10807 wl->rfk_info.proc_time);
10808
10809 seq_printf(m, ", bt_rfk[req:%d]",
10810 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
10811
10812 seq_printf(m, ", AOAC[RF_on:%d/RF_off:%d]",
10813 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
10814 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
10815 } else {
10816 seq_printf(m,
10817 "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)",
10818 "[summary]",
10819 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
10820 pfwinfo->cnt_c2h,
10821 wl->status.map.lps, wl->status.map.rf_off);
10822 }
10823
10824 for (i = 0; i < BTC_NCNT_NUM; i++)
10825 cnt_sum += dm->cnt_notify[i];
10826
10827 seq_printf(m,
10828 "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
10829 "[notify_cnt]",
10830 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
10831 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
10832
10833 seq_printf(m,
10834 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
10835 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
10836 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
10837 cnt[BTC_NCNT_WL_STA]);
10838
10839 seq_printf(m,
10840 "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
10841 "[notify_cnt]",
10842 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
10843 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
10844 cnt[BTC_NCNT_SPECIAL_PACKET]);
10845
10846 seq_printf(m, "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
10847 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
10848 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
10849 cnt[BTC_NCNT_COUNTRYCODE]);
10850 }
10851
_show_summary_v8(struct rtw89_dev * rtwdev,struct seq_file * m)10852 static void _show_summary_v8(struct rtw89_dev *rtwdev, struct seq_file *m)
10853 {
10854 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
10855 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10856 struct rtw89_btc_fbtc_rpt_ctrl_v8 *prptctrl = NULL;
10857 struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
10858 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
10859 struct rtw89_btc_wl_info *wl = &cx->wl;
10860 u32 *cnt = rtwdev->btc.dm.cnt_notify;
10861 u32 cnt_sum = 0;
10862 u8 i;
10863
10864 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
10865 return;
10866
10867 seq_printf(m, "%s", "\n\r========== [Statistics] ==========");
10868
10869 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
10870 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
10871 !wl->status.map.rf_off) {
10872 prptctrl = &pfwinfo->rpt_ctrl.finfo.v8;
10873
10874 seq_printf(m,
10875 "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ",
10876 "[summary]", pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
10877 le16_to_cpu(prptctrl->rpt_info.cnt_h2c), pfwinfo->cnt_c2h,
10878 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
10879 le16_to_cpu(prptctrl->rpt_info.len_c2h),
10880 (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l,
10881 rtwdev->btc.ver->info_buf);
10882
10883 seq_printf(m, "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
10884 pfwinfo->event[BTF_EVNT_RPT],
10885 le16_to_cpu(prptctrl->rpt_info.cnt),
10886 le32_to_cpu(prptctrl->rpt_info.en));
10887
10888 if (dm->error.map.wl_fw_hang)
10889 seq_puts(m, " (WL FW Hang!!)");
10890
10891 seq_printf(m, "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
10892 "[mailbox]", le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
10893 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
10894 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
10895
10896 seq_printf(m, "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)",
10897 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
10898 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
10899 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
10900 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
10901 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
10902
10903 seq_printf(m,
10904 "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
10905 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
10906 cx->cnt_wl[BTC_WCNT_RFK_GO],
10907 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
10908 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT],
10909 wl->rfk_info.proc_time);
10910
10911 seq_printf(m, ", bt_rfk[req:%d]",
10912 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
10913
10914 seq_printf(m, ", AOAC[RF_on:%d/RF_off:%d]",
10915 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
10916 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
10917 } else {
10918 seq_printf(m,
10919 "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)",
10920 "[summary]",
10921 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
10922 pfwinfo->cnt_c2h,
10923 wl->status.map.lps, wl->status.map.rf_off);
10924 }
10925
10926 for (i = 0; i < BTC_NCNT_NUM; i++)
10927 cnt_sum += dm->cnt_notify[i];
10928
10929 seq_printf(m,
10930 "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
10931 "[notify_cnt]",
10932 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
10933 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
10934
10935 seq_printf(m,
10936 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
10937 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
10938 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
10939 cnt[BTC_NCNT_WL_STA]);
10940
10941 seq_printf(m,
10942 "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
10943 "[notify_cnt]",
10944 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
10945 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
10946 cnt[BTC_NCNT_SPECIAL_PACKET]);
10947
10948 seq_printf(m, "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
10949 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
10950 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
10951 cnt[BTC_NCNT_COUNTRYCODE]);
10952 }
10953
rtw89_btc_dump_info(struct rtw89_dev * rtwdev,struct seq_file * m)10954 void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m)
10955 {
10956 struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal;
10957 struct rtw89_btc *btc = &rtwdev->btc;
10958 const struct rtw89_btc_ver *ver = btc->ver;
10959 struct rtw89_btc_cx *cx = &btc->cx;
10960 struct rtw89_btc_bt_info *bt = &cx->bt;
10961
10962 seq_puts(m, "=========================================\n");
10963 seq_printf(m, "WL FW / BT FW %d.%d.%d.%d / NA\n",
10964 fw_suit->major_ver, fw_suit->minor_ver,
10965 fw_suit->sub_ver, fw_suit->sub_idex);
10966 seq_printf(m, "manual %d\n", btc->manual_ctrl);
10967
10968 seq_puts(m, "=========================================\n");
10969
10970 seq_printf(m, "\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)",
10971 "[bt_info]",
10972 bt->raw_info[2], bt->raw_info[3],
10973 bt->raw_info[4], bt->raw_info[5],
10974 bt->raw_info[6], bt->raw_info[7],
10975 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
10976 cx->cnt_bt[BTC_BCNT_INFOUPDATE],
10977 cx->cnt_bt[BTC_BCNT_INFOSAME]);
10978
10979 seq_puts(m, "\n=========================================\n");
10980
10981 _show_cx_info(rtwdev, m);
10982 _show_wl_info(rtwdev, m);
10983 _show_bt_info(rtwdev, m);
10984 _show_dm_info(rtwdev, m);
10985 _show_fw_dm_msg(rtwdev, m);
10986
10987 if (ver->fcxmreg == 1)
10988 _show_mreg_v1(rtwdev, m);
10989 else if (ver->fcxmreg == 2)
10990 _show_mreg_v2(rtwdev, m);
10991 else if (ver->fcxmreg == 7)
10992 _show_mreg_v7(rtwdev, m);
10993
10994 _show_gpio_dbg(rtwdev, m);
10995
10996 if (ver->fcxbtcrpt == 1)
10997 _show_summary_v1(rtwdev, m);
10998 else if (ver->fcxbtcrpt == 4)
10999 _show_summary_v4(rtwdev, m);
11000 else if (ver->fcxbtcrpt == 5)
11001 _show_summary_v5(rtwdev, m);
11002 else if (ver->fcxbtcrpt == 105)
11003 _show_summary_v105(rtwdev, m);
11004 else if (ver->fcxbtcrpt == 7)
11005 _show_summary_v7(rtwdev, m);
11006 else if (ver->fcxbtcrpt == 8)
11007 _show_summary_v8(rtwdev, m);
11008 }
11009
rtw89_coex_recognize_ver(struct rtw89_dev * rtwdev)11010 void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev)
11011 {
11012 const struct rtw89_chip_info *chip = rtwdev->chip;
11013 struct rtw89_btc *btc = &rtwdev->btc;
11014 const struct rtw89_btc_ver *btc_ver_def;
11015 const struct rtw89_fw_suit *fw_suit;
11016 u32 suit_ver_code;
11017 int i;
11018
11019 fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL);
11020 suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit);
11021
11022 for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) {
11023 btc_ver_def = &rtw89_btc_ver_defs[i];
11024
11025 if (chip->chip_id != btc_ver_def->chip_id)
11026 continue;
11027
11028 if (suit_ver_code >= btc_ver_def->fw_ver_code) {
11029 btc->ver = btc_ver_def;
11030 goto out;
11031 }
11032 }
11033
11034 btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX];
11035
11036 out:
11037 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n",
11038 (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code);
11039 }
11040