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