xref: /linux/drivers/net/wireless/realtek/rtw89/coex.c (revision 8be4d31cb8aaeea27bde4b7ddb26e28a89062ebf)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2019-2020  Realtek Corporation
3  */
4 
5 #include "chan.h"
6 #include "coex.h"
7 #include "debug.h"
8 #include "fw.h"
9 #include "mac.h"
10 #include "phy.h"
11 #include "ps.h"
12 #include "reg.h"
13 
14 #define RTW89_COEX_VERSION 0x09000013
15 #define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/
16 #define BTC_E2G_LIMIT_DEF 80
17 
18 enum btc_fbtc_tdma_template {
19 	CXTD_OFF = 0x0,
20 	CXTD_OFF_B2,
21 	CXTD_OFF_EXT,
22 	CXTD_FIX,
23 	CXTD_PFIX,
24 	CXTD_AUTO,
25 	CXTD_PAUTO,
26 	CXTD_AUTO2,
27 	CXTD_PAUTO2,
28 	CXTD_MAX,
29 };
30 
31 enum btc_fbtc_tdma_type {
32 	CXTDMA_OFF = 0x0,
33 	CXTDMA_FIX = 0x1,
34 	CXTDMA_AUTO = 0x2,
35 	CXTDMA_AUTO2 = 0x3,
36 	CXTDMA_MAX
37 };
38 
39 enum btc_fbtc_tdma_rx_flow_ctrl {
40 	CXFLC_OFF = 0x0,
41 	CXFLC_NULLP = 0x1,
42 	CXFLC_QOSNULL = 0x2,
43 	CXFLC_CTS = 0x3,
44 	CXFLC_MAX
45 };
46 
47 enum btc_fbtc_tdma_wlan_tx_pause {
48 	CXTPS_OFF = 0x0,  /* no wl tx pause*/
49 	CXTPS_ON = 0x1,
50 	CXTPS_MAX
51 };
52 
53 enum btc_mlme_state {
54 	MLME_NO_LINK,
55 	MLME_LINKING,
56 	MLME_LINKED,
57 };
58 
59 struct btc_fbtc_1slot {
60 	u8 fver;
61 	u8 sid; /* slot id */
62 	struct rtw89_btc_fbtc_slot slot;
63 } __packed;
64 
65 static const struct rtw89_btc_fbtc_tdma t_def[] = {
66 	[CXTD_OFF]	= { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
67 	[CXTD_OFF_B2]	= { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0},
68 	[CXTD_OFF_EXT]	= { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 2, 0, 0},
69 	[CXTD_FIX]	= { CXTDMA_FIX,    CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
70 	[CXTD_PFIX]	= { CXTDMA_FIX,  CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0},
71 	[CXTD_AUTO]	= { CXTDMA_AUTO,   CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
72 	[CXTD_PAUTO]	= { CXTDMA_AUTO, CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0},
73 	[CXTD_AUTO2]	= {CXTDMA_AUTO2,   CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
74 	[CXTD_PAUTO2]	= {CXTDMA_AUTO2, CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0}
75 };
76 
77 #define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \
78 	{ .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \
79 	  .cxtype = cpu_to_le16(__cxtype),}
80 
81 static const struct rtw89_btc_fbtc_slot s_def[] = {
82 	[CXST_OFF]	= __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
83 	[CXST_B2W]	= __DEF_FBTC_SLOT(5,   0xea5a5a5a, SLOT_ISO),
84 	[CXST_W1]	= __DEF_FBTC_SLOT(70,  0xea5a5a5a, SLOT_ISO),
85 	[CXST_W2]	= __DEF_FBTC_SLOT(15,  0xea5a5a5a, SLOT_ISO),
86 	[CXST_W2B]	= __DEF_FBTC_SLOT(15,  0xea5a5a5a, SLOT_ISO),
87 	[CXST_B1]	= __DEF_FBTC_SLOT(250, 0xe5555555, SLOT_MIX),
88 	[CXST_B2]	= __DEF_FBTC_SLOT(7,   0xea5a5a5a, SLOT_MIX),
89 	[CXST_B3]	= __DEF_FBTC_SLOT(5,   0xe5555555, SLOT_MIX),
90 	[CXST_B4]	= __DEF_FBTC_SLOT(50,  0xe5555555, SLOT_MIX),
91 	[CXST_LK]	= __DEF_FBTC_SLOT(20,  0xea5a5a5a, SLOT_ISO),
92 	[CXST_BLK]	= __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX),
93 	[CXST_E2G]	= __DEF_FBTC_SLOT(5,   0xea5a5a5a, SLOT_MIX),
94 	[CXST_E5G]	= __DEF_FBTC_SLOT(5,   0xffffffff, SLOT_ISO),
95 	[CXST_EBT]	= __DEF_FBTC_SLOT(5,   0xe5555555, SLOT_MIX),
96 	[CXST_ENULL]	= __DEF_FBTC_SLOT(5,   0xaaaaaaaa, SLOT_ISO),
97 	[CXST_WLK]	= __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX),
98 	[CXST_W1FDD]	= __DEF_FBTC_SLOT(50,  0xffffffff, SLOT_ISO),
99 	[CXST_B1FDD]	= __DEF_FBTC_SLOT(50,  0xffffdfff, SLOT_ISO),
100 };
101 
102 static const u32 cxtbl[] = {
103 	0xffffffff, /* 0 */
104 	0xaaaaaaaa, /* 1 */
105 	0xe5555555, /* 2 */
106 	0xee555555, /* 3 */
107 	0xd5555555, /* 4 */
108 	0x5a5a5a5a, /* 5 */
109 	0xfa5a5a5a, /* 6 */
110 	0xda5a5a5a, /* 7 */
111 	0xea5a5a5a, /* 8 */
112 	0x6a5a5aaa, /* 9 */
113 	0x6a5a6a5a, /* 10 */
114 	0x6a5a6aaa, /* 11 */
115 	0x6afa5afa, /* 12 */
116 	0xaaaa5aaa, /* 13 */
117 	0xaaffffaa, /* 14 */
118 	0xaa5555aa, /* 15 */
119 	0xfafafafa, /* 16 */
120 	0xffffddff, /* 17 */
121 	0xdaffdaff, /* 18 */
122 	0xfafadafa, /* 19 */
123 	0xea6a6a6a, /* 20 */
124 	0xea55556a, /* 21 */
125 	0xaafafafa, /* 22 */
126 	0xfafaaafa, /* 23 */
127 	0xfafffaff, /* 24 */
128 	0xea6a5a5a, /* 25 */
129 	0xfaff5aff, /* 26 */
130 	0xffffdfff, /* 27 */
131 	0xe6555555, /* 28 */
132 };
133 
134 static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
135 	/* firmware version must be in decreasing order for each chip */
136 	{RTL8852BT, RTW89_FW_VER_CODE(0, 29, 122, 0),
137 	 .fcxbtcrpt = 8, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
138 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 7,
139 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
140 	 .fwlrole = 7,   .frptmap = 3,    .fcxctrl = 7,  .fcxinit = 7,
141 	 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
142 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 8,
143 	},
144 	{RTL8852BT, RTW89_FW_VER_CODE(0, 29, 90, 0),
145 	 .fcxbtcrpt = 7, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
146 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 7,
147 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
148 	 .fwlrole = 7,   .frptmap = 3,    .fcxctrl = 7,  .fcxinit = 7,
149 	 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
150 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 8,
151 	},
152 	{RTL8922A, RTW89_FW_VER_CODE(0, 35, 71, 0),
153 	 .fcxbtcrpt = 8, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
154 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 7,
155 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
156 	 .fwlrole = 8,   .frptmap = 4,    .fcxctrl = 7,  .fcxinit = 7,
157 	 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_type = 2, .info_buf = 1800,
158 	 .max_role_num = 6, .fcxosi = 1,  .fcxmlo = 1,   .bt_desired = 9,
159 	},
160 	{RTL8922A, RTW89_FW_VER_CODE(0, 35, 63, 0),
161 	 .fcxbtcrpt = 8, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
162 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 7,
163 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
164 	 .fwlrole = 8,   .frptmap = 4,    .fcxctrl = 7,  .fcxinit = 7,
165 	 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_type = 2, .info_buf = 1800,
166 	 .max_role_num = 6, .fcxosi = 1,  .fcxmlo = 1,   .bt_desired = 9,
167 	},
168 	{RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0),
169 	 .fcxbtcrpt = 8, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
170 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 7,
171 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
172 	 .fwlrole = 8,   .frptmap = 3,    .fcxctrl = 7,  .fcxinit = 7,
173 	 .fwevntrptl = 1, .fwc2hfunc = 1, .drvinfo_type = 1, .info_buf = 1800,
174 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
175 	},
176 	{RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0),
177 	 .fcxbtcrpt = 105, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 5,
178 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 2,  .fcxgpiodbg = 1,
179 	 .fcxbtver = 1,  .fcxbtscan = 2,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
180 	 .fwlrole = 2,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
181 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
182 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
183 	},
184 	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0),
185 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
186 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
187 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
188 	 .fwlrole = 1,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
189 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
190 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
191 	},
192 	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0),
193 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
194 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
195 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
196 	 .fwlrole = 1,   .frptmap = 2,    .fcxctrl = 1,  .fcxinit = 0,
197 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
198 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
199 	},
200 	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0),
201 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
202 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
203 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
204 	 .fwlrole = 1,   .frptmap = 2,    .fcxctrl = 1,  .fcxinit = 0,
205 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
206 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
207 	},
208 	{RTL8852B, RTW89_FW_VER_CODE(0, 29, 122, 0),
209 	 .fcxbtcrpt = 8, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
210 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 7,
211 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
212 	 .fwlrole = 7,   .frptmap = 3,    .fcxctrl = 7,  .fcxinit = 7,
213 	 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
214 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 8,
215 	},
216 	{RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0),
217 	 .fcxbtcrpt = 105, .fcxtdma = 3,  .fcxslots = 1, .fcxcysta = 5,
218 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 2,  .fcxgpiodbg = 1,
219 	 .fcxbtver = 1,  .fcxbtscan = 2,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
220 	 .fwlrole = 2,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
221 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
222 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
223 	},
224 	{RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0),
225 	 .fcxbtcrpt = 5, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 4,
226 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
227 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
228 	 .fwlrole = 1,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
229 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
230 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
231 	},
232 	{RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0),
233 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
234 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
235 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
236 	 .fwlrole = 1,   .frptmap = 1,    .fcxctrl = 1,  .fcxinit = 0,
237 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
238 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
239 	},
240 	{RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0),
241 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
242 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
243 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
244 	 .fwlrole = 1,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
245 	 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1280,
246 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
247 	},
248 	{RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0),
249 	 .fcxbtcrpt = 1, .fcxtdma = 1,    .fcxslots = 1, .fcxcysta = 2,
250 	 .fcxstep = 2,   .fcxnullsta = 1, .fcxmreg = 1,  .fcxgpiodbg = 1,
251 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
252 	 .fwlrole = 0,   .frptmap = 0,    .fcxctrl = 0,  .fcxinit = 0,
253 	 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1024,
254 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
255 	},
256 
257 	/* keep it to be the last as default entry */
258 	{0, RTW89_FW_VER_CODE(0, 0, 0, 0),
259 	 .fcxbtcrpt = 1, .fcxtdma = 1,    .fcxslots = 1, .fcxcysta = 2,
260 	 .fcxstep = 2,   .fcxnullsta = 1, .fcxmreg = 1,  .fcxgpiodbg = 1,
261 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
262 	 .fwlrole = 0,   .frptmap = 0,    .fcxctrl = 0,  .fcxinit = 0,
263 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1024,
264 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
265 	},
266 };
267 
268 #define RTW89_DEFAULT_BTC_VER_IDX (ARRAY_SIZE(rtw89_btc_ver_defs) - 1)
269 
270 static const union rtw89_btc_wl_state_map btc_scanning_map = {
271 	.map = {
272 		.scan = 1,
273 		.connecting = 1,
274 		.roaming = 1,
275 		.dbccing = 1,
276 		._4way = 1,
277 	},
278 };
279 
chip_id_to_bt_rom_code_id(u32 id)280 static u32 chip_id_to_bt_rom_code_id(u32 id)
281 {
282 	switch (id) {
283 	case RTL8852A:
284 	case RTL8852B:
285 	case RTL8852C:
286 	case RTL8852BT:
287 		return 0x8852;
288 	case RTL8851B:
289 		return 0x8851;
290 	case RTL8922A:
291 		return 0x8922;
292 	default:
293 		return 0;
294 	}
295 }
296 
297 #define CASE_BTC_MLME_STATE(e) case MLME_##e: return #e
298 
id_to_mlme_state(u32 id)299 static const char *id_to_mlme_state(u32 id)
300 {
301 	switch (id) {
302 	CASE_BTC_MLME_STATE(NO_LINK);
303 	CASE_BTC_MLME_STATE(LINKING);
304 	CASE_BTC_MLME_STATE(LINKED);
305 	default:
306 		return "unknown";
307 	}
308 }
309 
chip_id_str(u32 id)310 static char *chip_id_str(u32 id)
311 {
312 	switch (id) {
313 	case RTL8852A:
314 		return "RTL8852A";
315 	case RTL8852B:
316 		return "RTL8852B";
317 	case RTL8852C:
318 		return "RTL8852C";
319 	case RTL8852BT:
320 		return "RTL8852BT";
321 	case RTL8851B:
322 		return "RTL8851B";
323 	case RTL8922A:
324 		return "RTL8922A";
325 	default:
326 		return "UNKNOWN";
327 	}
328 }
329 
330 struct rtw89_btc_btf_tlv {
331 	u8 type;
332 	u8 len;
333 	u8 val[];
334 } __packed;
335 
336 struct rtw89_btc_btf_tlv_v7 {
337 	u8 type;
338 	u8 ver;
339 	u8 len;
340 	u8 val[];
341 } __packed;
342 
343 enum btc_btf_set_report_en {
344 	RPT_EN_TDMA,
345 	RPT_EN_CYCLE,
346 	RPT_EN_MREG,
347 	RPT_EN_BT_VER_INFO,
348 	RPT_EN_BT_SCAN_INFO,
349 	RPT_EN_BT_DEVICE_INFO,
350 	RPT_EN_BT_AFH_MAP,
351 	RPT_EN_BT_AFH_MAP_LE,
352 	RPT_EN_BT_TX_PWR_LVL,
353 	RPT_EN_FW_STEP_INFO,
354 	RPT_EN_TEST,
355 	RPT_EN_WL_ALL,
356 	RPT_EN_BT_ALL,
357 	RPT_EN_ALL,
358 	RPT_EN_MONITER,
359 };
360 
361 struct rtw89_btc_btf_set_report_v1 {
362 	u8 fver;
363 	__le32 enable;
364 	__le32 para;
365 } __packed;
366 
367 struct rtw89_btc_btf_set_report_v8 {
368 	u8 type;
369 	u8 fver;
370 	u8 len;
371 	__le32 map;
372 } __packed;
373 
374 union rtw89_fbtc_rtp_ctrl {
375 	struct rtw89_btc_btf_set_report_v1 v1;
376 	struct rtw89_btc_btf_set_report_v8 v8;
377 };
378 
379 #define BTF_SET_SLOT_TABLE_VER 1
380 struct rtw89_btc_btf_set_slot_table {
381 	u8 fver;
382 	u8 tbl_num;
383 	struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num);
384 } __packed;
385 
386 struct rtw89_btc_btf_set_slot_table_v7 {
387 	u8 type;
388 	u8 ver;
389 	u8 len;
390 	struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX];
391 } __packed;
392 
393 struct rtw89_btc_btf_set_mon_reg_v1 {
394 	u8 fver;
395 	u8 reg_num;
396 	struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num);
397 } __packed;
398 
399 struct rtw89_btc_btf_set_mon_reg_v7 {
400 	u8 type;
401 	u8 fver;
402 	u8 len;
403 	struct rtw89_btc_fbtc_mreg regs[] __counted_by(len);
404 } __packed;
405 
406 union rtw89_fbtc_set_mon_reg {
407 	struct rtw89_btc_btf_set_mon_reg_v1 v1;
408 	struct rtw89_btc_btf_set_mon_reg_v7 v7;
409 } __packed;
410 
411 struct _wl_rinfo_now {
412 	u8 link_mode;
413 	u32 dbcc_2g_phy: 2;
414 };
415 
416 enum btc_btf_set_cx_policy {
417 	CXPOLICY_TDMA = 0x0,
418 	CXPOLICY_SLOT = 0x1,
419 	CXPOLICY_TYPE = 0x2,
420 	CXPOLICY_MAX,
421 };
422 
423 enum btc_b2w_scoreboard {
424 	BTC_BSCB_ACT = BIT(0),
425 	BTC_BSCB_ON = BIT(1),
426 	BTC_BSCB_WHQL = BIT(2),
427 	BTC_BSCB_BT_S1 = BIT(3),
428 	BTC_BSCB_A2DP_ACT = BIT(4),
429 	BTC_BSCB_RFK_RUN = BIT(5),
430 	BTC_BSCB_RFK_REQ = BIT(6),
431 	BTC_BSCB_LPS = BIT(7),
432 	BTC_BSCB_BT_LNAB0 = BIT(8),
433 	BTC_BSCB_BT_LNAB1 = BIT(10),
434 	BTC_BSCB_WLRFK = BIT(11),
435 	BTC_BSCB_BT_HILNA = BIT(13),
436 	BTC_BSCB_BT_CONNECT = BIT(16),
437 	BTC_BSCB_PATCH_CODE = BIT(30),
438 	BTC_BSCB_ALL = GENMASK(30, 0),
439 };
440 
441 enum btc_phymap {
442 	BTC_PHY_0 = BIT(0),
443 	BTC_PHY_1 = BIT(1),
444 	BTC_PHY_ALL = BIT(0) | BIT(1),
445 };
446 
447 enum btc_cx_state_map {
448 	BTC_WIDLE = 0,
449 	BTC_WBUSY_BNOSCAN,
450 	BTC_WBUSY_BSCAN,
451 	BTC_WSCAN_BNOSCAN,
452 	BTC_WSCAN_BSCAN,
453 	BTC_WLINKING
454 };
455 
456 enum btc_ant_phase {
457 	BTC_ANT_WPOWERON = 0,
458 	BTC_ANT_WINIT,
459 	BTC_ANT_WONLY,
460 	BTC_ANT_WOFF,
461 	BTC_ANT_W2G,
462 	BTC_ANT_W5G,
463 	BTC_ANT_W25G,
464 	BTC_ANT_FREERUN,
465 	BTC_ANT_WRFK,
466 	BTC_ANT_WRFK2,
467 	BTC_ANT_BRFK,
468 	BTC_ANT_MAX
469 };
470 
471 enum btc_plt {
472 	BTC_PLT_NONE = 0,
473 	BTC_PLT_LTE_RX = BIT(0),
474 	BTC_PLT_GNT_BT_TX = BIT(1),
475 	BTC_PLT_GNT_BT_RX = BIT(2),
476 	BTC_PLT_GNT_WL = BIT(3),
477 	BTC_PLT_BT = BIT(1) | BIT(2),
478 	BTC_PLT_ALL = 0xf
479 };
480 
481 enum btc_cx_poicy_main_type {
482 	BTC_CXP_OFF = 0,
483 	BTC_CXP_OFFB,
484 	BTC_CXP_OFFE,
485 	BTC_CXP_FIX,
486 	BTC_CXP_PFIX,
487 	BTC_CXP_AUTO,
488 	BTC_CXP_PAUTO,
489 	BTC_CXP_AUTO2,
490 	BTC_CXP_PAUTO2,
491 	BTC_CXP_MANUAL,
492 	BTC_CXP_USERDEF0,
493 	BTC_CXP_MAIN_MAX
494 };
495 
496 enum btc_cx_poicy_type {
497 	/* TDMA off + pri: BT > WL */
498 	BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0,
499 
500 	/* TDMA off + pri: WL > BT */
501 	BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1,
502 
503 	/* TDMA off + pri: BT = WL */
504 	BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2,
505 
506 	/* TDMA off + pri: BT = WL > BT_Lo */
507 	BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3,
508 
509 	/* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */
510 	BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4,
511 
512 	/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
513 	BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5,
514 
515 	/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
516 	BTC_CXP_OFF_EQ4 = (BTC_CXP_OFF << 8) | 6,
517 
518 	/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
519 	BTC_CXP_OFF_EQ5 = (BTC_CXP_OFF << 8) | 7,
520 
521 	/* TDMA off + pri: BT_Hi > WL > BT_Lo */
522 	BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 8,
523 
524 	/* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
525 	BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 9,
526 
527 	/* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
528 	BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 10,
529 
530 	/* TDMA off + pri: WL_Hi-Tx = BT */
531 	BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 11,
532 
533 	/* TDMA off + pri: WL > BT, Block-BT*/
534 	BTC_CXP_OFF_WL2 = (BTC_CXP_OFF << 8) | 12,
535 
536 	/* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/
537 	BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
538 
539 	/* TDMA off + Ext-Ctrl + pri: default */
540 	BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0,
541 
542 	/* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
543 	BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1,
544 
545 	/* TDMA off + Ext-Ctrl + pri: default */
546 	BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2,
547 
548 	/* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
549 	BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3,
550 
551 	/* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */
552 	BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4,
553 
554 	/* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */
555 	BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5,
556 
557 	/* TDMA off + Ext-Ctrl + pri: default */
558 	BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6,
559 
560 	/* TDMA Fix slot-0: W1:B1 = 30:30 */
561 	BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0,
562 
563 	/* TDMA Fix slot-1: W1:B1 = 50:50 */
564 	BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1,
565 
566 	/* TDMA Fix slot-2: W1:B1 = 20:30 */
567 	BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2,
568 
569 	/* TDMA Fix slot-3: W1:B1 = 40:10 */
570 	BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3,
571 
572 	/* TDMA Fix slot-4: W1:B1 = 70:10 */
573 	BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4,
574 
575 	/* TDMA Fix slot-5: W1:B1 = 20:60 */
576 	BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5,
577 
578 	/* TDMA Fix slot-6: W1:B1 = 30:60 */
579 	BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6,
580 
581 	/* TDMA Fix slot-7: W1:B1 = 20:80 */
582 	BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7,
583 
584 	/* TDMA Fix slot-8: W1:B1 = user-define */
585 	BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8,
586 
587 	/* TDMA Fix slot-9: W1:B1 = 40:10 */
588 	BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 9,
589 
590 	/* TDMA Fix slot-10: W1:B1 = 40:10 */
591 	BTC_CXP_FIX_TD4010ISO_DL = (BTC_CXP_FIX << 8) | 10,
592 
593 	/* TDMA Fix slot-11: W1:B1 = 40:10 */
594 	BTC_CXP_FIX_TD4010ISO_UL = (BTC_CXP_FIX << 8) | 11,
595 
596 	/* PS-TDMA Fix slot-0: W1:B1 = 30:30 */
597 	BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0,
598 
599 	/* PS-TDMA Fix slot-1: W1:B1 = 50:50 */
600 	BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1,
601 
602 	/* PS-TDMA Fix slot-2: W1:B1 = 20:30 */
603 	BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2,
604 
605 	/* PS-TDMA Fix slot-3: W1:B1 = 20:60 */
606 	BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3,
607 
608 	/* PS-TDMA Fix slot-4: W1:B1 = 30:70 */
609 	BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4,
610 
611 	/* PS-TDMA Fix slot-5: W1:B1 = 20:80 */
612 	BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5,
613 
614 	/* PS-TDMA Fix slot-6: W1:B1 = user-define */
615 	BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6,
616 
617 	/* TDMA Auto slot-0: W1:B1 = 50:200 */
618 	BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0,
619 
620 	/* TDMA Auto slot-1: W1:B1 = 60:200 */
621 	BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1,
622 
623 	/* TDMA Auto slot-2: W1:B1 = 20:200 */
624 	BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2,
625 
626 	/* TDMA Auto slot-3: W1:B1 = user-define */
627 	BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3,
628 
629 	/* PS-TDMA Auto slot-0: W1:B1 = 50:200 */
630 	BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0,
631 
632 	/* PS-TDMA Auto slot-1: W1:B1 = 60:200 */
633 	BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1,
634 
635 	/* PS-TDMA Auto slot-2: W1:B1 = 20:200 */
636 	BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2,
637 
638 	/* PS-TDMA Auto slot-3: W1:B1 = user-define */
639 	BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3,
640 
641 	/* TDMA Auto slot2-0: W1:B4 = 30:50 */
642 	BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0,
643 
644 	/* TDMA Auto slot2-1: W1:B4 = 30:70 */
645 	BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1,
646 
647 	/* TDMA Auto slot2-2: W1:B4 = 50:50 */
648 	BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2,
649 
650 	/* TDMA Auto slot2-3: W1:B4 = 60:60 */
651 	BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3,
652 
653 	/* TDMA Auto slot2-4: W1:B4 = 20:80 */
654 	BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4,
655 
656 	/* TDMA Auto slot2-5: W1:B4 = user-define */
657 	BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5,
658 
659 	/* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */
660 	BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0,
661 
662 	/* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */
663 	BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1,
664 
665 	/* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */
666 	BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2,
667 
668 	/* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */
669 	BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3,
670 
671 	/* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */
672 	BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4,
673 
674 	/* PS-TDMA Auto slot2-5: W1:B4 = user-define */
675 	BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5,
676 
677 	BTC_CXP_MAX = 0xffff
678 };
679 
680 enum btc_wl_rfk_result {
681 	BTC_WRFK_REJECT = 0,
682 	BTC_WRFK_ALLOW = 1,
683 };
684 
685 enum btc_coex_info_map_en {
686 	BTC_COEX_INFO_CX = BIT(0),
687 	BTC_COEX_INFO_WL = BIT(1),
688 	BTC_COEX_INFO_BT = BIT(2),
689 	BTC_COEX_INFO_DM = BIT(3),
690 	BTC_COEX_INFO_MREG = BIT(4),
691 	BTC_COEX_INFO_SUMMARY = BIT(5),
692 	BTC_COEX_INFO_ALL = GENMASK(7, 0),
693 };
694 
695 #define BTC_CXP_MASK GENMASK(15, 8)
696 
697 enum btc_w2b_scoreboard {
698 	BTC_WSCB_ACTIVE = BIT(0),
699 	BTC_WSCB_ON = BIT(1),
700 	BTC_WSCB_SCAN = BIT(2),
701 	BTC_WSCB_UNDERTEST = BIT(3),
702 	BTC_WSCB_RXGAIN = BIT(4),
703 	BTC_WSCB_WLBUSY = BIT(7),
704 	BTC_WSCB_EXTFEM = BIT(8),
705 	BTC_WSCB_TDMA = BIT(9),
706 	BTC_WSCB_FIX2M = BIT(10),
707 	BTC_WSCB_WLRFK = BIT(11),
708 	BTC_WSCB_RXSCAN_PRI = BIT(12),
709 	BTC_WSCB_BT_HILNA = BIT(13),
710 	BTC_WSCB_BTLOG = BIT(14),
711 	BTC_WSCB_ALL = GENMASK(23, 0),
712 };
713 
714 enum btc_wl_link_mode {
715 	BTC_WLINK_NOLINK = 0x0,
716 	BTC_WLINK_2G_STA,
717 	BTC_WLINK_2G_AP,
718 	BTC_WLINK_2G_GO,
719 	BTC_WLINK_2G_GC,
720 	BTC_WLINK_2G_SCC,
721 	BTC_WLINK_2G_MCC,
722 	BTC_WLINK_25G_MCC,
723 	BTC_WLINK_25G_DBCC,
724 	BTC_WLINK_5G,
725 	BTC_WLINK_2G_NAN,
726 	BTC_WLINK_OTHER,
727 	BTC_WLINK_MAX
728 };
729 
730 #define CASE_BTC_WL_LINK_MODE(e) case BTC_WLINK_## e: return #e
731 
id_to_linkmode(u8 id)732 static const char *id_to_linkmode(u8 id)
733 {
734 	switch (id) {
735 	CASE_BTC_WL_LINK_MODE(NOLINK);
736 	CASE_BTC_WL_LINK_MODE(2G_STA);
737 	CASE_BTC_WL_LINK_MODE(2G_AP);
738 	CASE_BTC_WL_LINK_MODE(2G_GO);
739 	CASE_BTC_WL_LINK_MODE(2G_GC);
740 	CASE_BTC_WL_LINK_MODE(2G_SCC);
741 	CASE_BTC_WL_LINK_MODE(2G_MCC);
742 	CASE_BTC_WL_LINK_MODE(25G_MCC);
743 	CASE_BTC_WL_LINK_MODE(25G_DBCC);
744 	CASE_BTC_WL_LINK_MODE(5G);
745 	CASE_BTC_WL_LINK_MODE(OTHER);
746 	default:
747 		return "unknown";
748 	}
749 }
750 
751 enum btc_wl_mrole_type {
752 	BTC_WLMROLE_NONE = 0x0,
753 	BTC_WLMROLE_STA_GC,
754 	BTC_WLMROLE_STA_GC_NOA,
755 	BTC_WLMROLE_STA_GO,
756 	BTC_WLMROLE_STA_GO_NOA,
757 	BTC_WLMROLE_STA_STA,
758 	BTC_WLMROLE_MAX
759 };
760 
761 enum btc_bt_hid_type {
762 	BTC_HID_218 = BIT(0),
763 	BTC_HID_418 = BIT(1),
764 	BTC_HID_BLE = BIT(2),
765 	BTC_HID_RCU = BIT(3),
766 	BTC_HID_RCU_VOICE = BIT(4),
767 	BTC_HID_OTHER_LEGACY = BIT(5)
768 };
769 
770 enum btc_reset_module {
771 	BTC_RESET_CX = BIT(0),
772 	BTC_RESET_DM = BIT(1),
773 	BTC_RESET_CTRL = BIT(2),
774 	BTC_RESET_CXDM = BIT(0) | BIT(1),
775 	BTC_RESET_BTINFO = BIT(3),
776 	BTC_RESET_MDINFO = BIT(4),
777 	BTC_RESET_ALL =  GENMASK(7, 0),
778 };
779 
780 enum btc_gnt_state {
781 	BTC_GNT_HW	= 0,
782 	BTC_GNT_SW_LO,
783 	BTC_GNT_SW_HI,
784 	BTC_GNT_MAX
785 };
786 
787 enum btc_ctr_path {
788 	BTC_CTRL_BY_BT = 0,
789 	BTC_CTRL_BY_WL
790 };
791 
792 enum btc_wlact_state {
793 	BTC_WLACT_HW = 0,
794 	BTC_WLACT_SW_LO,
795 	BTC_WLACT_SW_HI,
796 	BTC_WLACT_MAX,
797 };
798 
799 enum btc_wl_max_tx_time {
800 	BTC_MAX_TX_TIME_L1 = 500,
801 	BTC_MAX_TX_TIME_L2 = 1000,
802 	BTC_MAX_TX_TIME_L3 = 2000,
803 	BTC_MAX_TX_TIME_DEF = 5280
804 };
805 
806 enum btc_wl_max_tx_retry {
807 	BTC_MAX_TX_RETRY_L1 = 7,
808 	BTC_MAX_TX_RETRY_L2 = 15,
809 	BTC_MAX_TX_RETRY_DEF = 31,
810 };
811 
812 enum btc_reason_and_action {
813 	BTC_RSN_NONE,
814 	BTC_RSN_NTFY_INIT,
815 	BTC_RSN_NTFY_SWBAND,
816 	BTC_RSN_NTFY_WL_STA,
817 	BTC_RSN_NTFY_RADIO_STATE,
818 	BTC_RSN_UPDATE_BT_SCBD,
819 	BTC_RSN_NTFY_WL_RFK,
820 	BTC_RSN_UPDATE_BT_INFO,
821 	BTC_RSN_NTFY_SCAN_START,
822 	BTC_RSN_NTFY_SCAN_FINISH,
823 	BTC_RSN_NTFY_SPECIFIC_PACKET,
824 	BTC_RSN_NTFY_POWEROFF,
825 	BTC_RSN_NTFY_ROLE_INFO,
826 	BTC_RSN_CMD_SET_COEX,
827 	BTC_RSN_ACT1_WORK,
828 	BTC_RSN_BT_DEVINFO_WORK,
829 	BTC_RSN_RFK_CHK_WORK,
830 	BTC_RSN_NUM,
831 	BTC_ACT_NONE = 100,
832 	BTC_ACT_WL_ONLY,
833 	BTC_ACT_WL_5G,
834 	BTC_ACT_WL_OTHER,
835 	BTC_ACT_WL_IDLE,
836 	BTC_ACT_WL_NC,
837 	BTC_ACT_WL_RFK,
838 	BTC_ACT_WL_INIT,
839 	BTC_ACT_WL_OFF,
840 	BTC_ACT_FREERUN,
841 	BTC_ACT_BT_WHQL,
842 	BTC_ACT_BT_RFK,
843 	BTC_ACT_BT_OFF,
844 	BTC_ACT_BT_IDLE,
845 	BTC_ACT_BT_HFP,
846 	BTC_ACT_BT_HID,
847 	BTC_ACT_BT_A2DP,
848 	BTC_ACT_BT_A2DPSINK,
849 	BTC_ACT_BT_PAN,
850 	BTC_ACT_BT_A2DP_HID,
851 	BTC_ACT_BT_A2DP_PAN,
852 	BTC_ACT_BT_PAN_HID,
853 	BTC_ACT_BT_A2DP_PAN_HID,
854 	BTC_ACT_WL_25G_MCC,
855 	BTC_ACT_WL_2G_MCC,
856 	BTC_ACT_WL_2G_SCC,
857 	BTC_ACT_WL_2G_AP,
858 	BTC_ACT_WL_2G_GO,
859 	BTC_ACT_WL_2G_GC,
860 	BTC_ACT_WL_2G_NAN,
861 	BTC_ACT_LAST,
862 	BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE,
863 	BTC_ACT_EXT_BIT = BIT(14),
864 	BTC_POLICY_EXT_BIT = BIT(15),
865 };
866 
867 #define BTC_FREERUN_ANTISO_MIN 30
868 #define BTC_TDMA_BTHID_MAX 2
869 #define BTC_BLINK_NOCONNECT 0
870 #define BTC_B1_MAX 250 /* unit ms */
871 
872 static void _run_coex(struct rtw89_dev *rtwdev,
873 		      enum btc_reason_and_action reason);
874 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state);
875 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update);
876 
_send_fw_cmd(struct rtw89_dev * rtwdev,u8 h2c_class,u8 h2c_func,void * param,u16 len)877 static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func,
878 			void *param, u16 len)
879 {
880 	struct rtw89_btc *btc = &rtwdev->btc;
881 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
882 	struct rtw89_btc_cx *cx = &btc->cx;
883 	struct rtw89_btc_wl_info *wl = &cx->wl;
884 	struct rtw89_btc_dm *dm = &btc->dm;
885 	int ret;
886 
887 	if (len > BTC_H2C_MAXLEN || len == 0) {
888 		btc->fwinfo.cnt_h2c_fail++;
889 		dm->error.map.h2c_buffer_over = true;
890 		return -EINVAL;
891 	} else if (!wl->status.map.init_ok) {
892 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
893 			    "[BTC], %s(): return by btc not init!!\n", __func__);
894 		pfwinfo->cnt_h2c_fail++;
895 		return -EINVAL;
896 	} else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF &&
897 		    wl->status.map.rf_off == BTC_LPS_RF_OFF) ||
898 		   (wl->status.map.lps_pre == BTC_LPS_RF_OFF &&
899 		    wl->status.map.lps == BTC_LPS_RF_OFF)) {
900 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
901 			    "[BTC], %s(): return by wl off!!\n", __func__);
902 		pfwinfo->cnt_h2c_fail++;
903 		return -EINVAL;
904 	}
905 
906 	ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, param, len,
907 					false, true);
908 	if (ret)
909 		pfwinfo->cnt_h2c_fail++;
910 	else
911 		pfwinfo->cnt_h2c++;
912 
913 	return ret;
914 }
915 
916 #define BTC_BT_DEF_BR_TX_PWR 4
917 #define BTC_BT_DEF_LE_TX_PWR 4
918 
_reset_btc_var(struct rtw89_dev * rtwdev,u8 type)919 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
920 {
921 	struct rtw89_btc *btc = &rtwdev->btc;
922 	const struct rtw89_btc_ver *ver = btc->ver;
923 	struct rtw89_btc_cx *cx = &btc->cx;
924 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
925 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
926 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
927 	struct rtw89_btc_wl_link_info *wl_linfo;
928 	u8 i;
929 
930 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
931 
932 	if (type & BTC_RESET_CX)
933 		memset(cx, 0, sizeof(*cx));
934 
935 	if (type & BTC_RESET_BTINFO) /* only for BT enable */
936 		memset(bt, 0, sizeof(*bt));
937 
938 	if (type & BTC_RESET_CTRL) {
939 		memset(&btc->ctrl, 0, sizeof(btc->ctrl));
940 		btc->manual_ctrl = false;
941 		if (ver->fcxctrl != 7)
942 			btc->ctrl.ctrl.trace_step = FCXDEF_STEP;
943 	}
944 
945 	/* Init Coex variables that are not zero */
946 	if (type & BTC_RESET_DM) {
947 		memset(&btc->dm, 0, sizeof(btc->dm));
948 		memset(bt_linfo->rssi_state, 0, sizeof(bt_linfo->rssi_state));
949 		for (i = 0; i < RTW89_PORT_NUM; i++) {
950 			if (btc->ver->fwlrole == 8)
951 				wl_linfo = &wl->rlink_info[i][0];
952 			else
953 				wl_linfo = &wl->link_info[i];
954 			memset(wl_linfo->rssi_state, 0, sizeof(wl_linfo->rssi_state));
955 		}
956 
957 		/* set the slot_now table to original */
958 		btc->dm.tdma_now = t_def[CXTD_OFF];
959 		btc->dm.tdma = t_def[CXTD_OFF];
960 		if (ver->fcxslots >= 7) {
961 			for (i = 0; i < ARRAY_SIZE(s_def); i++) {
962 				btc->dm.slot.v7[i].dur = s_def[i].dur;
963 				btc->dm.slot.v7[i].cxtype = s_def[i].cxtype;
964 				btc->dm.slot.v7[i].cxtbl = s_def[i].cxtbl;
965 			}
966 			memcpy(&btc->dm.slot_now.v7, &btc->dm.slot.v7,
967 			       sizeof(btc->dm.slot_now.v7));
968 		} else {
969 			memcpy(&btc->dm.slot_now.v1, s_def,
970 			       sizeof(btc->dm.slot_now.v1));
971 			memcpy(&btc->dm.slot.v1, s_def,
972 			       sizeof(btc->dm.slot.v1));
973 		}
974 
975 		btc->policy_len = 0;
976 		btc->bt_req_len = 0;
977 
978 		btc->dm.coex_info_map = BTC_COEX_INFO_ALL;
979 		btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF;
980 		btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF;
981 		btc->dm.wl_pre_agc_rb = BTC_PREAGC_NOTFOUND;
982 		btc->dm.wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_NOTFOUND;
983 	}
984 
985 	if (type & BTC_RESET_MDINFO)
986 		memset(&btc->mdinfo, 0, sizeof(btc->mdinfo));
987 
988 	bt->link_info.bt_txpwr_desc.br_dbm = BTC_BT_DEF_BR_TX_PWR;
989 	bt->link_info.bt_txpwr_desc.le_dbm = BTC_BT_DEF_LE_TX_PWR;
990 }
991 
_search_reg_index(struct rtw89_dev * rtwdev,u8 mreg_num,u16 reg_type,u32 target)992 static u8 _search_reg_index(struct rtw89_dev *rtwdev, u8 mreg_num, u16 reg_type, u32 target)
993 {
994 	const struct rtw89_chip_info *chip = rtwdev->chip;
995 	u8 i;
996 
997 	for (i = 0; i < mreg_num; i++)
998 		if (le16_to_cpu(chip->mon_reg[i].type) == reg_type &&
999 		    le32_to_cpu(chip->mon_reg[i].offset) == target) {
1000 			return i;
1001 	}
1002 	return BTC_REG_NOTFOUND;
1003 }
1004 
_get_reg_status(struct rtw89_dev * rtwdev,u8 type,u8 * val)1005 static void _get_reg_status(struct rtw89_dev *rtwdev, u8 type, u8 *val)
1006 {
1007 	struct rtw89_btc *btc = &rtwdev->btc;
1008 	const struct rtw89_btc_ver *ver = btc->ver;
1009 	union rtw89_btc_module_info *md = &btc->mdinfo;
1010 	union rtw89_btc_fbtc_mreg_val *pmreg;
1011 	u32 pre_agc_addr = R_BTC_BB_PRE_AGC_S1;
1012 	u32 reg_val;
1013 	u8 idx, switch_type;
1014 
1015 	if (ver->fcxinit == 7)
1016 		switch_type = md->md_v7.switch_type;
1017 	else
1018 		switch_type = md->md.switch_type;
1019 
1020 	if (btc->btg_pos == RF_PATH_A)
1021 		pre_agc_addr = R_BTC_BB_PRE_AGC_S0;
1022 
1023 	switch (type) {
1024 	case BTC_CSTATUS_TXDIV_POS:
1025 		if (switch_type == BTC_SWITCH_INTERNAL)
1026 			*val = BTC_ANT_DIV_MAIN;
1027 		break;
1028 	case BTC_CSTATUS_RXDIV_POS:
1029 		if (switch_type == BTC_SWITCH_INTERNAL)
1030 			*val = BTC_ANT_DIV_MAIN;
1031 		break;
1032 	case BTC_CSTATUS_BB_GNT_MUX:
1033 		reg_val = rtw89_phy_read32(rtwdev, R_BTC_BB_BTG_RX);
1034 		*val = !(reg_val & B_BTC_BB_GNT_MUX);
1035 		break;
1036 	case BTC_CSTATUS_BB_GNT_MUX_MON:
1037 		if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
1038 			return;
1039 
1040 		pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
1041 		if (ver->fcxmreg == 1) {
1042 			idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
1043 						REG_BB, R_BTC_BB_BTG_RX);
1044 			if (idx == BTC_REG_NOTFOUND) {
1045 				*val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
1046 			} else {
1047 				reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]);
1048 				*val = !(reg_val & B_BTC_BB_GNT_MUX);
1049 			}
1050 		} else if (ver->fcxmreg == 2) {
1051 			idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
1052 						REG_BB, R_BTC_BB_BTG_RX);
1053 			if (idx == BTC_REG_NOTFOUND) {
1054 				*val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
1055 			} else {
1056 				reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]);
1057 				*val = !(reg_val & B_BTC_BB_GNT_MUX);
1058 			}
1059 		}
1060 		break;
1061 	case BTC_CSTATUS_BB_PRE_AGC:
1062 		reg_val = rtw89_phy_read32(rtwdev, pre_agc_addr);
1063 		reg_val &= B_BTC_BB_PRE_AGC_MASK;
1064 		*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1065 		break;
1066 	case BTC_CSTATUS_BB_PRE_AGC_MON:
1067 		if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
1068 			return;
1069 
1070 		pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
1071 		if (ver->fcxmreg == 1) {
1072 			idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
1073 						REG_BB, pre_agc_addr);
1074 			if (idx == BTC_REG_NOTFOUND) {
1075 				*val = BTC_PREAGC_NOTFOUND;
1076 			} else {
1077 				reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]) &
1078 					  B_BTC_BB_PRE_AGC_MASK;
1079 				*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1080 			}
1081 		} else if (ver->fcxmreg == 2) {
1082 			idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
1083 						REG_BB, pre_agc_addr);
1084 			if (idx == BTC_REG_NOTFOUND) {
1085 				*val = BTC_PREAGC_NOTFOUND;
1086 			} else {
1087 				reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]) &
1088 					  B_BTC_BB_PRE_AGC_MASK;
1089 				*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1090 			}
1091 		}
1092 		break;
1093 	default:
1094 		break;
1095 	}
1096 }
1097 
1098 #define BTC_RPT_HDR_SIZE 3
1099 #define BTC_CHK_WLSLOT_DRIFT_MAX 15
1100 #define BTC_CHK_BTSLOT_DRIFT_MAX 15
1101 #define BTC_CHK_HANG_MAX 3
1102 
_chk_btc_err(struct rtw89_dev * rtwdev,u8 type,u32 cnt)1103 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt)
1104 {
1105 	struct rtw89_btc *btc = &rtwdev->btc;
1106 	struct rtw89_btc_cx *cx = &btc->cx;
1107 	struct rtw89_btc_bt_info *bt = &cx->bt;
1108 	struct rtw89_btc_wl_info *wl = &cx->wl;
1109 	struct rtw89_btc_dm *dm = &btc->dm;
1110 
1111 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
1112 		    "[BTC], %s(): type:%d cnt:%d\n",
1113 		    __func__, type, cnt);
1114 
1115 	switch (type) {
1116 	case BTC_DCNT_WL_FW_VER_MATCH:
1117 		if ((wl->ver_info.fw_coex & 0xffff0000) !=
1118 		     rtwdev->chip->wlcx_desired) {
1119 			wl->fw_ver_mismatch = true;
1120 			dm->error.map.wl_ver_mismatch = true;
1121 		} else {
1122 			wl->fw_ver_mismatch = false;
1123 			dm->error.map.wl_ver_mismatch = false;
1124 		}
1125 		break;
1126 	case BTC_DCNT_RPT_HANG:
1127 		if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map)
1128 			dm->cnt_dm[BTC_DCNT_RPT_HANG]++;
1129 		else
1130 			dm->cnt_dm[BTC_DCNT_RPT_HANG] = 0;
1131 
1132 		if (dm->cnt_dm[BTC_DCNT_RPT_HANG] >= BTC_CHK_HANG_MAX)
1133 			dm->error.map.wl_fw_hang = true;
1134 		else
1135 			dm->error.map.wl_fw_hang = false;
1136 
1137 		dm->cnt_dm[BTC_DCNT_RPT] = cnt;
1138 		break;
1139 	case BTC_DCNT_CYCLE_HANG:
1140 		if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt &&
1141 		    (dm->tdma_now.type != CXTDMA_OFF ||
1142 		     dm->tdma_now.ext_ctrl == CXECTL_EXT))
1143 			dm->cnt_dm[BTC_DCNT_CYCLE_HANG]++;
1144 		else
1145 			dm->cnt_dm[BTC_DCNT_CYCLE_HANG] = 0;
1146 
1147 		if (dm->cnt_dm[BTC_DCNT_CYCLE_HANG] >= BTC_CHK_HANG_MAX)
1148 			dm->error.map.cycle_hang = true;
1149 		else
1150 			dm->error.map.cycle_hang = false;
1151 
1152 		dm->cnt_dm[BTC_DCNT_CYCLE] = cnt;
1153 		break;
1154 	case BTC_DCNT_W1_HANG:
1155 		if (dm->cnt_dm[BTC_DCNT_W1] == cnt &&
1156 		    dm->tdma_now.type != CXTDMA_OFF)
1157 			dm->cnt_dm[BTC_DCNT_W1_HANG]++;
1158 		else
1159 			dm->cnt_dm[BTC_DCNT_W1_HANG] = 0;
1160 
1161 		if (dm->cnt_dm[BTC_DCNT_W1_HANG] >= BTC_CHK_HANG_MAX)
1162 			dm->error.map.w1_hang = true;
1163 		else
1164 			dm->error.map.w1_hang = false;
1165 
1166 		dm->cnt_dm[BTC_DCNT_W1] = cnt;
1167 		break;
1168 	case BTC_DCNT_B1_HANG:
1169 		if (dm->cnt_dm[BTC_DCNT_B1] == cnt &&
1170 		    dm->tdma_now.type != CXTDMA_OFF)
1171 			dm->cnt_dm[BTC_DCNT_B1_HANG]++;
1172 		else
1173 			dm->cnt_dm[BTC_DCNT_B1_HANG] = 0;
1174 
1175 		if (dm->cnt_dm[BTC_DCNT_B1_HANG] >= BTC_CHK_HANG_MAX)
1176 			dm->error.map.b1_hang = true;
1177 		else
1178 			dm->error.map.b1_hang = false;
1179 
1180 		dm->cnt_dm[BTC_DCNT_B1] = cnt;
1181 		break;
1182 	case BTC_DCNT_E2G_HANG:
1183 		if (dm->cnt_dm[BTC_DCNT_E2G] == cnt &&
1184 		    dm->tdma_now.ext_ctrl == CXECTL_EXT)
1185 			dm->cnt_dm[BTC_DCNT_E2G_HANG]++;
1186 		else
1187 			dm->cnt_dm[BTC_DCNT_E2G_HANG] = 0;
1188 
1189 		if (dm->cnt_dm[BTC_DCNT_E2G_HANG] >= BTC_CHK_HANG_MAX)
1190 			dm->error.map.wl_e2g_hang = true;
1191 		else
1192 			dm->error.map.wl_e2g_hang = false;
1193 
1194 		dm->cnt_dm[BTC_DCNT_E2G] = cnt;
1195 		break;
1196 	case BTC_DCNT_TDMA_NONSYNC:
1197 		if (cnt != 0) /* if tdma not sync between drv/fw  */
1198 			dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++;
1199 		else
1200 			dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0;
1201 
1202 		if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX)
1203 			dm->error.map.tdma_no_sync = true;
1204 		else
1205 			dm->error.map.tdma_no_sync = false;
1206 		break;
1207 	case BTC_DCNT_SLOT_NONSYNC:
1208 		if (cnt != 0) /* if slot not sync between drv/fw  */
1209 			dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++;
1210 		else
1211 			dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0;
1212 
1213 		if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX)
1214 			dm->error.map.slot_no_sync = true;
1215 		else
1216 			dm->error.map.slot_no_sync = false;
1217 		break;
1218 	case BTC_DCNT_BTTX_HANG:
1219 		cnt = cx->cnt_bt[BTC_BCNT_LOPRI_TX];
1220 
1221 		if (cnt == 0 && bt->link_info.slave_role)
1222 			dm->cnt_dm[BTC_DCNT_BTTX_HANG]++;
1223 		else
1224 			dm->cnt_dm[BTC_DCNT_BTTX_HANG] = 0;
1225 
1226 		if (dm->cnt_dm[BTC_DCNT_BTTX_HANG] >= BTC_CHK_HANG_MAX)
1227 			dm->error.map.bt_tx_hang = true;
1228 		else
1229 			dm->error.map.bt_tx_hang = false;
1230 		break;
1231 	case BTC_DCNT_BTCNT_HANG:
1232 		cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] +
1233 		      cx->cnt_bt[BTC_BCNT_HIPRI_TX] +
1234 		      cx->cnt_bt[BTC_BCNT_LOPRI_RX] +
1235 		      cx->cnt_bt[BTC_BCNT_LOPRI_TX];
1236 
1237 		if (cnt == 0)
1238 			dm->cnt_dm[BTC_DCNT_BTCNT_HANG]++;
1239 		else
1240 			dm->cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
1241 
1242 		if ((dm->cnt_dm[BTC_DCNT_BTCNT_HANG] >= BTC_CHK_HANG_MAX &&
1243 		     bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_HANG] &&
1244 		     !bt->enable.now))
1245 			_update_bt_scbd(rtwdev, false);
1246 		break;
1247 	case BTC_DCNT_WL_SLOT_DRIFT:
1248 		if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX)
1249 			dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++;
1250 		else
1251 			dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0;
1252 
1253 		if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1254 			dm->error.map.wl_slot_drift = true;
1255 		else
1256 			dm->error.map.wl_slot_drift = false;
1257 		break;
1258 	case BTC_DCNT_BT_SLOT_DRIFT:
1259 		if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX)
1260 			dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++;
1261 		else
1262 			dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0;
1263 
1264 		if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1265 			dm->error.map.bt_slot_drift = true;
1266 		else
1267 			dm->error.map.bt_slot_drift = false;
1268 
1269 		break;
1270 	}
1271 }
1272 
_update_bt_report(struct rtw89_dev * rtwdev,u8 rpt_type,u8 * pfinfo)1273 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo)
1274 {
1275 	struct rtw89_btc *btc = &rtwdev->btc;
1276 	const struct rtw89_btc_ver *ver = btc->ver;
1277 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1278 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
1279 	struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc;
1280 	union  rtw89_btc_fbtc_btver *pver = &btc->fwinfo.rpt_fbtc_btver.finfo;
1281 	struct rtw89_btc_fbtc_btafh_v2 *pafh_v2 = NULL;
1282 	struct rtw89_btc_fbtc_btafh_v7 *pafh_v7 = NULL;
1283 	struct rtw89_btc_fbtc_btdevinfo *pdev = NULL;
1284 	struct rtw89_btc_fbtc_btafh *pafh_v1 = NULL;
1285 	struct rtw89_btc_fbtc_btscan_v1 *pscan_v1;
1286 	struct rtw89_btc_fbtc_btscan_v2 *pscan_v2;
1287 	struct rtw89_btc_fbtc_btscan_v7 *pscan_v7;
1288 	bool scan_update = true;
1289 	int i;
1290 
1291 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
1292 		    "[BTC], %s(): rpt_type:%d\n",
1293 		    __func__, rpt_type);
1294 
1295 	switch (rpt_type) {
1296 	case BTC_RPT_TYPE_BT_VER:
1297 		if (ver->fcxbtver == 7) {
1298 			pver->v7 = *(struct rtw89_btc_fbtc_btver_v7 *)pfinfo;
1299 			bt->ver_info.fw = le32_to_cpu(pver->v7.fw_ver);
1300 			bt->ver_info.fw_coex = le32_get_bits(pver->v7.coex_ver,
1301 							     GENMASK(7, 0));
1302 			bt->feature = le32_to_cpu(pver->v7.feature);
1303 		} else {
1304 			pver->v1 = *(struct rtw89_btc_fbtc_btver_v1 *)pfinfo;
1305 			bt->ver_info.fw = le32_to_cpu(pver->v1.fw_ver);
1306 			bt->ver_info.fw_coex = le32_get_bits(pver->v1.coex_ver,
1307 							     GENMASK(7, 0));
1308 			bt->feature = le32_to_cpu(pver->v1.feature);
1309 		}
1310 		break;
1311 	case BTC_RPT_TYPE_BT_SCAN:
1312 		if (ver->fcxbtscan == 1) {
1313 			pscan_v1 = (struct rtw89_btc_fbtc_btscan_v1 *)pfinfo;
1314 			for (i = 0; i < BTC_SCAN_MAX1; i++) {
1315 				bt->scan_info_v1[i] = pscan_v1->scan[i];
1316 				if (bt->scan_info_v1[i].win == 0 &&
1317 				    bt->scan_info_v1[i].intvl == 0)
1318 					scan_update = false;
1319 			}
1320 		} else if (ver->fcxbtscan == 2) {
1321 			pscan_v2 = (struct rtw89_btc_fbtc_btscan_v2 *)pfinfo;
1322 			for (i = 0; i < CXSCAN_MAX; i++) {
1323 				bt->scan_info_v2[i] = pscan_v2->para[i];
1324 				if ((pscan_v2->type & BIT(i)) &&
1325 				    pscan_v2->para[i].win == 0 &&
1326 				    pscan_v2->para[i].intvl == 0)
1327 					scan_update = false;
1328 			}
1329 		} else if (ver->fcxbtscan == 7) {
1330 			pscan_v7 = (struct rtw89_btc_fbtc_btscan_v7 *)pfinfo;
1331 			for (i = 0; i < CXSCAN_MAX; i++) {
1332 				bt->scan_info_v2[i] = pscan_v7->para[i];
1333 				if ((pscan_v7->type & BIT(i)) &&
1334 				    pscan_v7->para[i].win == 0 &&
1335 				    pscan_v7->para[i].intvl == 0)
1336 					scan_update = false;
1337 			}
1338 		}
1339 		if (scan_update)
1340 			bt->scan_info_update = 1;
1341 		break;
1342 	case BTC_RPT_TYPE_BT_AFH:
1343 		if (ver->fcxbtafh == 2) {
1344 			pafh_v2 = (struct rtw89_btc_fbtc_btafh_v2 *)pfinfo;
1345 			if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1346 				memcpy(&bt_linfo->afh_map[0], pafh_v2->afh_l, 4);
1347 				memcpy(&bt_linfo->afh_map[4], pafh_v2->afh_m, 4);
1348 				memcpy(&bt_linfo->afh_map[8], pafh_v2->afh_h, 2);
1349 			}
1350 			if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LE) {
1351 				memcpy(&bt_linfo->afh_map_le[0], pafh_v2->afh_le_a, 4);
1352 				memcpy(&bt_linfo->afh_map_le[4], pafh_v2->afh_le_b, 1);
1353 			}
1354 		} else if (ver->fcxbtafh == 7) {
1355 			pafh_v7 = (struct rtw89_btc_fbtc_btafh_v7 *)pfinfo;
1356 			if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1357 				memcpy(&bt_linfo->afh_map[0], pafh_v7->afh_l, 4);
1358 				memcpy(&bt_linfo->afh_map[4], pafh_v7->afh_m, 4);
1359 				memcpy(&bt_linfo->afh_map[8], pafh_v7->afh_h, 2);
1360 			}
1361 			if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LE) {
1362 				memcpy(&bt_linfo->afh_map_le[0], pafh_v7->afh_le_a, 4);
1363 				memcpy(&bt_linfo->afh_map_le[4], pafh_v7->afh_le_b, 1);
1364 			}
1365 		} else if (ver->fcxbtafh == 1) {
1366 			pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo;
1367 			memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4);
1368 			memcpy(&bt_linfo->afh_map[4], pafh_v1->afh_m, 4);
1369 			memcpy(&bt_linfo->afh_map[8], pafh_v1->afh_h, 2);
1370 		}
1371 		break;
1372 	case BTC_RPT_TYPE_BT_DEVICE:
1373 		pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo;
1374 		a2dp->device_name = le32_to_cpu(pdev->dev_name);
1375 		a2dp->vendor_id = le16_to_cpu(pdev->vendor_id);
1376 		a2dp->flush_time = le32_to_cpu(pdev->flush_time);
1377 		break;
1378 	default:
1379 		break;
1380 	}
1381 }
1382 
rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev * rtwdev,u8 * index)1383 static void rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev *rtwdev, u8 *index)
1384 {
1385 	struct rtw89_btc *btc = &rtwdev->btc;
1386 	const struct rtw89_btc_ver *ver = btc->ver;
1387 
1388 	if (ver->fwevntrptl == 1)
1389 		return;
1390 
1391 	if (*index <= __BTC_RPT_TYPE_V0_SAME)
1392 		return;
1393 	else if (*index <= __BTC_RPT_TYPE_V0_MAX)
1394 		(*index)++;
1395 	else
1396 		*index = BTC_RPT_TYPE_MAX;
1397 }
1398 
1399 #define BTC_LEAK_AP_TH 10
1400 #define BTC_CYSTA_CHK_PERIOD 100
1401 
1402 struct rtw89_btc_prpt {
1403 	u8 type;
1404 	__le16 len;
1405 	u8 content[];
1406 } __packed;
1407 
_chk_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * prptbuf,u32 index)1408 static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
1409 			   struct rtw89_btc_btf_fwinfo *pfwinfo,
1410 			   u8 *prptbuf, u32 index)
1411 {
1412 	struct rtw89_btc *btc = &rtwdev->btc;
1413 	struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver;
1414 	const struct rtw89_btc_ver *ver = btc->ver;
1415 	struct rtw89_btc_dm *dm = &btc->dm;
1416 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
1417 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1418 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1419 	union rtw89_btc_fbtc_rpt_ctrl_ver_info *prpt = NULL;
1420 	union rtw89_btc_fbtc_cysta_info *pcysta = NULL;
1421 	struct rtw89_btc_prpt *btc_prpt = NULL;
1422 	void *rpt_content = NULL, *pfinfo = NULL;
1423 	u8 rpt_type = 0;
1424 	u16 wl_slot_set = 0, wl_slot_real = 0, val16;
1425 	u32 trace_step = 0, rpt_len = 0, diff_t = 0;
1426 	u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr;
1427 	u8 i, val = 0, val1, val2;
1428 
1429 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
1430 		    "[BTC], %s(): index:%d\n",
1431 		    __func__, index);
1432 
1433 	if (!prptbuf) {
1434 		pfwinfo->err[BTFRE_INVALID_INPUT]++;
1435 		return 0;
1436 	}
1437 
1438 	btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index];
1439 	rpt_type = btc_prpt->type;
1440 	rpt_len = le16_to_cpu(btc_prpt->len);
1441 	rpt_content = btc_prpt->content;
1442 
1443 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
1444 		    "[BTC], %s(): rpt_type:%d\n",
1445 		    __func__, rpt_type);
1446 
1447 	rtw89_btc_fw_rpt_evnt_ver(rtwdev, &rpt_type);
1448 
1449 	switch (rpt_type) {
1450 	case BTC_RPT_TYPE_CTRL:
1451 		pcinfo = &pfwinfo->rpt_ctrl.cinfo;
1452 		prpt = &pfwinfo->rpt_ctrl.finfo;
1453 		if (ver->fcxbtcrpt == 1) {
1454 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v1;
1455 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v1);
1456 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v1.fver;
1457 		} else if (ver->fcxbtcrpt == 4) {
1458 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v4;
1459 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v4);
1460 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v4.fver;
1461 		} else if (ver->fcxbtcrpt == 5) {
1462 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v5;
1463 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v5);
1464 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v5.fver;
1465 		} else if (ver->fcxbtcrpt == 105) {
1466 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v105;
1467 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v105);
1468 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v105.fver;
1469 			pcinfo->req_fver = 5;
1470 			break;
1471 		} else if (ver->fcxbtcrpt == 8) {
1472 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v8;
1473 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8);
1474 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v8.fver;
1475 		} else if (ver->fcxbtcrpt == 7) {
1476 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v7;
1477 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v7);
1478 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v7.fver;
1479 		} else {
1480 			goto err;
1481 		}
1482 		pcinfo->req_fver = ver->fcxbtcrpt;
1483 		break;
1484 	case BTC_RPT_TYPE_TDMA:
1485 		pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
1486 		if (ver->fcxtdma == 1) {
1487 			pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
1488 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1);
1489 			fwsubver->fcxtdma = 0;
1490 		} else if (ver->fcxtdma == 3 || ver->fcxtdma == 7) {
1491 			pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3;
1492 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3);
1493 			fwsubver->fcxtdma = pfwinfo->rpt_fbtc_tdma.finfo.v3.fver;
1494 		} else {
1495 			goto err;
1496 		}
1497 		pcinfo->req_fver = ver->fcxtdma;
1498 		break;
1499 	case BTC_RPT_TYPE_SLOT:
1500 		pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
1501 		if (ver->fcxslots == 1) {
1502 			pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1;
1503 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v1);
1504 			fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v1.fver;
1505 		} else if (ver->fcxslots == 7) {
1506 			pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7;
1507 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v7);
1508 			fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v7.fver;
1509 		} else {
1510 			goto err;
1511 		}
1512 		pcinfo->req_fver = ver->fcxslots;
1513 		break;
1514 	case BTC_RPT_TYPE_CYSTA:
1515 		pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
1516 		pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
1517 		if (ver->fcxcysta == 2) {
1518 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
1519 			pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
1520 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v2);
1521 			fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v2.fver;
1522 		} else if (ver->fcxcysta == 3) {
1523 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
1524 			pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
1525 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v3);
1526 			fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v3.fver;
1527 		} else if (ver->fcxcysta == 4) {
1528 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
1529 			pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
1530 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v4);
1531 			fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v4.fver;
1532 		} else if (ver->fcxcysta == 5) {
1533 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
1534 			pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
1535 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v5);
1536 			fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v5.fver;
1537 		} else if (ver->fcxcysta == 7) {
1538 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
1539 			pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
1540 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v7);
1541 			fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v7.fver;
1542 		} else {
1543 			goto err;
1544 		}
1545 		pcinfo->req_fver = ver->fcxcysta;
1546 		break;
1547 	case BTC_RPT_TYPE_STEP:
1548 		pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
1549 		if (ver->fcxctrl != 7)
1550 			trace_step = btc->ctrl.ctrl.trace_step;
1551 
1552 		if (ver->fcxstep == 2) {
1553 			pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v2;
1554 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) *
1555 					  trace_step +
1556 					  offsetof(struct rtw89_btc_fbtc_steps_v2, step);
1557 			fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v2.fver;
1558 		} else if (ver->fcxstep == 3) {
1559 			pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3;
1560 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) *
1561 					  trace_step +
1562 					  offsetof(struct rtw89_btc_fbtc_steps_v3, step);
1563 			fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v3.fver;
1564 		} else {
1565 			goto err;
1566 		}
1567 		pcinfo->req_fver = ver->fcxstep;
1568 		break;
1569 	case BTC_RPT_TYPE_NULLSTA:
1570 		pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
1571 		if (ver->fcxnullsta == 1) {
1572 			pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1;
1573 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v1);
1574 			fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v1.fver;
1575 		} else if (ver->fcxnullsta == 2) {
1576 			pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2;
1577 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v2);
1578 			fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v2.fver;
1579 		} else if (ver->fcxnullsta == 7) {
1580 			pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v7;
1581 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v7);
1582 			fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v7.fver;
1583 		} else {
1584 			goto err;
1585 		}
1586 		pcinfo->req_fver = ver->fcxnullsta;
1587 		break;
1588 	case BTC_RPT_TYPE_MREG:
1589 		pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
1590 		if (ver->fcxmreg == 1) {
1591 			pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
1592 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v1);
1593 			fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v1.fver;
1594 		} else if (ver->fcxmreg == 2) {
1595 			pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
1596 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v2);
1597 			fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v2.fver;
1598 		} else if (ver->fcxmreg == 7) {
1599 			pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
1600 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v7);
1601 			fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v7.fver;
1602 		} else {
1603 			goto err;
1604 		}
1605 		pcinfo->req_fver = ver->fcxmreg;
1606 		break;
1607 	case BTC_RPT_TYPE_GPIO_DBG:
1608 		pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
1609 		if (ver->fcxgpiodbg == 7) {
1610 			pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7;
1611 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7);
1612 			fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7.fver;
1613 		} else {
1614 			pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1;
1615 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1);
1616 			fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1.fver;
1617 		}
1618 		pcinfo->req_fver = ver->fcxgpiodbg;
1619 		break;
1620 	case BTC_RPT_TYPE_BT_VER:
1621 		pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
1622 		if (ver->fcxbtver == 1) {
1623 			pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v1;
1624 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v1);
1625 			fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v1.fver;
1626 		} else if (ver->fcxbtver == 7) {
1627 			pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v7;
1628 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v7);
1629 			fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v7.fver;
1630 		}
1631 		pcinfo->req_fver = ver->fcxbtver;
1632 		break;
1633 	case BTC_RPT_TYPE_BT_SCAN:
1634 		pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
1635 		if (ver->fcxbtscan == 1) {
1636 			pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1;
1637 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v1);
1638 			fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v1.fver;
1639 		} else if (ver->fcxbtscan == 2) {
1640 			pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2;
1641 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v2);
1642 			fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v2.fver;
1643 		} else if (ver->fcxbtscan == 7) {
1644 			pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v7;
1645 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v7);
1646 			fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v7.fver;
1647 		} else {
1648 			goto err;
1649 		}
1650 		pcinfo->req_fver = ver->fcxbtscan;
1651 		break;
1652 	case BTC_RPT_TYPE_BT_AFH:
1653 		pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
1654 		if (ver->fcxbtafh == 1) {
1655 			pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1;
1656 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v1);
1657 			fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v1.fver;
1658 		} else if (ver->fcxbtafh == 2) {
1659 			pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2;
1660 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2);
1661 			fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v2.fver;
1662 		} else if (ver->fcxbtafh == 7) {
1663 			pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v7;
1664 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v7);
1665 			fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v7.fver;
1666 		} else {
1667 			goto err;
1668 		}
1669 		pcinfo->req_fver = ver->fcxbtafh;
1670 		break;
1671 	case BTC_RPT_TYPE_BT_DEVICE:
1672 		pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
1673 		pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo;
1674 		pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo);
1675 		fwsubver->fcxbtdevinfo = pfwinfo->rpt_fbtc_btdev.finfo.fver;
1676 		pcinfo->req_fver = ver->fcxbtdevinfo;
1677 		break;
1678 	default:
1679 		pfwinfo->err[BTFRE_UNDEF_TYPE]++;
1680 		return 0;
1681 	}
1682 
1683 	pcinfo->rx_len = rpt_len;
1684 	pcinfo->rx_cnt++;
1685 
1686 	if (rpt_len != pcinfo->req_len) {
1687 		if (rpt_type < BTC_RPT_TYPE_MAX)
1688 			pfwinfo->len_mismch |= (0x1 << rpt_type);
1689 		else
1690 			pfwinfo->len_mismch |= BIT(31);
1691 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
1692 			    "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n",
1693 			    __func__, rpt_type, rpt_len, pcinfo->req_len);
1694 
1695 		pcinfo->valid = 0;
1696 		return 0;
1697 	} else if (!pfinfo || !rpt_content || !pcinfo->req_len) {
1698 		pfwinfo->err[BTFRE_EXCEPTION]++;
1699 		pcinfo->valid = 0;
1700 		return 0;
1701 	}
1702 
1703 	memcpy(pfinfo, rpt_content, pcinfo->req_len);
1704 	pcinfo->valid = 1;
1705 
1706 	switch (rpt_type) {
1707 	case BTC_RPT_TYPE_CTRL:
1708 		if (ver->fcxbtcrpt == 1) {
1709 			prpt->v1 = pfwinfo->rpt_ctrl.finfo.v1;
1710 			btc->fwinfo.rpt_en_map = prpt->v1.rpt_enable;
1711 			wl->ver_info.fw_coex = prpt->v1.wl_fw_coex_ver;
1712 			wl->ver_info.fw = prpt->v1.wl_fw_ver;
1713 			dm->wl_fw_cx_offload = !!prpt->v1.wl_fw_cx_offload;
1714 
1715 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1716 				     pfwinfo->event[BTF_EVNT_RPT]);
1717 
1718 			/* To avoid I/O if WL LPS or power-off */
1719 			if (wl->status.map.lps != BTC_LPS_RF_OFF &&
1720 			    !wl->status.map.rf_off) {
1721 				rtwdev->chip->ops->btc_update_bt_cnt(rtwdev);
1722 				_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1723 
1724 				btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1725 					rtw89_mac_get_plt_cnt(rtwdev,
1726 							      RTW89_MAC_0);
1727 			}
1728 		} else if (ver->fcxbtcrpt == 4) {
1729 			prpt->v4 = pfwinfo->rpt_ctrl.finfo.v4;
1730 			btc->fwinfo.rpt_en_map = le32_to_cpu(prpt->v4.rpt_info.en);
1731 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v4.wl_fw_info.cx_ver);
1732 			wl->ver_info.fw = le32_to_cpu(prpt->v4.wl_fw_info.fw_ver);
1733 			dm->wl_fw_cx_offload = !!le32_to_cpu(prpt->v4.wl_fw_info.cx_offload);
1734 
1735 			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1736 				memcpy(&dm->gnt.band[i], &prpt->v4.gnt_val[i],
1737 				       sizeof(dm->gnt.band[i]));
1738 
1739 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1740 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_TX]);
1741 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1742 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_RX]);
1743 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1744 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_TX]);
1745 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1746 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_RX]);
1747 			btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1748 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_POLLUTED]);
1749 
1750 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1751 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1752 				     pfwinfo->event[BTF_EVNT_RPT]);
1753 
1754 			if (le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
1755 				bt->rfk_info.map.timeout = 1;
1756 			else
1757 				bt->rfk_info.map.timeout = 0;
1758 
1759 			dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1760 		} else if (ver->fcxbtcrpt == 5) {
1761 			prpt->v5 = pfwinfo->rpt_ctrl.finfo.v5;
1762 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v5.rpt_info.en);
1763 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v5.rpt_info.cx_ver);
1764 			wl->ver_info.fw = le32_to_cpu(prpt->v5.rpt_info.fw_ver);
1765 			dm->wl_fw_cx_offload = 0;
1766 
1767 			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1768 				memcpy(&dm->gnt.band[i], &prpt->v5.gnt_val[i][0],
1769 				       sizeof(dm->gnt.band[i]));
1770 
1771 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1772 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_TX]);
1773 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1774 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_RX]);
1775 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1776 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_TX]);
1777 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1778 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_RX]);
1779 			btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1780 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_POLLUTED]);
1781 
1782 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1783 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1784 				     pfwinfo->event[BTF_EVNT_RPT]);
1785 
1786 			dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1787 		} else if (ver->fcxbtcrpt == 105) {
1788 			prpt->v105 = pfwinfo->rpt_ctrl.finfo.v105;
1789 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v105.rpt_info.en);
1790 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v105.rpt_info.cx_ver);
1791 			wl->ver_info.fw = le32_to_cpu(prpt->v105.rpt_info.fw_ver);
1792 			dm->wl_fw_cx_offload = 0;
1793 
1794 			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1795 				memcpy(&dm->gnt.band[i], &prpt->v105.gnt_val[i][0],
1796 				       sizeof(dm->gnt.band[i]));
1797 
1798 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1799 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_TX_V105]);
1800 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1801 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_RX_V105]);
1802 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1803 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_TX_V105]);
1804 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1805 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_RX_V105]);
1806 			btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1807 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1808 
1809 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1810 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1811 				     pfwinfo->event[BTF_EVNT_RPT]);
1812 
1813 			dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1814 		} else if (ver->fcxbtcrpt == 7) {
1815 			prpt->v7 = pfwinfo->rpt_ctrl.finfo.v7;
1816 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v7.rpt_info.en);
1817 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v7.rpt_info.cx_ver);
1818 			wl->ver_info.fw = le32_to_cpu(prpt->v7.rpt_info.fw_ver);
1819 
1820 			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1821 				memcpy(&dm->gnt.band[i], &prpt->v7.gnt_val[i][0],
1822 				       sizeof(dm->gnt.band[i]));
1823 
1824 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1825 				le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_TX_V105]);
1826 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1827 				le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_RX_V105]);
1828 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1829 				le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_TX_V105]);
1830 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1831 				le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_RX_V105]);
1832 
1833 			val1 = le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1834 			if (val1 > btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW])
1835 				val1 -= btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]; /* diff */
1836 
1837 			btc->cx.cnt_bt[BTC_BCNT_POLUT_DIFF] = val1;
1838 			btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW] =
1839 				le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1840 
1841 			val1 = pfwinfo->event[BTF_EVNT_RPT];
1842 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1843 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
1844 			_chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
1845 			_chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
1846 		} else if (ver->fcxbtcrpt == 8) {
1847 			prpt->v8 = pfwinfo->rpt_ctrl.finfo.v8;
1848 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v8.rpt_info.en);
1849 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v8.rpt_info.cx_ver);
1850 			wl->ver_info.fw = le32_to_cpu(prpt->v8.rpt_info.fw_ver);
1851 
1852 			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1853 				memcpy(&dm->gnt.band[i], &prpt->v8.gnt_val[i][0],
1854 				       sizeof(dm->gnt.band[i]));
1855 
1856 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1857 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_TX_V105]);
1858 			btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1859 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_RX_V105]);
1860 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1861 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_TX_V105]);
1862 			btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1863 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_RX_V105]);
1864 
1865 			val1 = le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1866 			if (val1 > btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW])
1867 				val1 -= btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]; /* diff */
1868 
1869 			btc->cx.cnt_bt[BTC_BCNT_POLUT_DIFF] = val1;
1870 			btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW] =
1871 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1872 
1873 			val1 = pfwinfo->event[BTF_EVNT_RPT];
1874 			if (((prpt->v8.rpt_len_max_h << 8) +
1875 			      prpt->v8.rpt_len_max_l) != ver->info_buf)
1876 				dm->error.map.h2c_c2h_buffer_mismatch = true;
1877 			else
1878 				dm->error.map.h2c_c2h_buffer_mismatch = false;
1879 
1880 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1881 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
1882 			_chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
1883 			_chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
1884 		} else {
1885 			goto err;
1886 		}
1887 		break;
1888 	case BTC_RPT_TYPE_TDMA:
1889 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
1890 			    "[BTC], %s(): check %d %zu\n", __func__,
1891 			    BTC_DCNT_TDMA_NONSYNC,
1892 			    sizeof(dm->tdma_now));
1893 		if (ver->fcxtdma == 1)
1894 			_chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
1895 				     memcmp(&dm->tdma_now,
1896 					    &pfwinfo->rpt_fbtc_tdma.finfo.v1,
1897 					    sizeof(dm->tdma_now)));
1898 		else if (ver->fcxtdma == 3 || ver->fcxtdma == 7)
1899 			_chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
1900 				     memcmp(&dm->tdma_now,
1901 					    &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma,
1902 					    sizeof(dm->tdma_now)));
1903 		else
1904 			goto err;
1905 		break;
1906 	case BTC_RPT_TYPE_SLOT:
1907 		if (ver->fcxslots == 7) {
1908 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
1909 				    "[BTC], %s(): check %d %zu\n",
1910 				    __func__, BTC_DCNT_SLOT_NONSYNC,
1911 				    sizeof(dm->slot_now.v7));
1912 			_chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
1913 				     memcmp(dm->slot_now.v7,
1914 					    pfwinfo->rpt_fbtc_slots.finfo.v7.slot,
1915 					    sizeof(dm->slot_now.v7)));
1916 		} else if (ver->fcxslots == 1) {
1917 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
1918 				    "[BTC], %s(): check %d %zu\n",
1919 				    __func__, BTC_DCNT_SLOT_NONSYNC,
1920 				    sizeof(dm->slot_now.v1));
1921 			_chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
1922 				     memcmp(dm->slot_now.v1,
1923 					    pfwinfo->rpt_fbtc_slots.finfo.v1.slot,
1924 					    sizeof(dm->slot_now.v1)));
1925 		}
1926 		break;
1927 	case BTC_RPT_TYPE_CYSTA:
1928 		if (ver->fcxcysta == 2) {
1929 			if (le16_to_cpu(pcysta->v2.cycles) < BTC_CYSTA_CHK_PERIOD)
1930 				break;
1931 			/* Check Leak-AP */
1932 			if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) != 0 &&
1933 			    le32_to_cpu(pcysta->v2.leakrx_cnt) != 0 && dm->tdma_now.rxflctrl) {
1934 				if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) <
1935 				    BTC_LEAK_AP_TH * le32_to_cpu(pcysta->v2.leakrx_cnt))
1936 					dm->leak_ap = 1;
1937 			}
1938 
1939 			/* Check diff time between WL slot and W1/E2G slot */
1940 			if (dm->tdma_now.type == CXTDMA_OFF &&
1941 			    dm->tdma_now.ext_ctrl == CXECTL_EXT) {
1942 				if (ver->fcxslots == 1)
1943 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_E2G].dur);
1944 				else if (ver->fcxslots == 7)
1945 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_E2G].dur);
1946 			} else {
1947 				if (ver->fcxslots == 1)
1948 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1949 				else if (ver->fcxslots == 7)
1950 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1951 			}
1952 
1953 			if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) {
1954 				diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set;
1955 				_chk_btc_err(rtwdev,
1956 					     BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1957 			}
1958 
1959 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1960 				     le32_to_cpu(pcysta->v2.slot_cnt[CXST_W1]));
1961 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1962 				     le32_to_cpu(pcysta->v2.slot_cnt[CXST_B1]));
1963 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1964 				     le16_to_cpu(pcysta->v2.cycles));
1965 		} else if (ver->fcxcysta == 3) {
1966 			if (le16_to_cpu(pcysta->v3.cycles) < BTC_CYSTA_CHK_PERIOD)
1967 				break;
1968 
1969 			cnt_leak_slot = le32_to_cpu(pcysta->v3.slot_cnt[CXST_LK]);
1970 			cnt_rx_imr = le32_to_cpu(pcysta->v3.leak_slot.cnt_rximr);
1971 
1972 			/* Check Leak-AP */
1973 			if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
1974 			    dm->tdma_now.rxflctrl) {
1975 				if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
1976 					dm->leak_ap = 1;
1977 			}
1978 
1979 			/* Check diff time between real WL slot and W1 slot */
1980 			if (dm->tdma_now.type == CXTDMA_OFF) {
1981 				if (ver->fcxslots == 1)
1982 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1983 				else if (ver->fcxslots == 7)
1984 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1985 				wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]);
1986 				if (wl_slot_real > wl_slot_set) {
1987 					diff_t = wl_slot_real - wl_slot_set;
1988 					_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1989 				}
1990 			}
1991 
1992 			/* Check diff time between real BT slot and EBT/E5G slot */
1993 			if (dm->tdma_now.type == CXTDMA_OFF &&
1994 			    dm->tdma_now.ext_ctrl == CXECTL_EXT &&
1995 			    btc->bt_req_len != 0) {
1996 				bt_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_BT]);
1997 				if (btc->bt_req_len > bt_slot_real) {
1998 					diff_t = btc->bt_req_len - bt_slot_real;
1999 					_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2000 				}
2001 			}
2002 
2003 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2004 				     le32_to_cpu(pcysta->v3.slot_cnt[CXST_W1]));
2005 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2006 				     le32_to_cpu(pcysta->v3.slot_cnt[CXST_B1]));
2007 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2008 				     le16_to_cpu(pcysta->v3.cycles));
2009 		} else if (ver->fcxcysta == 4) {
2010 			if (le16_to_cpu(pcysta->v4.cycles) < BTC_CYSTA_CHK_PERIOD)
2011 				break;
2012 
2013 			cnt_leak_slot = le16_to_cpu(pcysta->v4.slot_cnt[CXST_LK]);
2014 			cnt_rx_imr = le32_to_cpu(pcysta->v4.leak_slot.cnt_rximr);
2015 
2016 			/* Check Leak-AP */
2017 			if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
2018 			    dm->tdma_now.rxflctrl) {
2019 				if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
2020 					dm->leak_ap = 1;
2021 			}
2022 
2023 			/* Check diff time between real WL slot and W1 slot */
2024 			if (dm->tdma_now.type == CXTDMA_OFF) {
2025 				if (ver->fcxslots == 1)
2026 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2027 				else if (ver->fcxslots == 7)
2028 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2029 				wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]);
2030 				if (wl_slot_real > wl_slot_set) {
2031 					diff_t = wl_slot_real - wl_slot_set;
2032 					_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2033 				}
2034 			}
2035 
2036 			/* Check diff time between real BT slot and EBT/E5G slot */
2037 			if (dm->tdma_now.type == CXTDMA_OFF &&
2038 			    dm->tdma_now.ext_ctrl == CXECTL_EXT &&
2039 			    btc->bt_req_len != 0) {
2040 				bt_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_BT]);
2041 
2042 				if (btc->bt_req_len > bt_slot_real) {
2043 					diff_t = btc->bt_req_len - bt_slot_real;
2044 					_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2045 				}
2046 			}
2047 
2048 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2049 				     le16_to_cpu(pcysta->v4.slot_cnt[CXST_W1]));
2050 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2051 				     le16_to_cpu(pcysta->v4.slot_cnt[CXST_B1]));
2052 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2053 				     le16_to_cpu(pcysta->v4.cycles));
2054 		} else if (ver->fcxcysta == 5) {
2055 			if (dm->fddt_train == BTC_FDDT_ENABLE)
2056 				break;
2057 			cnt_leak_slot = le16_to_cpu(pcysta->v5.slot_cnt[CXST_LK]);
2058 			cnt_rx_imr = le32_to_cpu(pcysta->v5.leak_slot.cnt_rximr);
2059 
2060 			/* Check Leak-AP */
2061 			if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
2062 			    dm->tdma_now.rxflctrl) {
2063 				if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD &&
2064 				    cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
2065 					dm->leak_ap = 1;
2066 			}
2067 
2068 			/* Check diff time between real WL slot and W1 slot */
2069 			if (dm->tdma_now.type == CXTDMA_OFF) {
2070 				if (ver->fcxslots == 1)
2071 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2072 				else if (ver->fcxslots == 7)
2073 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2074 				wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]);
2075 
2076 				if (wl_slot_real > wl_slot_set)
2077 					diff_t = wl_slot_real - wl_slot_set;
2078 				else
2079 					diff_t = wl_slot_set - wl_slot_real;
2080 			}
2081 			_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2082 
2083 			/* Check diff time between real BT slot and EBT/E5G slot */
2084 			bt_slot_set = btc->bt_req_len;
2085 			bt_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_BT]);
2086 			diff_t = 0;
2087 			if (dm->tdma_now.type == CXTDMA_OFF &&
2088 			    dm->tdma_now.ext_ctrl == CXECTL_EXT &&
2089 			    bt_slot_set != 0) {
2090 				if (bt_slot_set > bt_slot_real)
2091 					diff_t = bt_slot_set - bt_slot_real;
2092 				else
2093 					diff_t = bt_slot_real - bt_slot_set;
2094 			}
2095 
2096 			_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2097 			_chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
2098 				     le16_to_cpu(pcysta->v5.slot_cnt[CXST_E2G]));
2099 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2100 				     le16_to_cpu(pcysta->v5.slot_cnt[CXST_W1]));
2101 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2102 				     le16_to_cpu(pcysta->v5.slot_cnt[CXST_B1]));
2103 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2104 				     le16_to_cpu(pcysta->v5.cycles));
2105 		} else if (ver->fcxcysta == 7) {
2106 			if (dm->fddt_train == BTC_FDDT_ENABLE)
2107 				break;
2108 
2109 			pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
2110 
2111 			if (dm->tdma_now.type != CXTDMA_OFF) {
2112 				/* Check diff time between real WL slot and W1 slot */
2113 				val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_WL]);
2114 				_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, val16);
2115 
2116 				/* Check Leak-AP */
2117 				val1 = le32_to_cpu(pcysta->v7.leak_slot.cnt_rximr) *
2118 				       BTC_LEAK_AP_TH;
2119 				val2 = le16_to_cpu(pcysta->v7.slot_cnt[CXST_LK]);
2120 
2121 				val16 = le16_to_cpu(pcysta->v7.cycles);
2122 				if (dm->tdma_now.rxflctrl &&
2123 				    val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
2124 					dm->leak_ap = 1;
2125 			} else if (dm->tdma_now.ext_ctrl == CXECTL_EXT) {
2126 				val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_BT]);
2127 				/* Check diff between real BT slot and EBT/E5G slot */
2128 				_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, val16);
2129 
2130 				/* Check bt slot length for P2P mode*/
2131 				val1 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt_timeout) *
2132 				       BTC_SLOT_REQ_TH;
2133 				val2 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt);
2134 
2135 				val16 = le16_to_cpu(pcysta->v7.cycles);
2136 				if (val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
2137 					dm->slot_req_more = 1;
2138 				else if (bt->link_info.status.map.connect == 0)
2139 					dm->slot_req_more = 0;
2140 			}
2141 
2142 			_chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
2143 				     le16_to_cpu(pcysta->v7.slot_cnt[CXST_E2G]));
2144 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2145 				     le16_to_cpu(pcysta->v7.slot_cnt[CXST_W1]));
2146 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2147 				     le16_to_cpu(pcysta->v7.slot_cnt[CXST_B1]));
2148 
2149 			/* "BT_SLOT_FLOOD" error-check MUST before "CYCLE_HANG" */
2150 			_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_FLOOD,
2151 				     le16_to_cpu(pcysta->v7.cycles));
2152 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2153 				     le16_to_cpu(pcysta->v7.cycles));
2154 		} else {
2155 			goto err;
2156 		}
2157 		break;
2158 	case BTC_RPT_TYPE_MREG:
2159 		if (ver->fcxmreg == 7)
2160 			break;
2161 		_get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX_MON, &val);
2162 		if (dm->wl_btg_rx == BTC_BTGCTRL_BB_GNT_FWCTRL)
2163 			dm->wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_FWCTRL;
2164 		else
2165 			dm->wl_btg_rx_rb = val;
2166 
2167 		_get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC_MON, &val);
2168 		if (dm->wl_pre_agc == BTC_PREAGC_BB_FWCTRL)
2169 			dm->wl_pre_agc_rb = BTC_PREAGC_BB_FWCTRL;
2170 		else
2171 			dm->wl_pre_agc_rb = val;
2172 		break;
2173 	case BTC_RPT_TYPE_BT_VER:
2174 	case BTC_RPT_TYPE_BT_SCAN:
2175 	case BTC_RPT_TYPE_BT_AFH:
2176 	case BTC_RPT_TYPE_BT_DEVICE:
2177 		_update_bt_report(rtwdev, rpt_type, pfinfo);
2178 		break;
2179 	}
2180 	return (rpt_len + BTC_RPT_HDR_SIZE);
2181 
2182 err:
2183 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2184 		    "[BTC], %s(): Undefined version for type=%d\n", __func__, rpt_type);
2185 	return 0;
2186 }
2187 
_parse_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * pbuf,u32 buf_len)2188 static void _parse_btc_report(struct rtw89_dev *rtwdev,
2189 			      struct rtw89_btc_btf_fwinfo *pfwinfo,
2190 			      u8 *pbuf, u32 buf_len)
2191 {
2192 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
2193 	struct rtw89_btc_prpt *btc_prpt = NULL;
2194 	u32 index = 0, rpt_len = 0;
2195 
2196 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2197 		    "[BTC], %s(): buf_len:%d\n",
2198 		    __func__, buf_len);
2199 
2200 	while (pbuf) {
2201 		btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index];
2202 		if (index + 2 >= ver->info_buf)
2203 			break;
2204 		/* At least 3 bytes: type(1) & len(2) */
2205 		rpt_len = le16_to_cpu(btc_prpt->len);
2206 		if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len)
2207 			break;
2208 
2209 		rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index);
2210 		if (!rpt_len)
2211 			break;
2212 		index += rpt_len;
2213 	}
2214 }
2215 
2216 #define BTC_TLV_HDR_LEN 2
2217 #define BTC_TLV_HDR_LEN_V7 3
2218 
_append_tdma(struct rtw89_dev * rtwdev)2219 static void _append_tdma(struct rtw89_dev *rtwdev)
2220 {
2221 	struct rtw89_btc *btc = &rtwdev->btc;
2222 	const struct rtw89_btc_ver *ver = btc->ver;
2223 	struct rtw89_btc_dm *dm = &btc->dm;
2224 	struct rtw89_btc_btf_tlv *tlv;
2225 	struct rtw89_btc_btf_tlv_v7 *tlv_v7;
2226 	struct rtw89_btc_fbtc_tdma *v;
2227 	struct rtw89_btc_fbtc_tdma_v3 *v3;
2228 	u16 len = btc->policy_len;
2229 
2230 	if (!btc->update_policy_force &&
2231 	    !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) {
2232 		rtw89_debug(rtwdev,
2233 			    RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n",
2234 			    __func__);
2235 		return;
2236 	}
2237 
2238 	tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
2239 	tlv->type = CXPOLICY_TDMA;
2240 	if (ver->fcxtdma == 1) {
2241 		v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0];
2242 		tlv->len = sizeof(*v);
2243 		*v = dm->tdma;
2244 		btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
2245 	} else if (ver->fcxtdma == 7) {
2246 		tlv_v7 = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2247 		tlv_v7->len = sizeof(dm->tdma);
2248 		tlv_v7->ver = ver->fcxtdma;
2249 		tlv_v7->type = CXPOLICY_TDMA;
2250 		memcpy(tlv_v7->val, &dm->tdma, tlv_v7->len);
2251 		btc->policy_len += BTC_TLV_HDR_LEN_V7 + tlv_v7->len;
2252 	} else {
2253 		tlv->len = sizeof(*v3);
2254 		v3 = (struct rtw89_btc_fbtc_tdma_v3 *)&tlv->val[0];
2255 		v3->fver = ver->fcxtdma;
2256 		v3->tdma = dm->tdma;
2257 		btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v3);
2258 	}
2259 
2260 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2261 		    "[BTC], %s(): type:%d, rxflctrl=%d, txpause=%d, wtgle_n=%d, leak_n=%d, ext_ctrl=%d\n",
2262 		    __func__, dm->tdma.type, dm->tdma.rxflctrl,
2263 		    dm->tdma.txpause, dm->tdma.wtgle_n, dm->tdma.leak_n,
2264 		    dm->tdma.ext_ctrl);
2265 }
2266 
_append_slot_v1(struct rtw89_dev * rtwdev)2267 static void _append_slot_v1(struct rtw89_dev *rtwdev)
2268 {
2269 	struct rtw89_btc *btc = &rtwdev->btc;
2270 	struct rtw89_btc_dm *dm = &btc->dm;
2271 	struct rtw89_btc_btf_tlv *tlv = NULL;
2272 	struct btc_fbtc_1slot *v = NULL;
2273 	u16 len = 0;
2274 	u8 i, cnt = 0;
2275 
2276 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2277 		    "[BTC], %s(): A:btc->policy_len = %d\n",
2278 		    __func__, btc->policy_len);
2279 
2280 	for (i = 0; i < CXST_MAX; i++) {
2281 		if (!btc->update_policy_force &&
2282 		    !memcmp(&dm->slot.v1[i], &dm->slot_now.v1[i],
2283 			    sizeof(dm->slot.v1[i])))
2284 			continue;
2285 
2286 		len = btc->policy_len;
2287 
2288 		tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
2289 		v = (struct btc_fbtc_1slot *)&tlv->val[0];
2290 		tlv->type = CXPOLICY_SLOT;
2291 		tlv->len = sizeof(*v);
2292 
2293 		v->fver = btc->ver->fcxslots;
2294 		v->sid = i;
2295 		v->slot = dm->slot.v1[i];
2296 
2297 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2298 			    "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n",
2299 			    __func__, i, dm->slot.v1[i].dur, dm->slot.v1[i].cxtbl,
2300 			    dm->slot.v1[i].cxtype);
2301 		cnt++;
2302 
2303 		btc->policy_len += BTC_TLV_HDR_LEN  + sizeof(*v);
2304 	}
2305 
2306 	if (cnt > 0)
2307 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2308 			    "[BTC], %s(): slot update (cnt=%d)!!\n",
2309 			    __func__, cnt);
2310 }
2311 
_append_slot_v7(struct rtw89_dev * rtwdev)2312 static void _append_slot_v7(struct rtw89_dev *rtwdev)
2313 {
2314 	struct rtw89_btc_btf_tlv_v7 *tlv = NULL;
2315 	struct rtw89_btc *btc = &rtwdev->btc;
2316 	struct rtw89_btc_dm *dm = &btc->dm;
2317 	u8 i, cnt = 0;
2318 	u16 len;
2319 
2320 	for (i = 0; i < CXST_MAX; i++) {
2321 		if (!btc->update_policy_force &&
2322 		    !memcmp(&dm->slot.v7[i], &dm->slot_now.v7[i],
2323 			    sizeof(dm->slot.v7[i])))
2324 			continue;
2325 
2326 		len = btc->policy_len;
2327 
2328 		if (!tlv) {
2329 			if ((len + BTC_TLV_HDR_LEN_V7) > RTW89_BTC_POLICY_MAXLEN) {
2330 				rtw89_debug(rtwdev, RTW89_DBG_BTC,
2331 					    "[BTC], %s(): buff overflow!\n", __func__);
2332 				break;
2333 			}
2334 
2335 			tlv = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2336 			tlv->type = CXPOLICY_SLOT;
2337 			tlv->ver = btc->ver->fcxslots;
2338 			tlv->len = sizeof(dm->slot.v7[0]) + BTC_TLV_SLOT_ID_LEN_V7;
2339 			len += BTC_TLV_HDR_LEN_V7;
2340 		}
2341 
2342 		if ((len + (u16)tlv->len) > RTW89_BTC_POLICY_MAXLEN) {
2343 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
2344 				    "[BTC], %s(): buff overflow!\n", __func__);
2345 			break;
2346 		}
2347 
2348 		btc->policy[len] = i; /* slot-id */
2349 		memcpy(&btc->policy[len + 1], &dm->slot.v7[i],
2350 		       sizeof(dm->slot.v7[0]));
2351 		len += tlv->len;
2352 
2353 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2354 			    "[BTC], %s: policy_len=%d, slot-%d: dur=%d, type=%d, table=0x%08x\n",
2355 			    __func__, btc->policy_len, i, dm->slot.v7[i].dur,
2356 			    dm->slot.v7[i].cxtype, dm->slot.v7[i].cxtbl);
2357 		cnt++;
2358 		btc->policy_len = len; /* update total length */
2359 	}
2360 
2361 	if (cnt > 0)
2362 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2363 			    "[BTC], %s: slot update (cnt=%d, len=%d)!!\n",
2364 			    __func__, cnt, btc->policy_len);
2365 }
2366 
_append_slot(struct rtw89_dev * rtwdev)2367 static void _append_slot(struct rtw89_dev *rtwdev)
2368 {
2369 	struct rtw89_btc *btc = &rtwdev->btc;
2370 
2371 	if (btc->ver->fcxslots == 7)
2372 		_append_slot_v7(rtwdev);
2373 	else
2374 		_append_slot_v1(rtwdev);
2375 }
2376 
rtw89_btc_fw_rpt_ver(struct rtw89_dev * rtwdev,u32 rpt_map)2377 static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map)
2378 {
2379 	struct rtw89_btc *btc = &rtwdev->btc;
2380 	const struct rtw89_btc_ver *ver = btc->ver;
2381 	u32 bit_map = 0;
2382 
2383 	switch (rpt_map) {
2384 	case RPT_EN_TDMA:
2385 		bit_map = BIT(0);
2386 		break;
2387 	case RPT_EN_CYCLE:
2388 		bit_map = BIT(1);
2389 		break;
2390 	case RPT_EN_MREG:
2391 		bit_map = BIT(2);
2392 		break;
2393 	case RPT_EN_BT_VER_INFO:
2394 		bit_map = BIT(3);
2395 		break;
2396 	case RPT_EN_BT_SCAN_INFO:
2397 		bit_map = BIT(4);
2398 		break;
2399 	case RPT_EN_BT_DEVICE_INFO:
2400 		switch (ver->frptmap) {
2401 		case 0:
2402 		case 1:
2403 		case 2:
2404 			bit_map = BIT(6);
2405 			break;
2406 		case 3:
2407 		case 4:
2408 			bit_map = BIT(5);
2409 			break;
2410 		default:
2411 			break;
2412 		}
2413 		break;
2414 	case RPT_EN_BT_AFH_MAP:
2415 		switch (ver->frptmap) {
2416 		case 0:
2417 		case 1:
2418 		case 2:
2419 			bit_map = BIT(5);
2420 			break;
2421 		case 3:
2422 		case 4:
2423 			bit_map = BIT(6);
2424 			break;
2425 		default:
2426 			break;
2427 		}
2428 		break;
2429 	case RPT_EN_BT_AFH_MAP_LE:
2430 		switch (ver->frptmap) {
2431 		case 2:
2432 			bit_map = BIT(8);
2433 			break;
2434 		case 3:
2435 		case 4:
2436 			bit_map = BIT(7);
2437 			break;
2438 		default:
2439 			break;
2440 		}
2441 		break;
2442 	case RPT_EN_BT_TX_PWR_LVL:
2443 		switch (ver->frptmap) {
2444 		case 0:
2445 		case 1:
2446 		case 2:
2447 		case 3:
2448 			break;
2449 		case 4:
2450 			bit_map = BIT(8);
2451 			break;
2452 		default:
2453 			break;
2454 		}
2455 		break;
2456 	case RPT_EN_FW_STEP_INFO:
2457 		switch (ver->frptmap) {
2458 		case 1:
2459 		case 2:
2460 			bit_map = BIT(7);
2461 			break;
2462 		case 3:
2463 			bit_map = BIT(8);
2464 			break;
2465 		case 4:
2466 			bit_map = BIT(9);
2467 			break;
2468 		default:
2469 			break;
2470 		}
2471 		break;
2472 	case RPT_EN_TEST:
2473 		bit_map = BIT(31);
2474 		break;
2475 	case RPT_EN_WL_ALL:
2476 		switch (ver->frptmap) {
2477 		case 0:
2478 		case 1:
2479 		case 2:
2480 			bit_map = GENMASK(2, 0);
2481 			break;
2482 		case 3:
2483 			bit_map = GENMASK(2, 0) | BIT(8);
2484 			break;
2485 		case 4:
2486 			bit_map = GENMASK(2, 0) | BIT(9);
2487 			break;
2488 		default:
2489 			break;
2490 		}
2491 		break;
2492 	case RPT_EN_BT_ALL:
2493 		switch (ver->frptmap) {
2494 		case 0:
2495 		case 1:
2496 			bit_map = GENMASK(6, 3);
2497 			break;
2498 		case 2:
2499 			bit_map = GENMASK(6, 3) | BIT(8);
2500 			break;
2501 		case 3:
2502 			bit_map = GENMASK(7, 3);
2503 			break;
2504 		case 4:
2505 			bit_map = GENMASK(8, 3);
2506 			break;
2507 		default:
2508 			break;
2509 		}
2510 		break;
2511 	case RPT_EN_ALL:
2512 		switch (ver->frptmap) {
2513 		case 0:
2514 			bit_map = GENMASK(6, 0);
2515 			break;
2516 		case 1:
2517 			bit_map = GENMASK(7, 0);
2518 			break;
2519 		case 2:
2520 		case 3:
2521 			bit_map = GENMASK(8, 0);
2522 			break;
2523 		case 4:
2524 			bit_map = GENMASK(9, 0);
2525 			break;
2526 		default:
2527 			break;
2528 		}
2529 		break;
2530 	case RPT_EN_MONITER:
2531 		switch (ver->frptmap) {
2532 		case 0:
2533 		case 1:
2534 			bit_map = GENMASK(6, 2);
2535 			break;
2536 		case 2:
2537 			bit_map = GENMASK(6, 2) | BIT(8);
2538 			break;
2539 		case 3:
2540 			bit_map = GENMASK(8, 2);
2541 			break;
2542 		case 4:
2543 			bit_map = GENMASK(9, 2);
2544 			break;
2545 		default:
2546 			break;
2547 		}
2548 		break;
2549 	}
2550 
2551 	return bit_map;
2552 }
2553 
rtw89_btc_fw_set_slots(struct rtw89_dev * rtwdev)2554 static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev)
2555 {
2556 	struct rtw89_btc *btc = &rtwdev->btc;
2557 	const struct rtw89_btc_ver *ver = btc->ver;
2558 	struct rtw89_btc_btf_tlv_v7 *tlv_v7 = NULL;
2559 	struct rtw89_btc_btf_set_slot_table *tbl;
2560 	struct rtw89_btc_dm *dm = &btc->dm;
2561 	u16 n, len;
2562 
2563 	if (ver->fcxslots == 7) {
2564 		len = sizeof(*tlv_v7) + sizeof(dm->slot.v7);
2565 		tlv_v7 = kmalloc(len, GFP_KERNEL);
2566 		if (!tlv_v7)
2567 			return;
2568 
2569 		tlv_v7->type = SET_SLOT_TABLE;
2570 		tlv_v7->ver = ver->fcxslots;
2571 		tlv_v7->len = ARRAY_SIZE(dm->slot.v7);
2572 		memcpy(tlv_v7->val, dm->slot.v7, sizeof(dm->slot.v7));
2573 
2574 		_send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, (u8 *)tlv_v7, len);
2575 
2576 		kfree(tlv_v7);
2577 	} else {
2578 		n = struct_size(tbl, tbls, CXST_MAX);
2579 		tbl = kmalloc(n, GFP_KERNEL);
2580 		if (!tbl)
2581 			return;
2582 
2583 		tbl->fver = BTF_SET_SLOT_TABLE_VER;
2584 		tbl->tbl_num = CXST_MAX;
2585 		memcpy(tbl->tbls, dm->slot.v1, flex_array_size(tbl, tbls, CXST_MAX));
2586 
2587 		_send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
2588 
2589 		kfree(tbl);
2590 	}
2591 }
2592 
rtw89_btc_fw_en_rpt(struct rtw89_dev * rtwdev,u32 rpt_map,bool rpt_state)2593 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
2594 				u32 rpt_map, bool rpt_state)
2595 {
2596 	struct rtw89_btc *btc = &rtwdev->btc;
2597 	struct rtw89_btc_wl_smap *wl_smap = &btc->cx.wl.status.map;
2598 	struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo;
2599 	union rtw89_fbtc_rtp_ctrl r;
2600 	u32 val, bit_map;
2601 	int ret;
2602 
2603 	if ((wl_smap->rf_off || wl_smap->lps != BTC_LPS_OFF) && rpt_state != 0)
2604 		return;
2605 
2606 	bit_map = rtw89_btc_fw_rpt_ver(rtwdev, rpt_map);
2607 
2608 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2609 		    "[BTC], %s(): rpt_map=%x, rpt_state=%x\n",
2610 		    __func__, rpt_map, rpt_state);
2611 
2612 	if (rpt_state)
2613 		val = fwinfo->rpt_en_map | bit_map;
2614 	else
2615 		val = fwinfo->rpt_en_map & ~bit_map;
2616 
2617 	if (val == fwinfo->rpt_en_map)
2618 		return;
2619 
2620 	if (btc->ver->fcxbtcrpt == 7 || btc->ver->fcxbtcrpt == 8) {
2621 		r.v8.type = SET_REPORT_EN;
2622 		r.v8.fver = btc->ver->fcxbtcrpt;
2623 		r.v8.len = sizeof(r.v8.map);
2624 		r.v8.map = cpu_to_le32(val);
2625 		ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v8,
2626 				   sizeof(r.v8));
2627 	} else {
2628 		if (btc->ver->fcxbtcrpt == 105)
2629 			r.v1.fver = 5;
2630 		else
2631 			r.v1.fver = btc->ver->fcxbtcrpt;
2632 		r.v1.enable = cpu_to_le32(val);
2633 		r.v1.para = cpu_to_le32(rpt_state);
2634 		ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v1,
2635 				   sizeof(r.v1));
2636 	}
2637 
2638 	if (!ret)
2639 		fwinfo->rpt_en_map = val;
2640 }
2641 
btc_fw_set_monreg(struct rtw89_dev * rtwdev)2642 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
2643 {
2644 	const struct rtw89_chip_info *chip = rtwdev->chip;
2645 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
2646 	struct rtw89_btc_btf_set_mon_reg_v1 *v1 = NULL;
2647 	struct rtw89_btc_btf_set_mon_reg_v7 *v7 = NULL;
2648 	u8 i, n, ulen, cxmreg_max;
2649 	u16 sz = 0;
2650 
2651 	n = chip->mon_reg_num;
2652 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2653 		    "[BTC], %s(): mon_reg_num=%d\n", __func__, n);
2654 
2655 	if (ver->fcxmreg == 1)
2656 		cxmreg_max = CXMREG_MAX;
2657 	else
2658 		cxmreg_max = CXMREG_MAX_V2;
2659 
2660 	if (n > cxmreg_max) {
2661 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2662 			    "[BTC], %s(): mon reg count %d > %d\n",
2663 			    __func__, n, cxmreg_max);
2664 		return;
2665 	}
2666 
2667 	ulen = sizeof(struct rtw89_btc_fbtc_mreg);
2668 
2669 	if (ver->fcxmreg == 7) {
2670 		sz = struct_size(v7, regs, n);
2671 		v7 = kmalloc(sz, GFP_KERNEL);
2672 		if (!v7)
2673 			return;
2674 		v7->type = RPT_EN_MREG;
2675 		v7->fver = ver->fcxmreg;
2676 		v7->len = n;
2677 		for (i = 0; i < n; i++) {
2678 			v7->regs[i].type = chip->mon_reg[i].type;
2679 			v7->regs[i].bytes = chip->mon_reg[i].bytes;
2680 			v7->regs[i].offset = chip->mon_reg[i].offset;
2681 		}
2682 
2683 		_send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v7, sz);
2684 		kfree(v7);
2685 	} else {
2686 		sz = struct_size(v1, regs, n);
2687 		v1 = kmalloc(sz, GFP_KERNEL);
2688 		if (!v1)
2689 			return;
2690 		v1->fver = ver->fcxmreg;
2691 		v1->reg_num = n;
2692 		memcpy(v1->regs, chip->mon_reg, flex_array_size(v1, regs, n));
2693 
2694 		_send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v1, sz);
2695 		kfree(v1);
2696 	}
2697 
2698 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2699 		    "[BTC], %s(): sz=%d ulen=%d n=%d\n",
2700 		    __func__, sz, ulen, n);
2701 
2702 	rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
2703 }
2704 
_update_dm_step(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason_or_action)2705 static void _update_dm_step(struct rtw89_dev *rtwdev,
2706 			    enum btc_reason_and_action reason_or_action)
2707 {
2708 	struct rtw89_btc *btc = &rtwdev->btc;
2709 	struct rtw89_btc_dm *dm = &btc->dm;
2710 
2711 	/* use ring-structure to store dm step */
2712 	dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action;
2713 	dm->dm_step.step_pos++;
2714 
2715 	if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) {
2716 		dm->dm_step.step_pos = 0;
2717 		dm->dm_step.step_ov = true;
2718 	}
2719 }
2720 
_fw_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)2721 static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
2722 			   enum btc_reason_and_action action)
2723 {
2724 	struct rtw89_btc *btc = &rtwdev->btc;
2725 	struct rtw89_btc_dm *dm = &btc->dm;
2726 	int ret;
2727 
2728 	dm->run_action = action;
2729 
2730 	_update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT);
2731 	_update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT);
2732 
2733 	btc->policy_len = 0;
2734 	btc->policy_type = policy_type;
2735 
2736 	_append_tdma(rtwdev);
2737 	_append_slot(rtwdev);
2738 
2739 	if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN)
2740 		return;
2741 
2742 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2743 		    "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n",
2744 		    __func__, action, policy_type, btc->policy_len);
2745 
2746 	if (dm->tdma.rxflctrl == CXFLC_NULLP ||
2747 	    dm->tdma.rxflctrl == CXFLC_QOSNULL)
2748 		btc->lps = 1;
2749 	else
2750 		btc->lps = 0;
2751 
2752 	if (btc->lps == 1)
2753 		rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
2754 
2755 	ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY,
2756 			   btc->policy, btc->policy_len);
2757 	if (!ret) {
2758 		memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now));
2759 		if (btc->ver->fcxslots == 7)
2760 			memcpy(&dm->slot_now.v7, &dm->slot.v7, sizeof(dm->slot_now.v7));
2761 		else
2762 			memcpy(&dm->slot_now.v1, &dm->slot.v1, sizeof(dm->slot_now.v1));
2763 	}
2764 
2765 	if (btc->update_policy_force)
2766 		btc->update_policy_force = false;
2767 
2768 	if (btc->lps == 0)
2769 		rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
2770 }
2771 
_fw_set_drv_info(struct rtw89_dev * rtwdev,u8 type)2772 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 type)
2773 {
2774 	struct rtw89_btc *btc = &rtwdev->btc;
2775 	const struct rtw89_btc_ver *ver = btc->ver;
2776 	struct rtw89_btc_dm *dm = &btc->dm;
2777 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2778 	struct rtw89_btc_rf_trx_para rf_para = dm->rf_trx_para;
2779 
2780 	switch (type) {
2781 	case CXDRVINFO_INIT:
2782 		if (ver->fcxinit == 7)
2783 			rtw89_fw_h2c_cxdrv_init_v7(rtwdev, type);
2784 		else
2785 			rtw89_fw_h2c_cxdrv_init(rtwdev, type);
2786 		break;
2787 	case CXDRVINFO_ROLE:
2788 		if (ver->fwlrole == 0)
2789 			rtw89_fw_h2c_cxdrv_role(rtwdev, type);
2790 		else if (ver->fwlrole == 1)
2791 			rtw89_fw_h2c_cxdrv_role_v1(rtwdev, type);
2792 		else if (ver->fwlrole == 2)
2793 			rtw89_fw_h2c_cxdrv_role_v2(rtwdev, type);
2794 		else if (ver->fwlrole == 7)
2795 			rtw89_fw_h2c_cxdrv_role_v7(rtwdev, type);
2796 		else if (ver->fwlrole == 8)
2797 			rtw89_fw_h2c_cxdrv_role_v8(rtwdev, type);
2798 		break;
2799 	case CXDRVINFO_CTRL:
2800 		if (ver->drvinfo_type == 1)
2801 			type = 2;
2802 
2803 		if (ver->fcxctrl == 7)
2804 			rtw89_fw_h2c_cxdrv_ctrl_v7(rtwdev, type);
2805 		else
2806 			rtw89_fw_h2c_cxdrv_ctrl(rtwdev, type);
2807 		break;
2808 	case CXDRVINFO_TRX:
2809 		if (ver->drvinfo_type == 1)
2810 			type = 3;
2811 
2812 		dm->trx_info.tx_power = u32_get_bits(rf_para.wl_tx_power,
2813 						     RTW89_BTC_WL_DEF_TX_PWR);
2814 		dm->trx_info.rx_gain = u32_get_bits(rf_para.wl_rx_gain,
2815 						    RTW89_BTC_WL_DEF_TX_PWR);
2816 		dm->trx_info.bt_tx_power = u32_get_bits(rf_para.bt_tx_power,
2817 							RTW89_BTC_WL_DEF_TX_PWR);
2818 		dm->trx_info.bt_rx_gain = u32_get_bits(rf_para.bt_rx_gain,
2819 						       RTW89_BTC_WL_DEF_TX_PWR);
2820 		dm->trx_info.cn = wl->cn_report;
2821 		dm->trx_info.nhm = wl->nhm.pwr;
2822 		rtw89_fw_h2c_cxdrv_trx(rtwdev, type);
2823 		break;
2824 	case CXDRVINFO_RFK:
2825 		if (ver->drvinfo_type == 1)
2826 			return;
2827 
2828 		rtw89_fw_h2c_cxdrv_rfk(rtwdev, type);
2829 		break;
2830 	case CXDRVINFO_TXPWR:
2831 	case CXDRVINFO_FDDT:
2832 	case CXDRVINFO_MLO:
2833 	case CXDRVINFO_OSI:
2834 		if (!ver->fcxosi)
2835 			return;
2836 
2837 		if (ver->drvinfo_type == 2)
2838 			type = 7;
2839 		else
2840 			return;
2841 
2842 		rtw89_fw_h2c_cxdrv_osi_info(rtwdev, type);
2843 		break;
2844 	default:
2845 		break;
2846 	}
2847 }
2848 
2849 static
btc_fw_event(struct rtw89_dev * rtwdev,u8 evt_id,void * data,u32 len)2850 void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len)
2851 {
2852 	struct rtw89_btc *btc = &rtwdev->btc;
2853 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
2854 
2855 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2856 		    "[BTC], %s(): evt_id:%d len:%d\n",
2857 		    __func__, evt_id, len);
2858 
2859 	if (!len || !data)
2860 		return;
2861 
2862 	switch (evt_id) {
2863 	case BTF_EVNT_RPT:
2864 		_parse_btc_report(rtwdev, pfwinfo, data, len);
2865 		break;
2866 	default:
2867 		break;
2868 	}
2869 }
2870 
_set_gnt(struct rtw89_dev * rtwdev,u8 phy_map,u8 wl_state,u8 bt_state)2871 static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map, u8 wl_state, u8 bt_state)
2872 {
2873 	struct rtw89_btc *btc = &rtwdev->btc;
2874 	struct rtw89_btc_dm *dm = &btc->dm;
2875 	struct rtw89_mac_ax_gnt *g = dm->gnt.band;
2876 	u8 i;
2877 
2878 	if (phy_map > BTC_PHY_ALL)
2879 		return;
2880 
2881 	for (i = 0; i < RTW89_PHY_NUM; i++) {
2882 		if (!(phy_map & BIT(i)))
2883 			continue;
2884 
2885 		switch (wl_state) {
2886 		case BTC_GNT_HW:
2887 			g[i].gnt_wl_sw_en = 0;
2888 			g[i].gnt_wl = 0;
2889 			break;
2890 		case BTC_GNT_SW_LO:
2891 			g[i].gnt_wl_sw_en = 1;
2892 			g[i].gnt_wl = 0;
2893 			break;
2894 		case BTC_GNT_SW_HI:
2895 			g[i].gnt_wl_sw_en = 1;
2896 			g[i].gnt_wl = 1;
2897 			break;
2898 		}
2899 
2900 		switch (bt_state) {
2901 		case BTC_GNT_HW:
2902 			g[i].gnt_bt_sw_en = 0;
2903 			g[i].gnt_bt = 0;
2904 			break;
2905 		case BTC_GNT_SW_LO:
2906 			g[i].gnt_bt_sw_en = 1;
2907 			g[i].gnt_bt = 0;
2908 			break;
2909 		case BTC_GNT_SW_HI:
2910 			g[i].gnt_bt_sw_en = 1;
2911 			g[i].gnt_bt = 1;
2912 			break;
2913 		}
2914 	}
2915 
2916 	rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
2917 }
2918 
_set_gnt_v1(struct rtw89_dev * rtwdev,u8 phy_map,u8 wl_state,u8 bt_state,u8 wlact_state)2919 static void _set_gnt_v1(struct rtw89_dev *rtwdev, u8 phy_map,
2920 			u8 wl_state, u8 bt_state, u8 wlact_state)
2921 {
2922 	struct rtw89_btc *btc = &rtwdev->btc;
2923 	struct rtw89_btc_dm *dm = &btc->dm;
2924 	struct rtw89_btc_fbtc_outsrc_set_info *osi = &dm->ost_info;
2925 	struct rtw89_mac_ax_wl_act *b = dm->gnt.bt;
2926 	struct rtw89_mac_ax_gnt *g = dm->gnt.band;
2927 	u8 i, bt_idx = dm->bt_select + 1;
2928 
2929 	if (phy_map > BTC_PHY_ALL)
2930 		return;
2931 
2932 	for (i = 0; i < RTW89_PHY_NUM; i++) {
2933 		if (!(phy_map & BIT(i)))
2934 			continue;
2935 
2936 		switch (wl_state) {
2937 		case BTC_GNT_HW:
2938 			g[i].gnt_wl_sw_en = 0;
2939 			g[i].gnt_wl = 0;
2940 			break;
2941 		case BTC_GNT_SW_LO:
2942 			g[i].gnt_wl_sw_en = 1;
2943 			g[i].gnt_wl = 0;
2944 			break;
2945 		case BTC_GNT_SW_HI:
2946 			g[i].gnt_wl_sw_en = 1;
2947 			g[i].gnt_wl = 1;
2948 			break;
2949 		}
2950 
2951 		switch (bt_state) {
2952 		case BTC_GNT_HW:
2953 			g[i].gnt_bt_sw_en = 0;
2954 			g[i].gnt_bt = 0;
2955 			break;
2956 		case BTC_GNT_SW_LO:
2957 			g[i].gnt_bt_sw_en = 1;
2958 			g[i].gnt_bt = 0;
2959 			break;
2960 		case BTC_GNT_SW_HI:
2961 			g[i].gnt_bt_sw_en = 1;
2962 			g[i].gnt_bt = 1;
2963 			break;
2964 		}
2965 	}
2966 
2967 	if (rtwdev->chip->para_ver & BTC_FEAT_WLAN_ACT_MUX) {
2968 		for (i = 0; i < 2; i++) {
2969 			if (!(bt_idx & BIT(i)))
2970 				continue;
2971 
2972 			switch (wlact_state) {
2973 			case BTC_WLACT_HW:
2974 				b[i].wlan_act_en = 0;
2975 				b[i].wlan_act = 0;
2976 				break;
2977 			case BTC_WLACT_SW_LO:
2978 				b[i].wlan_act_en = 1;
2979 				b[i].wlan_act = 0;
2980 				break;
2981 			case BTC_WLACT_SW_HI:
2982 				b[i].wlan_act_en = 1;
2983 				b[i].wlan_act = 1;
2984 				break;
2985 			}
2986 		}
2987 	}
2988 
2989 	if (!btc->ver->fcxosi) {
2990 		rtw89_mac_cfg_gnt_v2(rtwdev, &dm->gnt);
2991 		return;
2992 	}
2993 
2994 	memcpy(osi->gnt_set, dm->gnt.band, sizeof(osi->gnt_set));
2995 	memcpy(osi->wlact_set, dm->gnt.bt, sizeof(osi->wlact_set));
2996 
2997 	/* GBT source should be GBT_S1 in 1+1 (HWB0:5G + HWB1:2G) case */
2998 	if (osi->rf_band[BTC_RF_S0] == 1 &&
2999 	    osi->rf_band[BTC_RF_S1] == 0)
3000 		osi->rf_gbt_source = BTC_RF_S1;
3001 	else
3002 		osi->rf_gbt_source = BTC_RF_S0;
3003 }
3004 
3005 #define BTC_TDMA_WLROLE_MAX 3
3006 
_set_bt_ignore_wlan_act(struct rtw89_dev * rtwdev,u8 enable)3007 static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable)
3008 {
3009 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
3010 		    "[BTC], %s(): set bt %s wlan_act\n", __func__,
3011 		    enable ? "ignore" : "do not ignore");
3012 
3013 	_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1);
3014 }
3015 
3016 #define WL_TX_POWER_NO_BTC_CTRL	GENMASK(31, 0)
3017 #define WL_TX_POWER_ALL_TIME GENMASK(15, 0)
3018 #define WL_TX_POWER_WITH_BT GENMASK(31, 16)
3019 #define WL_TX_POWER_INT_PART GENMASK(8, 2)
3020 #define WL_TX_POWER_FRA_PART GENMASK(1, 0)
3021 #define B_BTC_WL_TX_POWER_SIGN BIT(7)
3022 #define B_TSSI_WL_TX_POWER_SIGN BIT(8)
3023 
_set_wl_tx_power(struct rtw89_dev * rtwdev,u32 level)3024 static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level)
3025 {
3026 	const struct rtw89_chip_info *chip = rtwdev->chip;
3027 	struct rtw89_btc *btc = &rtwdev->btc;
3028 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3029 	u32 pwr_val;
3030 
3031 	if (wl->rf_para.tx_pwr_freerun == level)
3032 		return;
3033 
3034 	wl->rf_para.tx_pwr_freerun = level;
3035 	btc->dm.rf_trx_para.wl_tx_power = level;
3036 
3037 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
3038 		    "[BTC], %s(): level = %d\n",
3039 		    __func__, level);
3040 
3041 	if (level == RTW89_BTC_WL_DEF_TX_PWR) {
3042 		pwr_val = WL_TX_POWER_NO_BTC_CTRL;
3043 	} else { /* only apply "force tx power" */
3044 		pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level);
3045 		if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR)
3046 			pwr_val = RTW89_BTC_WL_DEF_TX_PWR;
3047 
3048 		if (level & B_BTC_WL_TX_POWER_SIGN)
3049 			pwr_val |= B_TSSI_WL_TX_POWER_SIGN;
3050 		pwr_val |= WL_TX_POWER_WITH_BT;
3051 	}
3052 
3053 	chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val);
3054 }
3055 
_set_wl_rx_gain(struct rtw89_dev * rtwdev,u32 level)3056 static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
3057 {
3058 	const struct rtw89_chip_info *chip = rtwdev->chip;
3059 	struct rtw89_btc *btc = &rtwdev->btc;
3060 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3061 
3062 	if (wl->rf_para.rx_gain_freerun == level)
3063 		return;
3064 
3065 	wl->rf_para.rx_gain_freerun = level;
3066 	btc->dm.rf_trx_para.wl_rx_gain = level;
3067 
3068 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
3069 		    "[BTC], %s(): level = %d\n",
3070 		    __func__, level);
3071 
3072 	chip->ops->btc_set_wl_rx_gain(rtwdev, level);
3073 }
3074 
_set_bt_tx_power(struct rtw89_dev * rtwdev,u8 level)3075 static void _set_bt_tx_power(struct rtw89_dev *rtwdev, u8 level)
3076 {
3077 	struct rtw89_btc *btc = &rtwdev->btc;
3078 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3079 	int ret;
3080 	u8 buf;
3081 
3082 	if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0)
3083 		return;
3084 
3085 	if (bt->rf_para.tx_pwr_freerun == level)
3086 		return;
3087 
3088 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
3089 		    "[BTC], %s(): level = %d\n",
3090 		    __func__, level);
3091 
3092 	buf = (s8)(-level);
3093 	ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_TX_PWR, &buf, 1);
3094 	if (!ret) {
3095 		bt->rf_para.tx_pwr_freerun = level;
3096 		btc->dm.rf_trx_para.bt_tx_power = level;
3097 	}
3098 }
3099 
3100 #define BTC_BT_RX_NORMAL_LVL 7
3101 
_set_bt_rx_gain(struct rtw89_dev * rtwdev,u8 level)3102 static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, u8 level)
3103 {
3104 	struct rtw89_btc *btc = &rtwdev->btc;
3105 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3106 
3107 	if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0)
3108 		return;
3109 
3110 	if ((bt->rf_para.rx_gain_freerun == level ||
3111 	     level > BTC_BT_RX_NORMAL_LVL) &&
3112 	    (!rtwdev->chip->scbd || bt->lna_constrain == level))
3113 		return;
3114 
3115 	bt->rf_para.rx_gain_freerun = level;
3116 	btc->dm.rf_trx_para.bt_rx_gain = level;
3117 
3118 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
3119 		    "[BTC], %s(): level = %d\n",
3120 		    __func__, level);
3121 
3122 	if (level == BTC_BT_RX_NORMAL_LVL)
3123 		_write_scbd(rtwdev, BTC_WSCB_RXGAIN, false);
3124 	else
3125 		_write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
3126 
3127 	_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_LNA_CONSTRAIN, &level, sizeof(level));
3128 }
3129 
_set_rf_trx_para(struct rtw89_dev * rtwdev)3130 static void _set_rf_trx_para(struct rtw89_dev *rtwdev)
3131 {
3132 	const struct rtw89_chip_info *chip = rtwdev->chip;
3133 	struct rtw89_btc *btc = &rtwdev->btc;
3134 	const struct rtw89_btc_ver *ver = btc->ver;
3135 	struct rtw89_btc_dm *dm = &btc->dm;
3136 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3137 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3138 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
3139 	struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
3140 	struct rtw89_btc_rf_trx_para para;
3141 	u32 wl_stb_chg = 0;
3142 	u8 level_id = 0, link_mode = 0, i, dbcc_2g_phy = 0;
3143 
3144 	if (ver->fwlrole == 0) {
3145 		link_mode = wl->role_info.link_mode;
3146 		for (i = 0; i < RTW89_PHY_NUM; i++) {
3147 			if (wl->dbcc_info.real_band[i] == RTW89_BAND_2G)
3148 				dbcc_2g_phy = i;
3149 		}
3150 	} else if (ver->fwlrole == 1) {
3151 		link_mode = wl->role_info_v1.link_mode;
3152 		dbcc_2g_phy = wl->role_info_v1.dbcc_2g_phy;
3153 	} else if (ver->fwlrole == 2) {
3154 		link_mode = wl->role_info_v2.link_mode;
3155 		dbcc_2g_phy = wl->role_info_v2.dbcc_2g_phy;
3156 	}
3157 
3158 	/* decide trx_para_level */
3159 	if (btc->ant_type == BTC_ANT_SHARED) {
3160 		/* fix LNA2 + TIA gain not change by GNT_BT */
3161 		if ((btc->dm.wl_btg_rx && b->profile_cnt.now != 0) ||
3162 		    dm->bt_only == 1)
3163 			dm->trx_para_level = 1; /* for better BT ACI issue */
3164 		else
3165 			dm->trx_para_level = 0;
3166 	} else { /* non-shared antenna  */
3167 		dm->trx_para_level = 5;
3168 		/* modify trx_para if WK 2.4G-STA-DL + bt link */
3169 		if (b->profile_cnt.now != 0 &&
3170 		    link_mode == BTC_WLINK_2G_STA &&
3171 		    wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { /* uplink */
3172 			if (wl->rssi_level == 4 && bt->rssi_level > 2)
3173 				dm->trx_para_level = 6;
3174 			else if (wl->rssi_level == 3 && bt->rssi_level > 3)
3175 				dm->trx_para_level = 7;
3176 		}
3177 	}
3178 
3179 	level_id = dm->trx_para_level;
3180 	if (level_id >= chip->rf_para_dlink_num ||
3181 	    level_id >= chip->rf_para_ulink_num) {
3182 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
3183 			    "[BTC], %s(): invalid level_id: %d\n",
3184 			    __func__, level_id);
3185 		return;
3186 	}
3187 
3188 	if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
3189 		para = chip->rf_para_ulink[level_id];
3190 	else
3191 		para = chip->rf_para_dlink[level_id];
3192 
3193 	if (dm->fddt_train) {
3194 		_set_wl_rx_gain(rtwdev, 1);
3195 		_write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
3196 	} else {
3197 		_set_wl_tx_power(rtwdev, para.wl_tx_power);
3198 		_set_wl_rx_gain(rtwdev, para.wl_rx_gain);
3199 		_set_bt_tx_power(rtwdev, para.bt_tx_power);
3200 		_set_bt_rx_gain(rtwdev, para.bt_rx_gain);
3201 	}
3202 
3203 	if (!bt->enable.now || dm->wl_only || wl_smap->rf_off ||
3204 	    wl_smap->lps == BTC_LPS_RF_OFF ||
3205 	    link_mode == BTC_WLINK_5G ||
3206 	    link_mode == BTC_WLINK_NOLINK ||
3207 	    (rtwdev->dbcc_en && dbcc_2g_phy != RTW89_PHY_1))
3208 		wl_stb_chg = 0;
3209 	else
3210 		wl_stb_chg = 1;
3211 
3212 	if (wl_stb_chg != dm->wl_stb_chg) {
3213 		dm->wl_stb_chg = wl_stb_chg;
3214 		chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg);
3215 	}
3216 }
3217 
_update_btc_state_map(struct rtw89_dev * rtwdev)3218 static void _update_btc_state_map(struct rtw89_dev *rtwdev)
3219 {
3220 	struct rtw89_btc *btc = &rtwdev->btc;
3221 	struct rtw89_btc_cx *cx = &btc->cx;
3222 	struct rtw89_btc_wl_info *wl = &cx->wl;
3223 	struct rtw89_btc_bt_info *bt = &cx->bt;
3224 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
3225 
3226 	if (wl->status.map.connecting || wl->status.map._4way ||
3227 	    wl->status.map.roaming || wl->status.map.dbccing) {
3228 		cx->state_map = BTC_WLINKING;
3229 	} else if (wl->status.map.scan) { /* wl scan */
3230 		if (bt_linfo->status.map.inq_pag)
3231 			cx->state_map = BTC_WSCAN_BSCAN;
3232 		else
3233 			cx->state_map = BTC_WSCAN_BNOSCAN;
3234 	} else if (wl->status.map.busy) { /* only busy */
3235 		if (bt_linfo->status.map.inq_pag)
3236 			cx->state_map = BTC_WBUSY_BSCAN;
3237 		else
3238 			cx->state_map = BTC_WBUSY_BNOSCAN;
3239 	} else { /* wl idle */
3240 		cx->state_map = BTC_WIDLE;
3241 	}
3242 }
3243 
_set_bt_afh_info_v0(struct rtw89_dev * rtwdev)3244 static void _set_bt_afh_info_v0(struct rtw89_dev *rtwdev)
3245 {
3246 	const struct rtw89_chip_info *chip = rtwdev->chip;
3247 	struct rtw89_btc *btc = &rtwdev->btc;
3248 	const struct rtw89_btc_ver *ver = btc->ver;
3249 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3250 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3251 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
3252 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3253 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3254 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
3255 	struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
3256 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
3257 	struct rtw89_btc_wl_active_role *r;
3258 	struct rtw89_btc_wl_active_role_v1 *r1;
3259 	struct rtw89_btc_wl_active_role_v2 *r2;
3260 	struct rtw89_btc_wl_active_role_v7 *r7;
3261 	struct rtw89_btc_wl_rlink *rlink;
3262 	u8 en = 0, i, ch = 0, bw = 0;
3263 	u8 mode, connect_cnt;
3264 
3265 	if (btc->manual_ctrl || wl->status.map.scan)
3266 		return;
3267 
3268 	if (ver->fwlrole == 0) {
3269 		mode = wl_rinfo->link_mode;
3270 		connect_cnt = wl_rinfo->connect_cnt;
3271 	} else if (ver->fwlrole == 1) {
3272 		mode = wl_rinfo_v1->link_mode;
3273 		connect_cnt = wl_rinfo_v1->connect_cnt;
3274 	} else if (ver->fwlrole == 2) {
3275 		mode = wl_rinfo_v2->link_mode;
3276 		connect_cnt = wl_rinfo_v2->connect_cnt;
3277 	} else if (ver->fwlrole == 7) {
3278 		mode = wl_rinfo_v7->link_mode;
3279 		connect_cnt = wl_rinfo_v7->connect_cnt;
3280 	} else if (ver->fwlrole == 8) {
3281 		mode = wl_rinfo_v8->link_mode;
3282 		connect_cnt = wl_rinfo_v8->connect_cnt;
3283 	} else {
3284 		return;
3285 	}
3286 
3287 	if (wl->status.map.rf_off || bt->whql_test ||
3288 	    mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_5G ||
3289 	    connect_cnt > BTC_TDMA_WLROLE_MAX) {
3290 		en = false;
3291 	} else if (mode == BTC_WLINK_2G_MCC || mode == BTC_WLINK_2G_SCC) {
3292 		en = true;
3293 		/* get p2p channel */
3294 		for (i = 0; i < RTW89_PORT_NUM; i++) {
3295 			r = &wl_rinfo->active_role[i];
3296 			r1 = &wl_rinfo_v1->active_role_v1[i];
3297 			r2 = &wl_rinfo_v2->active_role_v2[i];
3298 			r7 = &wl_rinfo_v7->active_role[i];
3299 			rlink = &wl_rinfo_v8->rlink[i][0];
3300 
3301 			if (ver->fwlrole == 0 &&
3302 			    (r->role == RTW89_WIFI_ROLE_P2P_GO ||
3303 			     r->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3304 				ch = r->ch;
3305 				bw = r->bw;
3306 				break;
3307 			} else if (ver->fwlrole == 1 &&
3308 				   (r1->role == RTW89_WIFI_ROLE_P2P_GO ||
3309 				    r1->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3310 				ch = r1->ch;
3311 				bw = r1->bw;
3312 				break;
3313 			} else if (ver->fwlrole == 2 &&
3314 				   (r2->role == RTW89_WIFI_ROLE_P2P_GO ||
3315 				    r2->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3316 				ch = r2->ch;
3317 				bw = r2->bw;
3318 				break;
3319 			} else if (ver->fwlrole == 7 &&
3320 				   (r7->role == RTW89_WIFI_ROLE_P2P_GO ||
3321 				    r7->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3322 				ch = r7->ch;
3323 				bw = r7->bw;
3324 				break;
3325 			} else if (ver->fwlrole == 8 &&
3326 				   (rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
3327 				    rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3328 				ch = rlink->ch;
3329 				bw = rlink->bw;
3330 				break;
3331 			}
3332 		}
3333 	} else {
3334 		en = true;
3335 		/* get 2g channel  */
3336 		for (i = 0; i < RTW89_PORT_NUM; i++) {
3337 			r = &wl_rinfo->active_role[i];
3338 			r1 = &wl_rinfo_v1->active_role_v1[i];
3339 			r2 = &wl_rinfo_v2->active_role_v2[i];
3340 			r7 = &wl_rinfo_v7->active_role[i];
3341 			rlink = &wl_rinfo_v8->rlink[i][0];
3342 
3343 			if (ver->fwlrole == 0 &&
3344 			    r->connected && r->band == RTW89_BAND_2G) {
3345 				ch = r->ch;
3346 				bw = r->bw;
3347 				break;
3348 			} else if (ver->fwlrole == 1 &&
3349 				   r1->connected && r1->band == RTW89_BAND_2G) {
3350 				ch = r1->ch;
3351 				bw = r1->bw;
3352 				break;
3353 			} else if (ver->fwlrole == 2 &&
3354 				   r2->connected && r2->band == RTW89_BAND_2G) {
3355 				ch = r2->ch;
3356 				bw = r2->bw;
3357 				break;
3358 			} else if (ver->fwlrole == 7 &&
3359 				   r7->connected && r7->band == RTW89_BAND_2G) {
3360 				ch = r7->ch;
3361 				bw = r7->bw;
3362 				break;
3363 			} else if (ver->fwlrole == 8 &&
3364 				   rlink->connected && rlink->rf_band == RTW89_BAND_2G) {
3365 				ch = rlink->ch;
3366 				bw = rlink->bw;
3367 				break;
3368 			}
3369 		}
3370 	}
3371 
3372 	switch (bw) {
3373 	case RTW89_CHANNEL_WIDTH_20:
3374 		bw = 20 + chip->afh_guard_ch * 2;
3375 		break;
3376 	case RTW89_CHANNEL_WIDTH_40:
3377 		bw = 40 + chip->afh_guard_ch * 2;
3378 		break;
3379 	case RTW89_CHANNEL_WIDTH_5:
3380 		bw = 5 + chip->afh_guard_ch * 2;
3381 		break;
3382 	case RTW89_CHANNEL_WIDTH_10:
3383 		bw = 10 + chip->afh_guard_ch * 2;
3384 		break;
3385 	default:
3386 		bw = 0;
3387 		en = false; /* turn off AFH info if BW > 40 */
3388 		break;
3389 	}
3390 
3391 	if (wl->afh_info.en == en &&
3392 	    wl->afh_info.ch == ch &&
3393 	    wl->afh_info.bw == bw &&
3394 	    b->profile_cnt.last == b->profile_cnt.now) {
3395 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
3396 			    "[BTC], %s(): return because no change!\n",
3397 			    __func__);
3398 		return;
3399 	}
3400 
3401 	wl->afh_info.en = en;
3402 	wl->afh_info.ch = ch;
3403 	wl->afh_info.bw = bw;
3404 
3405 	_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3);
3406 
3407 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
3408 		    "[BTC], %s(): en=%d, ch=%d, bw=%d\n",
3409 		    __func__, en, ch, bw);
3410 	btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++;
3411 }
3412 
_set_bt_afh_info_v1(struct rtw89_dev * rtwdev)3413 static void _set_bt_afh_info_v1(struct rtw89_dev *rtwdev)
3414 {
3415 	const struct rtw89_chip_info *chip = rtwdev->chip;
3416 	struct rtw89_btc *btc = &rtwdev->btc;
3417 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3418 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
3419 	struct rtw89_btc_wl_afh_info *wl_afh = &wl->afh_info;
3420 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3421 	struct rtw89_btc_wl_rlink *rlink;
3422 	u8 en = 0, ch = 0, bw = 0, buf[3] = {};
3423 	u8 i, j, link_mode;
3424 
3425 	if (btc->manual_ctrl || wl->status.map.scan)
3426 		return;
3427 
3428 	link_mode = wl_rinfo->link_mode;
3429 
3430 	for (i = 0; i < btc->ver->max_role_num; i++) {
3431 		for (j = RTW89_MAC_0; j < RTW89_MAC_NUM; j++) {
3432 			if (wl->status.map.rf_off || bt->whql_test ||
3433 			    link_mode == BTC_WLINK_NOLINK ||
3434 			    link_mode == BTC_WLINK_5G)
3435 				break;
3436 
3437 			rlink = &wl_rinfo->rlink[i][j];
3438 
3439 			/* Don't care no-connected/non-2G-band role */
3440 			if (!rlink->connected || !rlink->active ||
3441 			    rlink->rf_band != RTW89_BAND_2G)
3442 				continue;
3443 
3444 			en = 1;
3445 			ch = rlink->ch;
3446 			bw = rlink->bw;
3447 
3448 			if (link_mode == BTC_WLINK_2G_MCC &&
3449 			    (rlink->role == RTW89_WIFI_ROLE_AP ||
3450 			     rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
3451 			     rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3452 				/* for 2.4G MCC, take role = ap/go/gc */
3453 				break;
3454 			} else if (link_mode != BTC_WLINK_2G_SCC ||
3455 				   rlink->bw == RTW89_CHANNEL_WIDTH_40) {
3456 				/* for 2.4G scc, take bw = 40M */
3457 				break;
3458 			}
3459 		}
3460 	}
3461 
3462 	/* default AFH channel sapn = center-ch +- 6MHz */
3463 	switch (bw) {
3464 	case RTW89_CHANNEL_WIDTH_20:
3465 		if (btc->dm.freerun || btc->dm.fddt_train)
3466 			bw = 48;
3467 		else
3468 			bw = 20 + chip->afh_guard_ch * 2;
3469 		break;
3470 	case RTW89_CHANNEL_WIDTH_40:
3471 		if (btc->dm.freerun)
3472 			bw = 40 + chip->afh_guard_ch * 2;
3473 		else
3474 			bw = 40;
3475 		break;
3476 	case RTW89_CHANNEL_WIDTH_5:
3477 		bw = 5 + chip->afh_guard_ch * 2;
3478 		break;
3479 	case RTW89_CHANNEL_WIDTH_10:
3480 		bw = 10 + chip->afh_guard_ch * 2;
3481 		break;
3482 	default:
3483 		en = false; /* turn off AFH info if invalid BW */
3484 		bw = 0;
3485 		ch = 0;
3486 		break;
3487 	}
3488 
3489 	if (!en || ch > 14 || ch == 0) {
3490 		en = false;
3491 		bw = 0;
3492 		ch = 0;
3493 	}
3494 
3495 	if (wl_afh->en == en &&
3496 	    wl_afh->ch == ch &&
3497 	    wl_afh->bw == bw &&
3498 	    (!bt->enable.now || bt->enable.last))
3499 		return;
3500 
3501 	wl_afh->en = buf[0];
3502 	wl_afh->ch = buf[1];
3503 	wl_afh->bw = buf[2];
3504 
3505 	if (_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3)) {
3506 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
3507 			    "[BTC], %s(): en=%d, ch=%d, bw=%d\n",
3508 			    __func__, en, ch, bw);
3509 
3510 		btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++;
3511 	}
3512 }
3513 
_set_bt_afh_info(struct rtw89_dev * rtwdev)3514 static void _set_bt_afh_info(struct rtw89_dev *rtwdev)
3515 {
3516 	if (rtwdev->chip->chip_id == RTL8922A)
3517 		_set_bt_afh_info_v1(rtwdev);
3518 	else
3519 		_set_bt_afh_info_v0(rtwdev);
3520 }
3521 
_check_freerun(struct rtw89_dev * rtwdev)3522 static bool _check_freerun(struct rtw89_dev *rtwdev)
3523 {
3524 	struct rtw89_btc *btc = &rtwdev->btc;
3525 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3526 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3527 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3528 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3529 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
3530 	struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
3531 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
3532 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
3533 	struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc;
3534 	union rtw89_btc_module_info *md = &btc->mdinfo;
3535 	const struct rtw89_btc_ver *ver = btc->ver;
3536 	u8 isolation, connect_cnt = 0;
3537 
3538 	if (ver->fcxinit == 7)
3539 		isolation = md->md_v7.ant.isolation;
3540 	else
3541 		isolation = md->md.ant.isolation;
3542 
3543 	if (ver->fwlrole == 0)
3544 		connect_cnt = wl_rinfo->connect_cnt;
3545 	else if (ver->fwlrole == 1)
3546 		connect_cnt = wl_rinfo_v1->connect_cnt;
3547 	else if (ver->fwlrole == 2)
3548 		connect_cnt = wl_rinfo_v2->connect_cnt;
3549 	else if (ver->fwlrole == 7)
3550 		connect_cnt = wl_rinfo_v7->connect_cnt;
3551 	else if (ver->fwlrole == 8)
3552 		connect_cnt = wl_rinfo_v8->connect_cnt;
3553 
3554 	if (btc->ant_type == BTC_ANT_SHARED) {
3555 		btc->dm.trx_para_level = 0;
3556 		return false;
3557 	}
3558 
3559 	/* The below is dedicated antenna case */
3560 	if (connect_cnt > BTC_TDMA_WLROLE_MAX) {
3561 		btc->dm.trx_para_level = 5;
3562 		return true;
3563 	}
3564 
3565 	if (bt_linfo->profile_cnt.now == 0) {
3566 		btc->dm.trx_para_level = 5;
3567 		return true;
3568 	}
3569 
3570 	if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) {
3571 		btc->dm.trx_para_level = 5;
3572 		return true;
3573 	}
3574 
3575 	/* TODO get isolation by BT psd */
3576 	if (isolation >= BTC_FREERUN_ANTISO_MIN) {
3577 		btc->dm.trx_para_level = 5;
3578 		return true;
3579 	}
3580 
3581 	if (!wl->status.map.busy) {/* wl idle -> freerun */
3582 		btc->dm.trx_para_level = 5;
3583 		return true;
3584 	} else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */
3585 		btc->dm.trx_para_level = 0;
3586 		return false;
3587 	} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
3588 		if (wl->rssi_level == 0 && bt_linfo->rssi > 31) {
3589 			btc->dm.trx_para_level = 6;
3590 			return true;
3591 		} else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) {
3592 			btc->dm.trx_para_level = 7;
3593 			return true;
3594 		}
3595 		btc->dm.trx_para_level = 0;
3596 		return false;
3597 	} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) {
3598 		if (bt_linfo->rssi > 28) {
3599 			btc->dm.trx_para_level = 6;
3600 			return true;
3601 		}
3602 	}
3603 
3604 	btc->dm.trx_para_level = 0;
3605 	return false;
3606 }
3607 
3608 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; })
3609 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; })
3610 #define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; })
3611 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; })
3612 
3613 struct btc_btinfo_lb2 {
3614 	u8 connect: 1;
3615 	u8 sco_busy: 1;
3616 	u8 inq_pag: 1;
3617 	u8 acl_busy: 1;
3618 	u8 hfp: 1;
3619 	u8 hid: 1;
3620 	u8 a2dp: 1;
3621 	u8 pan: 1;
3622 };
3623 
3624 struct btc_btinfo_lb3 {
3625 	u8 retry: 4;
3626 	u8 cqddr: 1;
3627 	u8 inq: 1;
3628 	u8 mesh_busy: 1;
3629 	u8 pag: 1;
3630 };
3631 
3632 struct btc_btinfo_hb0 {
3633 	s8 rssi;
3634 };
3635 
3636 struct btc_btinfo_hb1 {
3637 	u8 ble_connect: 1;
3638 	u8 reinit: 1;
3639 	u8 relink: 1;
3640 	u8 igno_wl: 1;
3641 	u8 voice: 1;
3642 	u8 ble_scan: 1;
3643 	u8 role_sw: 1;
3644 	u8 multi_link: 1;
3645 };
3646 
3647 struct btc_btinfo_hb2 {
3648 	u8 pan_active: 1;
3649 	u8 afh_update: 1;
3650 	u8 a2dp_active: 1;
3651 	u8 slave: 1;
3652 	u8 hid_slot: 2;
3653 	u8 hid_cnt: 2;
3654 };
3655 
3656 struct btc_btinfo_hb3 {
3657 	u8 a2dp_bitpool: 6;
3658 	u8 tx_3m: 1;
3659 	u8 a2dp_sink: 1;
3660 };
3661 
3662 union btc_btinfo {
3663 	u8 val;
3664 	struct btc_btinfo_lb2 lb2;
3665 	struct btc_btinfo_lb3 lb3;
3666 	struct btc_btinfo_hb0 hb0;
3667 	struct btc_btinfo_hb1 hb1;
3668 	struct btc_btinfo_hb2 hb2;
3669 	struct btc_btinfo_hb3 hb3;
3670 };
3671 
_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)3672 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
3673 			enum btc_reason_and_action action)
3674 {
3675 	const struct rtw89_chip_info *chip = rtwdev->chip;
3676 
3677 	chip->ops->btc_set_policy(rtwdev, policy_type);
3678 	_fw_set_policy(rtwdev, policy_type, action);
3679 }
3680 
3681 #define BTC_B1_MAX 250 /* unit ms */
rtw89_btc_set_policy(struct rtw89_dev * rtwdev,u16 policy_type)3682 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type)
3683 {
3684 	struct rtw89_btc *btc = &rtwdev->btc;
3685 	struct rtw89_btc_dm *dm = &btc->dm;
3686 	struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
3687 	struct rtw89_btc_fbtc_slot *s = dm->slot.v1;
3688 	u8 type;
3689 	u32 tbl_w1, tbl_b1, tbl_b4;
3690 
3691 	if (btc->ant_type == BTC_ANT_SHARED) {
3692 		if (btc->cx.wl.status.map._4way)
3693 			tbl_w1 = cxtbl[1];
3694 		else
3695 			tbl_w1 = cxtbl[8];
3696 		tbl_b1 = cxtbl[3];
3697 		tbl_b4 = cxtbl[3];
3698 	} else {
3699 		tbl_w1 = cxtbl[16];
3700 		tbl_b1 = cxtbl[17];
3701 		tbl_b4 = cxtbl[17];
3702 	}
3703 
3704 	type = (u8)((policy_type & BTC_CXP_MASK) >> 8);
3705 	btc->bt_req_en = false;
3706 
3707 	switch (type) {
3708 	case BTC_CXP_USERDEF0:
3709 		*t = t_def[CXTD_OFF];
3710 		s[CXST_OFF] = s_def[CXST_OFF];
3711 		_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
3712 		btc->update_policy_force = true;
3713 		break;
3714 	case BTC_CXP_OFF: /* TDMA off */
3715 		_write_scbd(rtwdev, BTC_WSCB_TDMA, false);
3716 		*t = t_def[CXTD_OFF];
3717 		s[CXST_OFF] = s_def[CXST_OFF];
3718 
3719 		switch (policy_type) {
3720 		case BTC_CXP_OFF_BT:
3721 			_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
3722 			break;
3723 		case BTC_CXP_OFF_WL:
3724 			_slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
3725 			break;
3726 		case BTC_CXP_OFF_EQ0:
3727 			_slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
3728 			break;
3729 		case BTC_CXP_OFF_EQ1:
3730 			_slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
3731 			break;
3732 		case BTC_CXP_OFF_EQ2:
3733 			_slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
3734 			break;
3735 		case BTC_CXP_OFF_EQ3:
3736 			_slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
3737 			break;
3738 		case BTC_CXP_OFF_BWB0:
3739 			_slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
3740 			break;
3741 		case BTC_CXP_OFF_BWB1:
3742 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
3743 			break;
3744 		case BTC_CXP_OFF_BWB3:
3745 			_slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
3746 			break;
3747 		}
3748 		break;
3749 	case BTC_CXP_OFFB: /* TDMA off + beacon protect */
3750 		_write_scbd(rtwdev, BTC_WSCB_TDMA, false);
3751 		*t = t_def[CXTD_OFF_B2];
3752 		s[CXST_OFF] = s_def[CXST_OFF];
3753 		switch (policy_type) {
3754 		case BTC_CXP_OFFB_BWB0:
3755 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
3756 			break;
3757 		}
3758 		break;
3759 	case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
3760 		btc->bt_req_en = true;
3761 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3762 		*t = t_def[CXTD_OFF_EXT];
3763 		switch (policy_type) {
3764 		case BTC_CXP_OFFE_DEF:
3765 			s[CXST_E2G] = s_def[CXST_E2G];
3766 			s[CXST_E5G] = s_def[CXST_E5G];
3767 			s[CXST_EBT] = s_def[CXST_EBT];
3768 			s[CXST_ENULL] = s_def[CXST_ENULL];
3769 			break;
3770 		case BTC_CXP_OFFE_DEF2:
3771 			_slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
3772 			s[CXST_E5G] = s_def[CXST_E5G];
3773 			s[CXST_EBT] = s_def[CXST_EBT];
3774 			s[CXST_ENULL] = s_def[CXST_ENULL];
3775 			break;
3776 		}
3777 		break;
3778 	case BTC_CXP_FIX: /* TDMA Fix-Slot */
3779 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3780 		*t = t_def[CXTD_FIX];
3781 		switch (policy_type) {
3782 		case BTC_CXP_FIX_TD3030:
3783 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3784 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3785 			break;
3786 		case BTC_CXP_FIX_TD5050:
3787 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3788 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
3789 			break;
3790 		case BTC_CXP_FIX_TD2030:
3791 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3792 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3793 			break;
3794 		case BTC_CXP_FIX_TD4010:
3795 			_slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
3796 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3797 			break;
3798 		case BTC_CXP_FIX_TD4010ISO:
3799 			_slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
3800 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3801 			break;
3802 		case BTC_CXP_FIX_TD4010ISO_DL:
3803 			_slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
3804 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
3805 			break;
3806 		case BTC_CXP_FIX_TD4010ISO_UL:
3807 			_slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
3808 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
3809 			break;
3810 		case BTC_CXP_FIX_TD7010:
3811 			_slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
3812 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3813 			break;
3814 		case BTC_CXP_FIX_TD2060:
3815 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3816 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3817 			break;
3818 		case BTC_CXP_FIX_TD3060:
3819 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3820 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3821 			break;
3822 		case BTC_CXP_FIX_TD2080:
3823 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3824 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
3825 			break;
3826 		case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
3827 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3828 				  tbl_w1, SLOT_ISO);
3829 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3830 				  tbl_b1, SLOT_MIX);
3831 			break;
3832 		}
3833 		break;
3834 	case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
3835 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3836 		*t = t_def[CXTD_PFIX];
3837 		if (btc->cx.wl.role_info.role_map.role.ap)
3838 			_tdma_set_flctrl(btc, CXFLC_QOSNULL);
3839 
3840 		switch (policy_type) {
3841 		case BTC_CXP_PFIX_TD3030:
3842 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3843 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3844 			break;
3845 		case BTC_CXP_PFIX_TD5050:
3846 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3847 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
3848 			break;
3849 		case BTC_CXP_PFIX_TD2030:
3850 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3851 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3852 			break;
3853 		case BTC_CXP_PFIX_TD2060:
3854 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3855 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3856 			break;
3857 		case BTC_CXP_PFIX_TD3070:
3858 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3859 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3860 			break;
3861 		case BTC_CXP_PFIX_TD2080:
3862 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3863 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
3864 			break;
3865 		}
3866 		break;
3867 	case BTC_CXP_AUTO: /* TDMA Auto-Slot */
3868 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3869 		*t = t_def[CXTD_AUTO];
3870 		switch (policy_type) {
3871 		case BTC_CXP_AUTO_TD50B1:
3872 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3873 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3874 			break;
3875 		case BTC_CXP_AUTO_TD60B1:
3876 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3877 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3878 			break;
3879 		case BTC_CXP_AUTO_TD20B1:
3880 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3881 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3882 			break;
3883 		case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
3884 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3885 				  tbl_w1, SLOT_ISO);
3886 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3887 				  tbl_b1, SLOT_MIX);
3888 			break;
3889 		}
3890 		break;
3891 	case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
3892 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3893 		*t = t_def[CXTD_PAUTO];
3894 		switch (policy_type) {
3895 		case BTC_CXP_PAUTO_TD50B1:
3896 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3897 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3898 			break;
3899 		case BTC_CXP_PAUTO_TD60B1:
3900 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3901 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3902 			break;
3903 		case BTC_CXP_PAUTO_TD20B1:
3904 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3905 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3906 			break;
3907 		case BTC_CXP_PAUTO_TDW1B1:
3908 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3909 				  tbl_w1, SLOT_ISO);
3910 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3911 				  tbl_b1, SLOT_MIX);
3912 			break;
3913 		}
3914 		break;
3915 	case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
3916 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3917 		*t = t_def[CXTD_AUTO2];
3918 		switch (policy_type) {
3919 		case BTC_CXP_AUTO2_TD3050:
3920 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3921 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3922 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3923 			break;
3924 		case BTC_CXP_AUTO2_TD3070:
3925 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3926 			_slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
3927 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3928 			break;
3929 		case BTC_CXP_AUTO2_TD5050:
3930 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3931 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3932 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3933 			break;
3934 		case BTC_CXP_AUTO2_TD6060:
3935 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3936 			_slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
3937 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3938 			break;
3939 		case BTC_CXP_AUTO2_TD2080:
3940 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3941 			_slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
3942 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3943 			break;
3944 		case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
3945 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3946 				  tbl_w1, SLOT_ISO);
3947 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
3948 				  tbl_b4, SLOT_MIX);
3949 			break;
3950 		}
3951 		break;
3952 	case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
3953 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3954 		*t = t_def[CXTD_PAUTO2];
3955 		switch (policy_type) {
3956 		case BTC_CXP_PAUTO2_TD3050:
3957 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3958 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3959 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3960 			break;
3961 		case BTC_CXP_PAUTO2_TD3070:
3962 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3963 			_slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
3964 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3965 			break;
3966 		case BTC_CXP_PAUTO2_TD5050:
3967 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3968 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3969 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3970 			break;
3971 		case BTC_CXP_PAUTO2_TD6060:
3972 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3973 			_slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
3974 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3975 			break;
3976 		case BTC_CXP_PAUTO2_TD2080:
3977 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3978 			_slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
3979 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3980 			break;
3981 		case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
3982 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3983 				  tbl_w1, SLOT_ISO);
3984 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
3985 				  tbl_b4, SLOT_MIX);
3986 			break;
3987 		}
3988 		break;
3989 	}
3990 }
3991 EXPORT_SYMBOL(rtw89_btc_set_policy);
3992 
rtw89_btc_set_policy_v1(struct rtw89_dev * rtwdev,u16 policy_type)3993 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
3994 {
3995 	struct rtw89_btc *btc = &rtwdev->btc;
3996 	struct rtw89_btc_dm *dm = &btc->dm;
3997 	struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
3998 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1;
3999 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
4000 	struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
4001 	struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc;
4002 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4003 	u8 type, null_role;
4004 	u32 tbl_w1, tbl_b1, tbl_b4;
4005 	u16 dur_2;
4006 
4007 	if (wl->status.map.lps) {
4008 		_slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
4009 			     s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
4010 		_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4011 			     s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4012 		_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4013 			     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4014 	}
4015 
4016 	type = FIELD_GET(BTC_CXP_MASK, policy_type);
4017 
4018 	if (btc->ant_type == BTC_ANT_SHARED) {
4019 		if (btc->cx.wl.status.map._4way)
4020 			tbl_w1 = cxtbl[1];
4021 		else if (hid->exist && hid->type == BTC_HID_218)
4022 			tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */
4023 		else
4024 			tbl_w1 = cxtbl[8];
4025 
4026 		if (dm->leak_ap &&
4027 		    (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) {
4028 			tbl_b1 = cxtbl[3];
4029 			tbl_b4 = cxtbl[3];
4030 		} else if (hid->exist && hid->type == BTC_HID_218) {
4031 			tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */
4032 			tbl_b4 = cxtbl[4];
4033 		} else {
4034 			tbl_b1 = cxtbl[2];
4035 			tbl_b4 = cxtbl[2];
4036 		}
4037 	} else {
4038 		tbl_b1 = cxtbl[17];
4039 		tbl_b4 = cxtbl[17];
4040 
4041 		if (wl->bg_mode)
4042 			tbl_w1 = cxtbl[8];
4043 		else if ((wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) &&
4044 			 hid->exist)
4045 			tbl_w1 = cxtbl[19];
4046 		else
4047 			tbl_w1 = cxtbl[16];
4048 	}
4049 
4050 	switch (type) {
4051 	case BTC_CXP_USERDEF0:
4052 		btc->update_policy_force = true;
4053 		*t = t_def[CXTD_OFF];
4054 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4055 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4056 		_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
4057 		break;
4058 	case BTC_CXP_OFF: /* TDMA off */
4059 		_write_scbd(rtwdev, BTC_WSCB_TDMA, false);
4060 		*t = t_def[CXTD_OFF];
4061 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4062 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4063 
4064 		switch (policy_type) {
4065 		case BTC_CXP_OFF_BT:
4066 			_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
4067 			break;
4068 		case BTC_CXP_OFF_WL:
4069 			_slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
4070 			break;
4071 		case BTC_CXP_OFF_WL2:
4072 			_slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
4073 			_slot_set_type(btc, CXST_OFF, SLOT_ISO);
4074 			break;
4075 		case BTC_CXP_OFF_EQ0:
4076 			_slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
4077 			_slot_set_type(btc, CXST_OFF, SLOT_ISO);
4078 			break;
4079 		case BTC_CXP_OFF_EQ1:
4080 			_slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
4081 			break;
4082 		case BTC_CXP_OFF_EQ2:
4083 			_slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
4084 			break;
4085 		case BTC_CXP_OFF_EQ3:
4086 			_slot_set_tbl(btc, CXST_OFF, cxtbl[24]);
4087 			break;
4088 		case BTC_CXP_OFF_EQ4:
4089 			_slot_set_tbl(btc, CXST_OFF, cxtbl[26]);
4090 			break;
4091 		case BTC_CXP_OFF_EQ5:
4092 			_slot_set_tbl(btc, CXST_OFF, cxtbl[27]);
4093 			break;
4094 		case BTC_CXP_OFF_BWB0:
4095 			_slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
4096 			break;
4097 		case BTC_CXP_OFF_BWB1:
4098 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
4099 			break;
4100 		case BTC_CXP_OFF_BWB2:
4101 			_slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
4102 			break;
4103 		case BTC_CXP_OFF_BWB3:
4104 			_slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
4105 			break;
4106 		default:
4107 			break;
4108 		}
4109 		break;
4110 	case BTC_CXP_OFFB: /* TDMA off + beacon protect */
4111 		_write_scbd(rtwdev, BTC_WSCB_TDMA, false);
4112 		*t = t_def[CXTD_OFF_B2];
4113 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4114 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4115 
4116 		switch (policy_type) {
4117 		case BTC_CXP_OFFB_BWB0:
4118 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
4119 			break;
4120 		default:
4121 			break;
4122 		}
4123 		break;
4124 	case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
4125 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4126 		*t = t_def[CXTD_OFF_EXT];
4127 
4128 		/* To avoid wl-s0 tx break by hid/hfp tx */
4129 		if (hid->exist || hfp->exist)
4130 			tbl_w1 = cxtbl[16];
4131 
4132 		dur_2 = dm->e2g_slot_limit;
4133 
4134 		switch (policy_type) {
4135 		case BTC_CXP_OFFE_2GBWISOB: /* for normal-case */
4136 			_slot_set(btc, CXST_E2G, 5, tbl_w1, SLOT_ISO);
4137 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4138 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4139 			_slot_set_dur(btc, CXST_EBT, dur_2);
4140 			break;
4141 		case BTC_CXP_OFFE_2GISOB: /* for bt no-link */
4142 			_slot_set(btc, CXST_E2G, 5, cxtbl[1], SLOT_ISO);
4143 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4144 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4145 			_slot_set_dur(btc, CXST_EBT, dur_2);
4146 			break;
4147 		case BTC_CXP_OFFE_DEF:
4148 			_slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
4149 				     s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
4150 			_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4151 				     s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4152 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4153 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4154 			_slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
4155 				     s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
4156 			break;
4157 		case BTC_CXP_OFFE_DEF2:
4158 			_slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
4159 			_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4160 				     s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4161 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4162 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4163 			_slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
4164 				     s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
4165 			break;
4166 		case BTC_CXP_OFFE_2GBWMIXB:
4167 			if (a2dp->exist)
4168 				_slot_set(btc, CXST_E2G, 5, cxtbl[2], SLOT_MIX);
4169 			else
4170 				_slot_set(btc, CXST_E2G, 5, tbl_w1, SLOT_MIX);
4171 			_slot_set_le(btc, CXST_EBT, cpu_to_le16(40),
4172 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4173 			break;
4174 		case BTC_CXP_OFFE_WL: /* for 4-way */
4175 			_slot_set(btc, CXST_E2G, 5, cxtbl[1], SLOT_MIX);
4176 			_slot_set(btc, CXST_EBT, 5, cxtbl[1], SLOT_MIX);
4177 			break;
4178 		default:
4179 			break;
4180 		}
4181 		_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4182 			     s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4183 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4184 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4185 		break;
4186 	case BTC_CXP_FIX: /* TDMA Fix-Slot */
4187 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4188 		*t = t_def[CXTD_FIX];
4189 
4190 		switch (policy_type) {
4191 		case BTC_CXP_FIX_TD3030:
4192 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4193 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4194 			break;
4195 		case BTC_CXP_FIX_TD5050:
4196 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4197 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
4198 			break;
4199 		case BTC_CXP_FIX_TD2030:
4200 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4201 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4202 			break;
4203 		case BTC_CXP_FIX_TD4010:
4204 			_slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
4205 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4206 			break;
4207 		case BTC_CXP_FIX_TD4010ISO:
4208 			_slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
4209 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4210 			break;
4211 		case BTC_CXP_FIX_TD4010ISO_DL:
4212 			_slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
4213 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
4214 			break;
4215 		case BTC_CXP_FIX_TD4010ISO_UL:
4216 			_slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
4217 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
4218 			break;
4219 		case BTC_CXP_FIX_TD7010:
4220 			_slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
4221 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4222 			break;
4223 		case BTC_CXP_FIX_TD2060:
4224 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4225 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4226 			break;
4227 		case BTC_CXP_FIX_TD3060:
4228 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4229 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4230 			break;
4231 		case BTC_CXP_FIX_TD2080:
4232 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4233 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
4234 			break;
4235 		case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
4236 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4237 				  tbl_w1, SLOT_ISO);
4238 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4239 				  tbl_b1, SLOT_MIX);
4240 			break;
4241 		default:
4242 			break;
4243 		}
4244 		break;
4245 	case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
4246 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4247 		*t = t_def[CXTD_PFIX];
4248 
4249 		switch (policy_type) {
4250 		case BTC_CXP_PFIX_TD3030:
4251 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4252 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4253 			break;
4254 		case BTC_CXP_PFIX_TD5050:
4255 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4256 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
4257 			break;
4258 		case BTC_CXP_PFIX_TD2030:
4259 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4260 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4261 			break;
4262 		case BTC_CXP_PFIX_TD2060:
4263 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4264 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4265 			break;
4266 		case BTC_CXP_PFIX_TD3070:
4267 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4268 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4269 			break;
4270 		case BTC_CXP_PFIX_TD2080:
4271 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4272 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
4273 			break;
4274 		case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */
4275 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4276 				  tbl_w1, SLOT_ISO);
4277 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4278 				  tbl_b1, SLOT_MIX);
4279 			break;
4280 		default:
4281 			break;
4282 		}
4283 		break;
4284 	case BTC_CXP_AUTO: /* TDMA Auto-Slot */
4285 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4286 		*t = t_def[CXTD_AUTO];
4287 
4288 		switch (policy_type) {
4289 		case BTC_CXP_AUTO_TD50B1:
4290 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
4291 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4292 			break;
4293 		case BTC_CXP_AUTO_TD60B1:
4294 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
4295 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4296 			break;
4297 		case BTC_CXP_AUTO_TD20B1:
4298 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
4299 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4300 			break;
4301 		case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
4302 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4303 				  tbl_w1, SLOT_ISO);
4304 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4305 				  tbl_b1, SLOT_MIX);
4306 			break;
4307 		default:
4308 			break;
4309 		}
4310 		break;
4311 	case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
4312 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4313 		*t = t_def[CXTD_PAUTO];
4314 
4315 		switch (policy_type) {
4316 		case BTC_CXP_PAUTO_TD50B1:
4317 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
4318 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4319 			break;
4320 		case BTC_CXP_PAUTO_TD60B1:
4321 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
4322 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4323 			break;
4324 		case BTC_CXP_PAUTO_TD20B1:
4325 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
4326 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4327 			break;
4328 		case BTC_CXP_PAUTO_TDW1B1:
4329 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4330 				  tbl_w1, SLOT_ISO);
4331 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4332 				  tbl_b1, SLOT_MIX);
4333 			break;
4334 		default:
4335 			break;
4336 		}
4337 		break;
4338 	case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
4339 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4340 		*t = t_def[CXTD_AUTO2];
4341 
4342 		switch (policy_type) {
4343 		case BTC_CXP_AUTO2_TD3050:
4344 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
4345 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4346 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
4347 			break;
4348 		case BTC_CXP_AUTO2_TD3070:
4349 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
4350 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4351 			_slot_set(btc, CXST_B4,  70, tbl_b4, SLOT_MIX);
4352 			break;
4353 		case BTC_CXP_AUTO2_TD5050:
4354 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
4355 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4356 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
4357 			break;
4358 		case BTC_CXP_AUTO2_TD6060:
4359 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
4360 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4361 			_slot_set(btc, CXST_B4,  60, tbl_b4, SLOT_MIX);
4362 			break;
4363 		case BTC_CXP_AUTO2_TD2080:
4364 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
4365 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4366 			_slot_set(btc, CXST_B4,  80, tbl_b4, SLOT_MIX);
4367 			break;
4368 		case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
4369 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4370 				  tbl_w1, SLOT_ISO);
4371 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4372 				  tbl_b1, SLOT_MIX);
4373 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
4374 				  tbl_b4, SLOT_MIX);
4375 			break;
4376 		default:
4377 			break;
4378 		}
4379 		break;
4380 	case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
4381 		_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4382 		*t = t_def[CXTD_PAUTO2];
4383 
4384 		switch (policy_type) {
4385 		case BTC_CXP_PAUTO2_TD3050:
4386 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
4387 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4388 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
4389 			break;
4390 		case BTC_CXP_PAUTO2_TD3070:
4391 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
4392 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4393 			_slot_set(btc, CXST_B4,  70, tbl_b4, SLOT_MIX);
4394 			break;
4395 		case BTC_CXP_PAUTO2_TD5050:
4396 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
4397 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4398 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
4399 			break;
4400 		case BTC_CXP_PAUTO2_TD6060:
4401 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
4402 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4403 			_slot_set(btc, CXST_B4,  60, tbl_b4, SLOT_MIX);
4404 			break;
4405 		case BTC_CXP_PAUTO2_TD2080:
4406 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
4407 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4408 			_slot_set(btc, CXST_B4,  80, tbl_b4, SLOT_MIX);
4409 			break;
4410 		case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
4411 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4412 				  tbl_w1, SLOT_ISO);
4413 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4414 				  tbl_b1, SLOT_MIX);
4415 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
4416 				  tbl_b4, SLOT_MIX);
4417 			break;
4418 		default:
4419 			break;
4420 		}
4421 		break;
4422 	}
4423 
4424 	if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) {
4425 		null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) |
4426 			    FIELD_PREP(0xf0, dm->wl_scc.null_role2);
4427 		_tdma_set_flctrl_role(btc, null_role);
4428 	}
4429 
4430 	/* enter leak_slot after each null-1 */
4431 	if (dm->leak_ap && dm->tdma.leak_n > 1)
4432 		_tdma_set_lek(btc, 1);
4433 
4434 	if (dm->tdma_instant_excute) {
4435 		btc->dm.tdma.option_ctrl |= BIT(0);
4436 		btc->update_policy_force = true;
4437 	}
4438 }
4439 EXPORT_SYMBOL(rtw89_btc_set_policy_v1);
4440 
_set_bt_plut(struct rtw89_dev * rtwdev,u8 phy_map,u8 tx_val,u8 rx_val)4441 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
4442 			 u8 tx_val, u8 rx_val)
4443 {
4444 	struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
4445 	struct rtw89_mac_ax_plt plt;
4446 
4447 	plt.tx = tx_val;
4448 	plt.rx = rx_val;
4449 
4450 	if (rtwdev->btc.ver->fwlrole == 8) {
4451 		plt.band = wl->pta_req_mac;
4452 		if (wl->bt_polut_type[plt.band] == tx_val)
4453 			return;
4454 
4455 		wl->bt_polut_type[plt.band] = tx_val;
4456 		rtw89_mac_cfg_plt(rtwdev, &plt);
4457 	} else {
4458 		plt.band = RTW89_MAC_0;
4459 
4460 		if (phy_map & BTC_PHY_0)
4461 			rtw89_mac_cfg_plt(rtwdev, &plt);
4462 
4463 		if (!rtwdev->dbcc_en)
4464 			return;
4465 
4466 		plt.band = RTW89_MAC_1;
4467 		if (phy_map & BTC_PHY_1)
4468 			rtw89_mac_cfg_plt(rtwdev, &plt);
4469 	}
4470 }
4471 
_set_ant_v0(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4472 static void _set_ant_v0(struct rtw89_dev *rtwdev, bool force_exec,
4473 			u8 phy_map, u8 type)
4474 {
4475 	struct rtw89_btc *btc = &rtwdev->btc;
4476 	struct rtw89_btc_dm *dm = &btc->dm;
4477 	struct rtw89_btc_cx *cx = &btc->cx;
4478 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4479 	struct rtw89_btc_bt_info *bt = &cx->bt;
4480 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4481 	u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0;
4482 	bool dbcc_chg = false;
4483 	u32 ant_path_type;
4484 
4485 	ant_path_type = ((phy_map << 8) + type);
4486 
4487 	if (btc->ver->fwlrole == 1)
4488 		dbcc_chg = wl->role_info_v1.dbcc_chg;
4489 	else if (btc->ver->fwlrole == 2)
4490 		dbcc_chg = wl->role_info_v2.dbcc_chg;
4491 	else if (btc->ver->fwlrole == 7)
4492 		dbcc_chg = wl->role_info_v7.dbcc_chg;
4493 	else if (btc->ver->fwlrole == 8)
4494 		dbcc_chg = wl->role_info_v8.dbcc_chg;
4495 
4496 	if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
4497 	    btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
4498 	    btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || dbcc_chg)
4499 		force_exec = FC_EXEC;
4500 
4501 	if (!force_exec && ant_path_type == dm->set_ant_path) {
4502 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4503 			    "[BTC], %s(): return by no change!!\n",
4504 			     __func__);
4505 		return;
4506 	} else if (bt->rfk_info.map.run) {
4507 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4508 			    "[BTC], %s(): return by bt rfk!!\n", __func__);
4509 		return;
4510 	} else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
4511 		   wl->rfk_info.state != BTC_WRFK_STOP) {
4512 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4513 			    "[BTC], %s(): return by wl rfk!!\n", __func__);
4514 		return;
4515 	}
4516 
4517 	dm->set_ant_path = ant_path_type;
4518 
4519 	rtw89_debug(rtwdev,
4520 		    RTW89_DBG_BTC,
4521 		    "[BTC], %s(): path=0x%x, set_type=0x%x\n",
4522 		    __func__, phy_map, dm->set_ant_path & 0xff);
4523 
4524 	switch (type) {
4525 	case BTC_ANT_WPOWERON:
4526 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4527 		break;
4528 	case BTC_ANT_WINIT:
4529 		if (bt->enable.now)
4530 			_set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
4531 		else
4532 			_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4533 
4534 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4535 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT);
4536 		break;
4537 	case BTC_ANT_WONLY:
4538 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4539 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4540 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4541 		break;
4542 	case BTC_ANT_WOFF:
4543 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4544 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4545 		break;
4546 	case BTC_ANT_W2G:
4547 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4548 		if (rtwdev->dbcc_en) {
4549 			for (i = 0; i < RTW89_PHY_NUM; i++) {
4550 				b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G);
4551 
4552 				gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
4553 				gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
4554 				/* BT should control by GNT_BT if WL_2G at S0 */
4555 				if (i == 1 &&
4556 				    wl_dinfo->real_band[0] == RTW89_BAND_2G &&
4557 				    wl_dinfo->real_band[1] == RTW89_BAND_5G)
4558 					gnt_bt_ctrl = BTC_GNT_HW;
4559 				_set_gnt(rtwdev, BIT(i), gnt_wl_ctrl, gnt_bt_ctrl);
4560 				plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE;
4561 				_set_bt_plut(rtwdev, BIT(i),
4562 					     plt_ctrl, plt_ctrl);
4563 			}
4564 		} else {
4565 			_set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
4566 			_set_bt_plut(rtwdev, BTC_PHY_ALL,
4567 				     BTC_PLT_BT, BTC_PLT_BT);
4568 		}
4569 		break;
4570 	case BTC_ANT_W5G:
4571 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4572 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW);
4573 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4574 		break;
4575 	case BTC_ANT_W25G:
4576 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4577 		_set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
4578 		_set_bt_plut(rtwdev, BTC_PHY_ALL,
4579 			     BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
4580 		break;
4581 	case BTC_ANT_FREERUN:
4582 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4583 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI);
4584 		_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4585 		break;
4586 	case BTC_ANT_WRFK:
4587 	case BTC_ANT_WRFK2:
4588 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4589 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4590 		_set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
4591 		break;
4592 	case BTC_ANT_BRFK:
4593 		rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4594 		_set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
4595 		_set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
4596 		break;
4597 	default:
4598 		break;
4599 	}
4600 }
4601 
_set_ant_v1(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4602 static void _set_ant_v1(struct rtw89_dev *rtwdev, bool force_exec,
4603 			u8 phy_map, u8 type)
4604 {
4605 	struct rtw89_btc *btc = &rtwdev->btc;
4606 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4607 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4608 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
4609 	u32 ant_path_type = rtw89_get_antpath_type(phy_map, type);
4610 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4611 	struct rtw89_btc_dm *dm = &btc->dm;
4612 	u8 gwl = BTC_GNT_HW;
4613 
4614 	if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
4615 	    btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
4616 	    btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || wl_rinfo->dbcc_chg)
4617 		force_exec = FC_EXEC;
4618 
4619 	if (wl_rinfo->link_mode != BTC_WLINK_25G_MCC &&
4620 	    btc->dm.wl_btg_rx == 2)
4621 		force_exec = FC_EXEC;
4622 
4623 	if (!force_exec && ant_path_type == dm->set_ant_path) {
4624 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4625 			    "[BTC], %s(): return by no change!!\n",
4626 			     __func__);
4627 		return;
4628 	} else if (bt->rfk_info.map.run) {
4629 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4630 			    "[BTC], %s(): return by bt rfk!!\n", __func__);
4631 		return;
4632 	} else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
4633 		   wl->rfk_info.state != BTC_WRFK_STOP) {
4634 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4635 			    "[BTC], %s(): return by wl rfk!!\n", __func__);
4636 		return;
4637 	}
4638 
4639 	dm->set_ant_path = ant_path_type;
4640 
4641 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
4642 		    "[BTC], %s(): path=0x%x, set_type=0x%x\n",
4643 		    __func__, phy_map, dm->set_ant_path & 0xff);
4644 
4645 	switch (type) {
4646 	case BTC_ANT_WINIT:
4647 		/* To avoid BT MP driver case (bt_enable but no mailbox) */
4648 		if (bt->enable.now && bt->run_patch_code)
4649 			_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
4650 				    BTC_WLACT_SW_LO);
4651 		else
4652 			_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4653 				    BTC_WLACT_SW_HI);
4654 		break;
4655 	case BTC_ANT_WONLY:
4656 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4657 			    BTC_WLACT_SW_HI);
4658 		break;
4659 	case BTC_ANT_WOFF:
4660 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
4661 			    BTC_WLACT_SW_LO);
4662 		break;
4663 	case BTC_ANT_W2G:
4664 	case BTC_ANT_W25G:
4665 		if (wl_rinfo->dbcc_en) {
4666 			if (wl_dinfo->real_band[RTW89_PHY_0] == RTW89_BAND_2G)
4667 				gwl = BTC_GNT_HW;
4668 			else
4669 				gwl = BTC_GNT_SW_HI;
4670 			_set_gnt_v1(rtwdev, BTC_PHY_0, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4671 
4672 			if (wl_dinfo->real_band[RTW89_PHY_1] == RTW89_BAND_2G)
4673 				gwl = BTC_GNT_HW;
4674 			else
4675 				gwl = BTC_GNT_SW_HI;
4676 			_set_gnt_v1(rtwdev, BTC_PHY_1, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4677 		} else {
4678 			gwl = BTC_GNT_HW;
4679 			_set_gnt_v1(rtwdev, phy_map, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4680 		}
4681 		break;
4682 	case BTC_ANT_W5G:
4683 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW, BTC_WLACT_HW);
4684 		break;
4685 	case BTC_ANT_FREERUN:
4686 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI,
4687 			    BTC_WLACT_SW_LO);
4688 		break;
4689 	case BTC_ANT_WRFK:
4690 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4691 			    BTC_WLACT_HW);
4692 		break;
4693 	case BTC_ANT_WRFK2:
4694 		_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4695 			    BTC_WLACT_SW_HI); /* no BT-Tx */
4696 		break;
4697 	default:
4698 		return;
4699 	}
4700 
4701 	_set_bt_plut(rtwdev, phy_map, BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
4702 }
4703 
_set_ant(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4704 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
4705 		     u8 phy_map, u8 type)
4706 {
4707 	if (rtwdev->chip->chip_id == RTL8922A)
4708 		_set_ant_v1(rtwdev, force_exec, phy_map, type);
4709 	else
4710 		_set_ant_v0(rtwdev, force_exec, phy_map, type);
4711 }
4712 
_action_wl_only(struct rtw89_dev * rtwdev)4713 static void _action_wl_only(struct rtw89_dev *rtwdev)
4714 {
4715 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
4716 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY);
4717 }
4718 
_action_wl_init(struct rtw89_dev * rtwdev)4719 static void _action_wl_init(struct rtw89_dev *rtwdev)
4720 {
4721 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4722 
4723 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT);
4724 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT);
4725 }
4726 
_action_wl_off(struct rtw89_dev * rtwdev,u8 mode)4727 static void _action_wl_off(struct rtw89_dev *rtwdev, u8 mode)
4728 {
4729 	struct rtw89_btc *btc = &rtwdev->btc;
4730 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4731 
4732 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4733 
4734 	if (wl->status.map.rf_off || btc->dm.bt_only) {
4735 		_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF);
4736 	} else if (wl->status.map.lps == BTC_LPS_RF_ON) {
4737 		if (mode == BTC_WLINK_5G)
4738 			_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
4739 		else
4740 			_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4741 	}
4742 
4743 	if (mode == BTC_WLINK_5G) {
4744 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OFF);
4745 	} else if (wl->status.map.lps == BTC_LPS_RF_ON) {
4746 		if (btc->cx.bt.link_info.a2dp_desc.active)
4747 			_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
4748 		else
4749 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_WL_OFF);
4750 	} else {
4751 		_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
4752 	}
4753 }
4754 
_action_freerun(struct rtw89_dev * rtwdev)4755 static void _action_freerun(struct rtw89_dev *rtwdev)
4756 {
4757 	struct rtw89_btc *btc = &rtwdev->btc;
4758 
4759 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4760 
4761 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN);
4762 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN);
4763 
4764 	btc->dm.freerun = true;
4765 }
4766 
_action_bt_whql(struct rtw89_dev * rtwdev)4767 static void _action_bt_whql(struct rtw89_dev *rtwdev)
4768 {
4769 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4770 
4771 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4772 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL);
4773 }
4774 
_action_bt_off(struct rtw89_dev * rtwdev)4775 static void _action_bt_off(struct rtw89_dev *rtwdev)
4776 {
4777 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4778 
4779 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
4780 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF);
4781 }
4782 
_action_bt_idle(struct rtw89_dev * rtwdev)4783 static void _action_bt_idle(struct rtw89_dev *rtwdev)
4784 {
4785 	struct rtw89_btc *btc = &rtwdev->btc;
4786 	struct rtw89_btc_bt_link_info *b = &btc->cx.bt.link_info;
4787 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4788 
4789 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4790 
4791 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
4792 		switch (btc->cx.state_map) {
4793 		case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/
4794 		case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */
4795 			if (b->status.map.connect)
4796 				_set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_IDLE);
4797 			else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
4798 				_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_DL, BTC_ACT_BT_IDLE);
4799 			else
4800 				_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_UL, BTC_ACT_BT_IDLE);
4801 			break;
4802 		case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */
4803 			_set_policy(rtwdev, BTC_CXP_PFIX_TD5050,
4804 				    BTC_ACT_BT_IDLE);
4805 			break;
4806 		case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */
4807 			_set_policy(rtwdev, BTC_CXP_FIX_TD5050,
4808 				    BTC_ACT_BT_IDLE);
4809 			break;
4810 		case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */
4811 			_set_policy(rtwdev, BTC_CXP_FIX_TD7010,
4812 				    BTC_ACT_BT_IDLE);
4813 			break;
4814 		case BTC_WIDLE:  /* wl-idle + bt-idle */
4815 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE);
4816 			break;
4817 		}
4818 	} else { /* dedicated-antenna */
4819 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE);
4820 	}
4821 }
4822 
_action_bt_hfp(struct rtw89_dev * rtwdev)4823 static void _action_bt_hfp(struct rtw89_dev *rtwdev)
4824 {
4825 	struct rtw89_btc *btc = &rtwdev->btc;
4826 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4827 
4828 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4829 
4830 	if (btc->ant_type == BTC_ANT_SHARED) {
4831 		if (btc->cx.wl.status.map._4way) {
4832 			_set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP);
4833 		} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4834 			btc->cx.bt.scan_rx_low_pri = true;
4835 			_set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP);
4836 		} else {
4837 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
4838 		}
4839 	} else {
4840 		if (wl->bg_mode)
4841 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
4842 		else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
4843 			_set_policy(rtwdev, BTC_CXP_OFF_EQ5, BTC_ACT_BT_HFP);
4844 		else
4845 			_set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP);
4846 	}
4847 }
4848 
_action_bt_hid(struct rtw89_dev * rtwdev)4849 static void _action_bt_hid(struct rtw89_dev *rtwdev)
4850 {
4851 	const struct rtw89_chip_info *chip = rtwdev->chip;
4852 	struct rtw89_btc *btc = &rtwdev->btc;
4853 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4854 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4855 	struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc;
4856 	u16 policy_type = BTC_CXP_OFF_BT;
4857 
4858 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4859 
4860 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
4861 		if (wl->status.map._4way) {
4862 			policy_type = BTC_CXP_OFF_WL;
4863 		} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4864 			btc->cx.bt.scan_rx_low_pri = true;
4865 			if (hid->type & BTC_HID_BLE)
4866 				policy_type = BTC_CXP_OFF_BWB0;
4867 			else
4868 				policy_type = BTC_CXP_OFF_BWB2;
4869 		} else if (hid->type == BTC_HID_218) {
4870 			bt->scan_rx_low_pri = true;
4871 			policy_type = BTC_CXP_OFF_BWB2;
4872 		} else if (chip->para_ver == 0x1) {
4873 			policy_type = BTC_CXP_OFF_BWB3;
4874 		} else {
4875 			policy_type = BTC_CXP_OFF_BWB1;
4876 		}
4877 	} else { /* dedicated-antenna */
4878 		if (wl->bg_mode)
4879 			policy_type = BTC_CXP_OFF_BWB1;
4880 		else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
4881 			policy_type = BTC_CXP_OFF_EQ4;
4882 		else
4883 			policy_type = BTC_CXP_OFF_EQ3;
4884 	}
4885 
4886 	_set_policy(rtwdev, policy_type, BTC_ACT_BT_HID);
4887 }
4888 
_action_bt_a2dp(struct rtw89_dev * rtwdev)4889 static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
4890 {
4891 	struct rtw89_btc *btc = &rtwdev->btc;
4892 	struct rtw89_btc_dm *dm = &btc->dm;
4893 
4894 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4895 
4896 	dm->slot_dur[CXST_W1] = 20;
4897 	dm->slot_dur[CXST_B1] = BTC_B1_MAX;
4898 
4899 	switch (btc->cx.state_map) {
4900 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
4901 		_set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
4902 		break;
4903 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
4904 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP);
4905 		break;
4906 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */
4907 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP);
4908 		break;
4909 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
4910 	case BTC_WLINKING: /* wl-connecting + bt-A2DP */
4911 		if (btc->cx.wl.rfk_info.con_rfk)
4912 			_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP);
4913 		else
4914 			_set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP);
4915 		break;
4916 	case BTC_WIDLE:  /* wl-idle + bt-A2DP */
4917 		_set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP);
4918 		break;
4919 	}
4920 }
4921 
_action_bt_a2dpsink(struct rtw89_dev * rtwdev)4922 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev)
4923 {
4924 	struct rtw89_btc *btc = &rtwdev->btc;
4925 
4926 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4927 
4928 	switch (btc->cx.state_map) {
4929 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */
4930 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK);
4931 		break;
4932 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */
4933 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK);
4934 		break;
4935 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */
4936 		_set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK);
4937 		break;
4938 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */
4939 		_set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK);
4940 		break;
4941 	case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */
4942 		if (btc->cx.wl.rfk_info.con_rfk)
4943 			_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DPSINK);
4944 		else
4945 			_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
4946 		break;
4947 	case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */
4948 		_set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK);
4949 		break;
4950 	}
4951 }
4952 
_action_bt_pan(struct rtw89_dev * rtwdev)4953 static void _action_bt_pan(struct rtw89_dev *rtwdev)
4954 {
4955 	struct rtw89_btc *btc = &rtwdev->btc;
4956 	struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
4957 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
4958 	struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
4959 
4960 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4961 
4962 	switch (btc->cx.state_map) {
4963 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */
4964 		if (a2dp.active || !pan.exist) {
4965 			btc->dm.slot_dur[CXST_W1] = 80;
4966 			btc->dm.slot_dur[CXST_B1] = 20;
4967 			_set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN);
4968 		} else {
4969 			_set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
4970 		}
4971 		break;
4972 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */
4973 		_set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN);
4974 		break;
4975 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */
4976 		_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN);
4977 		break;
4978 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */
4979 		_set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN);
4980 		break;
4981 	case BTC_WLINKING: /* wl-connecting + bt-PAN */
4982 		_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO, BTC_ACT_BT_PAN);
4983 		break;
4984 	case BTC_WIDLE: /* wl-idle + bt-pan */
4985 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN);
4986 		break;
4987 	}
4988 }
4989 
_action_bt_a2dp_hid(struct rtw89_dev * rtwdev)4990 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
4991 {
4992 	struct rtw89_btc *btc = &rtwdev->btc;
4993 	struct rtw89_btc_dm *dm = &btc->dm;
4994 
4995 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4996 
4997 	dm->slot_dur[CXST_W1] = 20;
4998 	dm->slot_dur[CXST_B1] = BTC_B1_MAX;
4999 
5000 	switch (btc->cx.state_map) {
5001 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */
5002 	case BTC_WIDLE:  /* wl-idle + bt-A2DP */
5003 		_set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
5004 		break;
5005 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */
5006 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_HID);
5007 		break;
5008 
5009 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */
5010 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
5011 		break;
5012 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */
5013 	case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */
5014 		if (btc->cx.wl.rfk_info.con_rfk)
5015 			_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP_HID);
5016 		else
5017 			_set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
5018 		break;
5019 	}
5020 }
5021 
_action_bt_a2dp_pan(struct rtw89_dev * rtwdev)5022 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev)
5023 {
5024 	struct rtw89_btc *btc = &rtwdev->btc;
5025 
5026 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5027 
5028 	switch (btc->cx.state_map) {
5029 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */
5030 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
5031 		break;
5032 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */
5033 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
5034 		break;
5035 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */
5036 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN);
5037 		break;
5038 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */
5039 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
5040 		break;
5041 	case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */
5042 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN);
5043 		break;
5044 	case BTC_WIDLE:  /* wl-idle + bt-A2DP+PAN */
5045 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN);
5046 		break;
5047 	}
5048 }
5049 
_action_bt_pan_hid(struct rtw89_dev * rtwdev)5050 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev)
5051 {
5052 	struct rtw89_btc *btc = &rtwdev->btc;
5053 
5054 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5055 
5056 	switch (btc->cx.state_map) {
5057 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */
5058 		_set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID);
5059 		break;
5060 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */
5061 		_set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID);
5062 		break;
5063 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */
5064 		_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID);
5065 		break;
5066 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */
5067 		_set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID);
5068 		break;
5069 	case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */
5070 		_set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID);
5071 		break;
5072 	case BTC_WIDLE: /* wl-idle + bt-PAN+HID */
5073 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID);
5074 		break;
5075 	}
5076 }
5077 
_action_bt_a2dp_pan_hid(struct rtw89_dev * rtwdev)5078 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev)
5079 {
5080 	struct rtw89_btc *btc = &rtwdev->btc;
5081 
5082 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5083 
5084 	switch (btc->cx.state_map) {
5085 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */
5086 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
5087 			    BTC_ACT_BT_A2DP_PAN_HID);
5088 		break;
5089 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */
5090 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
5091 			    BTC_ACT_BT_A2DP_PAN_HID);
5092 		break;
5093 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */
5094 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3070,
5095 			    BTC_ACT_BT_A2DP_PAN_HID);
5096 		break;
5097 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */
5098 	case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */
5099 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050,
5100 			    BTC_ACT_BT_A2DP_PAN_HID);
5101 		break;
5102 	case BTC_WIDLE:  /* wl-idle + bt-A2DP+PAN+HID */
5103 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080,
5104 			    BTC_ACT_BT_A2DP_PAN_HID);
5105 		break;
5106 	}
5107 }
5108 
_action_wl_5g(struct rtw89_dev * rtwdev)5109 static void _action_wl_5g(struct rtw89_dev *rtwdev)
5110 {
5111 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
5112 	_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G);
5113 }
5114 
_action_wl_other(struct rtw89_dev * rtwdev)5115 static void _action_wl_other(struct rtw89_dev *rtwdev)
5116 {
5117 	struct rtw89_btc *btc = &rtwdev->btc;
5118 
5119 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5120 
5121 	if (btc->ant_type == BTC_ANT_SHARED)
5122 		_set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER);
5123 	else
5124 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER);
5125 }
5126 
_action_wl_nc(struct rtw89_dev * rtwdev)5127 static void _action_wl_nc(struct rtw89_dev *rtwdev)
5128 {
5129 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5130 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC);
5131 }
5132 
_action_wl_rfk(struct rtw89_dev * rtwdev)5133 static void _action_wl_rfk(struct rtw89_dev *rtwdev)
5134 {
5135 	struct rtw89_btc *btc = &rtwdev->btc;
5136 	struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info;
5137 
5138 	if (rfk.state != BTC_WRFK_START)
5139 		return;
5140 
5141 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n",
5142 		    __func__, rfk.band);
5143 
5144 	btc->dm.tdma_instant_excute = 1;
5145 
5146 	if (rfk.state == BTC_WRFK_ONESHOT_START ||
5147 	    btc->ant_type == BTC_ANT_SHARED) {
5148 		_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2);
5149 		_set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK);
5150 	} else {
5151 		_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
5152 		_set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK);
5153 	}
5154 }
5155 
_set_btg_ctrl(struct rtw89_dev * rtwdev)5156 static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
5157 {
5158 	struct rtw89_btc *btc = &rtwdev->btc;
5159 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5160 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5161 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5162 	struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
5163 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5164 	struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info;
5165 	struct rtw89_btc_wl_role_info *wl_rinfo_v0 = &wl->role_info;
5166 	const struct rtw89_chip_info *chip = rtwdev->chip;
5167 	const struct rtw89_btc_ver *ver = btc->ver;
5168 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5169 	struct rtw89_btc_dm *dm = &btc->dm;
5170 	struct _wl_rinfo_now wl_rinfo;
5171 	u32 is_btg = BTC_BTGCTRL_DISABLE;
5172 
5173 	if (btc->manual_ctrl)
5174 		return;
5175 
5176 	if (ver->fwlrole == 0)
5177 		wl_rinfo.link_mode = wl_rinfo_v0->link_mode;
5178 	else if (ver->fwlrole == 1)
5179 		wl_rinfo.link_mode = wl_rinfo_v1->link_mode;
5180 	else if (ver->fwlrole == 2)
5181 		wl_rinfo.link_mode = wl_rinfo_v2->link_mode;
5182 	else if (ver->fwlrole == 7)
5183 		wl_rinfo.link_mode = wl_rinfo_v7->link_mode;
5184 	else if (ver->fwlrole == 8)
5185 		wl_rinfo.link_mode = wl_rinfo_v8->link_mode;
5186 	else
5187 		return;
5188 
5189 	/* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */
5190 	if (btc->ant_type == BTC_ANT_SHARED) {
5191 		if (!(bt->run_patch_code && bt->enable.now))
5192 			is_btg = BTC_BTGCTRL_DISABLE;
5193 		else if (wl_rinfo.link_mode != BTC_WLINK_5G)
5194 			is_btg = BTC_BTGCTRL_ENABLE;
5195 		else
5196 			is_btg = BTC_BTGCTRL_DISABLE;
5197 
5198 		/* bb call ctrl_btg() in WL FW by slot */
5199 		if (!ver->fcxosi &&
5200 		    wl_rinfo.link_mode == BTC_WLINK_25G_MCC)
5201 			is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL;
5202 	}
5203 
5204 	if (is_btg == dm->wl_btg_rx)
5205 		return;
5206 	else
5207 		dm->wl_btg_rx = is_btg;
5208 
5209 	/* skip setup if btg_ctrl set by wl fw */
5210 	if (!ver->fcxosi && is_btg > BTC_BTGCTRL_ENABLE)
5211 		return;
5212 
5213 	/* Below flow is for BTC_FEAT_NEW_BBAPI_FLOW = 1 */
5214 	if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */
5215 		if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */
5216 			o_info->btg_rx[BTC_RF_S0] = BTC_BTGCTRL_DISABLE;
5217 		else
5218 			o_info->btg_rx[BTC_RF_S0] = is_btg;
5219 
5220 		if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */
5221 			o_info->btg_rx[BTC_RF_S1] = BTC_BTGCTRL_DISABLE;
5222 		else
5223 			o_info->btg_rx[BTC_RF_S1] = is_btg;
5224 	} else { /* 2+0 or 0+2 */
5225 		o_info->btg_rx[BTC_RF_S0] = is_btg;
5226 		o_info->btg_rx[BTC_RF_S1] = is_btg;
5227 	}
5228 
5229 	if (ver->fcxosi)
5230 		return;
5231 
5232 	chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S0],
5233 				  RTW89_PHY_0);
5234 	if (chip->chip_id != RTL8922A)
5235 		return;
5236 
5237 	chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S1],
5238 				  RTW89_PHY_1);
5239 }
5240 
_set_wl_preagc_ctrl(struct rtw89_dev * rtwdev)5241 static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev)
5242 {
5243 	struct rtw89_btc *btc = &rtwdev->btc;
5244 	struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info;
5245 	struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
5246 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5247 	struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2;
5248 	struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
5249 	struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8;
5250 	const struct rtw89_chip_info *chip = rtwdev->chip;
5251 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5252 	struct rtw89_btc_dm *dm = &btc->dm;
5253 	u8 is_preagc, val, link_mode, dbcc_2g_phy;
5254 	u8 role_ver = rtwdev->btc.ver->fwlrole;
5255 	bool dbcc_en;
5256 
5257 	if (btc->manual_ctrl)
5258 		return;
5259 
5260 	if (role_ver == 2) {
5261 		dbcc_en = rinfo_v2->dbcc_en;
5262 		link_mode = rinfo_v2->link_mode;
5263 		dbcc_2g_phy = rinfo_v2->dbcc_2g_phy;
5264 	} else if (role_ver == 7) {
5265 		dbcc_en = rinfo_v7->dbcc_en;
5266 		link_mode = rinfo_v7->link_mode;
5267 		dbcc_2g_phy = rinfo_v7->dbcc_2g_phy;
5268 	} else if (role_ver == 8) {
5269 		dbcc_en = rinfo_v8->dbcc_en;
5270 		link_mode = rinfo_v8->link_mode;
5271 		dbcc_2g_phy = rinfo_v7->dbcc_2g_phy;
5272 	} else {
5273 		return;
5274 	}
5275 
5276 	if (!(bt->run_patch_code && bt->enable.now)) {
5277 		is_preagc = BTC_PREAGC_DISABLE;
5278 	} else if (link_mode == BTC_WLINK_5G) {
5279 		is_preagc = BTC_PREAGC_DISABLE;
5280 	} else if (link_mode == BTC_WLINK_NOLINK ||
5281 		 btc->cx.bt.link_info.profile_cnt.now == 0) {
5282 		is_preagc = BTC_PREAGC_DISABLE;
5283 	} else if (dm->tdma_now.type != CXTDMA_OFF &&
5284 		 !bt_linfo->hfp_desc.exist &&
5285 		 !bt_linfo->hid_desc.exist &&
5286 		 dm->fddt_train == BTC_FDDT_DISABLE) {
5287 		is_preagc = BTC_PREAGC_DISABLE;
5288 	} else if (dbcc_en && (dbcc_2g_phy != RTW89_PHY_1)) {
5289 		is_preagc = BTC_PREAGC_DISABLE;
5290 	} else if (btc->ant_type == BTC_ANT_SHARED) {
5291 		is_preagc = BTC_PREAGC_DISABLE;
5292 	} else {
5293 		is_preagc = BTC_PREAGC_ENABLE;
5294 	}
5295 
5296 	if (!btc->ver->fcxosi && link_mode == BTC_WLINK_25G_MCC)
5297 		is_preagc = BTC_PREAGC_BB_FWCTRL;
5298 
5299 	if (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
5300 	    dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) {
5301 		_get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val);
5302 		dm->wl_pre_agc_rb = val;
5303 	}
5304 
5305 	if ((wl->coex_mode == BTC_MODE_NORMAL &&
5306 	     (dm->run_reason == BTC_RSN_NTFY_INIT ||
5307 	      dm->run_reason == BTC_RSN_NTFY_SWBAND ||
5308 	      dm->wl_pre_agc_rb != dm->wl_pre_agc)) ||
5309 	    is_preagc != dm->wl_pre_agc) {
5310 		dm->wl_pre_agc = is_preagc;
5311 
5312 		if (!btc->ver->fcxosi && is_preagc > BTC_PREAGC_ENABLE)
5313 			return;
5314 
5315 		if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */
5316 			if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */
5317 				o_info->nbtg_tx[BTC_RF_S0] = BTC_PREAGC_DISABLE;
5318 			else
5319 				o_info->nbtg_tx[BTC_RF_S0] = is_preagc;
5320 
5321 			if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */
5322 				o_info->nbtg_tx[BTC_RF_S1] = BTC_PREAGC_DISABLE;
5323 			else
5324 				o_info->nbtg_tx[BTC_RF_S1] = is_preagc;
5325 
5326 		} else { /* 2+0 or 0+2 */
5327 			o_info->nbtg_tx[BTC_RF_S0] = is_preagc;
5328 			o_info->nbtg_tx[BTC_RF_S1] = is_preagc;
5329 		}
5330 
5331 		if (btc->ver->fcxosi)
5332 			return;
5333 
5334 		chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S0],
5335 					   RTW89_PHY_0);
5336 		if (chip->chip_id != RTL8922A)
5337 			return;
5338 		chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S1],
5339 					   RTW89_PHY_1);
5340 	}
5341 }
5342 
5343 struct rtw89_txtime_data {
5344 	struct rtw89_dev *rtwdev;
5345 	int type;
5346 	u32 tx_time;
5347 	u8 tx_retry;
5348 	u16 enable;
5349 	bool reenable;
5350 };
5351 
__rtw89_tx_time_iter(struct rtw89_vif_link * rtwvif_link,struct rtw89_sta_link * rtwsta_link,struct rtw89_txtime_data * iter_data)5352 static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link,
5353 				 struct rtw89_sta_link *rtwsta_link,
5354 				 struct rtw89_txtime_data *iter_data)
5355 {
5356 	struct rtw89_dev *rtwdev = iter_data->rtwdev;
5357 	struct rtw89_btc *btc = &rtwdev->btc;
5358 	struct rtw89_btc_cx *cx = &btc->cx;
5359 	struct rtw89_btc_wl_info *wl = &cx->wl;
5360 	struct rtw89_btc_wl_link_info *plink = NULL;
5361 	u8 port = rtwvif_link->port;
5362 	u32 tx_time = iter_data->tx_time;
5363 	u8 tx_retry = iter_data->tx_retry;
5364 	u16 enable = iter_data->enable;
5365 	bool reenable = iter_data->reenable;
5366 
5367 	if (btc->ver->fwlrole == 8)
5368 		plink = &wl->rlink_info[port][0];
5369 	else
5370 		plink = &wl->link_info[port];
5371 
5372 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
5373 		    "[BTC], %s(): port = %d\n", __func__, port);
5374 
5375 	if (!plink->connected) {
5376 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
5377 			    "[BTC], %s(): connected = %d\n",
5378 			    __func__, plink->connected);
5379 		return;
5380 	}
5381 
5382 	/* backup the original tx time before tx-limit on */
5383 	if (reenable) {
5384 		rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time);
5385 		rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry);
5386 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
5387 			    "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n",
5388 			    __func__, plink->tx_time, plink->tx_retry);
5389 	}
5390 
5391 	/* restore the original tx time if no tx-limit */
5392 	if (!enable) {
5393 		rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time);
5394 		rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true,
5395 					     plink->tx_retry);
5396 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
5397 			    "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n",
5398 			    __func__, plink->tx_time, plink->tx_retry);
5399 
5400 	} else {
5401 		rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time);
5402 		rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry);
5403 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
5404 			    "[BTC], %s(): set, tx_time=%d tx_retry= %d\n",
5405 			    __func__, tx_time, tx_retry);
5406 	}
5407 }
5408 
rtw89_tx_time_iter(void * data,struct ieee80211_sta * sta)5409 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
5410 {
5411 	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
5412 	struct rtw89_txtime_data *iter_data =
5413 				(struct rtw89_txtime_data *)data;
5414 	struct rtw89_vif_link *rtwvif_link;
5415 	struct rtw89_sta_link *rtwsta_link;
5416 	unsigned int link_id;
5417 
5418 	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
5419 		rtwvif_link = rtwsta_link->rtwvif_link;
5420 		__rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data);
5421 	}
5422 }
5423 
_set_wl_tx_limit(struct rtw89_dev * rtwdev)5424 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
5425 {
5426 	struct rtw89_btc *btc = &rtwdev->btc;
5427 	const struct rtw89_btc_ver *ver = btc->ver;
5428 	struct rtw89_btc_cx *cx = &btc->cx;
5429 	struct rtw89_btc_dm *dm = &btc->dm;
5430 	struct rtw89_btc_wl_info *wl = &cx->wl;
5431 	struct rtw89_btc_bt_info *bt = &cx->bt;
5432 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
5433 	struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
5434 	struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
5435 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5436 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5437 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5438 	struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
5439 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5440 	struct rtw89_txtime_data data = {.rtwdev = rtwdev};
5441 	u8 mode, igno_bt, tx_retry;
5442 	u32 tx_time;
5443 	u16 enable;
5444 	bool reenable = false;
5445 
5446 	if (btc->manual_ctrl)
5447 		return;
5448 
5449 	if (ver->fwlrole == 0)
5450 		mode = wl_rinfo->link_mode;
5451 	else if (ver->fwlrole == 1)
5452 		mode = wl_rinfo_v1->link_mode;
5453 	else if (ver->fwlrole == 2)
5454 		mode = wl_rinfo_v2->link_mode;
5455 	else if (ver->fwlrole == 7)
5456 		mode = wl_rinfo_v7->link_mode;
5457 	else if (ver->fwlrole == 8)
5458 		mode = wl_rinfo_v8->link_mode;
5459 	else
5460 		return;
5461 
5462 	if (ver->fcxctrl == 7)
5463 		igno_bt = btc->ctrl.ctrl_v7.igno_bt;
5464 	else
5465 		igno_bt = btc->ctrl.ctrl.igno_bt;
5466 
5467 	if (btc->dm.freerun || igno_bt || b->profile_cnt.now == 0 ||
5468 	    mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) {
5469 		enable = 0;
5470 		tx_time = BTC_MAX_TX_TIME_DEF;
5471 		tx_retry = BTC_MAX_TX_RETRY_DEF;
5472 	} else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) {
5473 		enable = 1;
5474 		tx_time = BTC_MAX_TX_TIME_L2;
5475 		tx_retry = BTC_MAX_TX_RETRY_L1;
5476 	} else if (hfp->exist || hid->exist) {
5477 		enable = 1;
5478 		tx_time = BTC_MAX_TX_TIME_L3;
5479 		tx_retry = BTC_MAX_TX_RETRY_L1;
5480 	} else {
5481 		enable = 0;
5482 		tx_time = BTC_MAX_TX_TIME_DEF;
5483 		tx_retry = BTC_MAX_TX_RETRY_DEF;
5484 	}
5485 
5486 	if (dm->wl_tx_limit.enable == enable &&
5487 	    dm->wl_tx_limit.tx_time == tx_time &&
5488 	    dm->wl_tx_limit.tx_retry == tx_retry)
5489 		return;
5490 
5491 	if (!dm->wl_tx_limit.enable && enable)
5492 		reenable = true;
5493 
5494 	dm->wl_tx_limit.enable = enable;
5495 	dm->wl_tx_limit.tx_time = tx_time;
5496 	dm->wl_tx_limit.tx_retry = tx_retry;
5497 
5498 	data.enable = enable;
5499 	data.tx_time = tx_time;
5500 	data.tx_retry = tx_retry;
5501 	data.reenable = reenable;
5502 
5503 	ieee80211_iterate_stations_atomic(rtwdev->hw,
5504 					  rtw89_tx_time_iter,
5505 					  &data);
5506 }
5507 
_set_bt_rx_agc(struct rtw89_dev * rtwdev)5508 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
5509 {
5510 	struct rtw89_btc *btc = &rtwdev->btc;
5511 	const struct rtw89_btc_ver *ver = btc->ver;
5512 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5513 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5514 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5515 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5516 	struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
5517 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5518 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5519 	bool bt_hi_lna_rx = false;
5520 	u8 mode;
5521 
5522 	if (ver->fwlrole == 0)
5523 		mode = wl_rinfo->link_mode;
5524 	else if (ver->fwlrole == 1)
5525 		mode = wl_rinfo_v1->link_mode;
5526 	else if (ver->fwlrole == 2)
5527 		mode = wl_rinfo_v2->link_mode;
5528 	else if (ver->fwlrole == 7)
5529 		mode = wl_rinfo_v7->link_mode;
5530 	else if (ver->fwlrole == 8)
5531 		mode = wl_rinfo_v8->link_mode;
5532 	else
5533 		return;
5534 
5535 	if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
5536 		bt_hi_lna_rx = true;
5537 
5538 	if (bt_hi_lna_rx == bt->hi_lna_rx)
5539 		return;
5540 
5541 	_write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx);
5542 }
5543 
_set_bt_rx_scan_pri(struct rtw89_dev * rtwdev)5544 static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev)
5545 {
5546 	struct rtw89_btc *btc = &rtwdev->btc;
5547 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5548 
5549 	_write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri));
5550 }
5551 
_wl_req_mac(struct rtw89_dev * rtwdev,u8 mac)5552 static void _wl_req_mac(struct rtw89_dev *rtwdev, u8 mac)
5553 {
5554 	struct rtw89_btc *btc = &rtwdev->btc;
5555 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5556 	struct rtw89_btc_dm *dm = &btc->dm;
5557 	u32 add;
5558 
5559 	if (mac == wl->pta_req_mac)
5560 		return;
5561 
5562 	dm->ost_info.pta_req_hw_band = mac;
5563 	wl->pta_req_mac = mac;
5564 	wl->pta_reg_mac_chg = true;
5565 
5566 	if (btc->ver->fcxosi)
5567 		return;
5568 
5569 	if (rtwdev->chip->chip_gen == RTW89_CHIP_BE)
5570 		add = R_BE_BTC_CFG;
5571 	else
5572 		add = R_AX_BTC_CFG;
5573 
5574 	if (mac == RTW89_MAC_0)
5575 		rtw89_write32_clr(rtwdev, add, B_AX_WL_SRC);
5576 	else
5577 		rtw89_write32_set(rtwdev, add, B_AX_WL_SRC);
5578 }
5579 
_action_common(struct rtw89_dev * rtwdev)5580 static void _action_common(struct rtw89_dev *rtwdev)
5581 {
5582 	struct rtw89_btc *btc = &rtwdev->btc;
5583 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5584 	struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8;
5585 	struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
5586 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5587 	struct rtw89_btc_dm *dm = &btc->dm;
5588 	u32 bt_rom_code_id, bt_fw_ver;
5589 
5590 	if (btc->ver->fwlrole == 8)
5591 		_wl_req_mac(rtwdev, rinfo_v8->pta_req_band);
5592 
5593 	_set_btg_ctrl(rtwdev);
5594 	_set_wl_preagc_ctrl(rtwdev);
5595 	_set_wl_tx_limit(rtwdev);
5596 	_set_bt_afh_info(rtwdev);
5597 	_set_bt_rx_agc(rtwdev);
5598 	_set_rf_trx_para(rtwdev);
5599 	_set_bt_rx_scan_pri(rtwdev);
5600 
5601 	bt_rom_code_id = chip_id_to_bt_rom_code_id(rtwdev->btc.ver->chip_id);
5602 	bt_fw_ver = bt->ver_info.fw & 0xffff;
5603 	if (bt->enable.now &&
5604 	    (bt_fw_ver == 0 ||
5605 	     (bt_fw_ver == bt_rom_code_id && bt->run_patch_code && rtwdev->chip->scbd)))
5606 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 1);
5607 	else
5608 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 0);
5609 
5610 	if (dm->run_reason == BTC_RSN_NTFY_INIT ||
5611 	    dm->run_reason == BTC_RSN_NTFY_RADIO_STATE ||
5612 	    dm->run_reason == BTC_RSN_NTFY_POWEROFF) {
5613 		_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
5614 
5615 		if (wl_smap->rf_off == 1 || wl_smap->lps != BTC_LPS_OFF)
5616 			rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
5617 		else
5618 			rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
5619 	}
5620 
5621 	if (wl->scbd_change) {
5622 		rtw89_mac_cfg_sb(rtwdev, wl->scbd);
5623 		rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n",
5624 			    wl->scbd);
5625 		wl->scbd_change = false;
5626 		btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++;
5627 	}
5628 
5629 	if (btc->ver->fcxosi) {
5630 		if (memcmp(&dm->ost_info_last, &dm->ost_info,
5631 			   sizeof(dm->ost_info_last)) ||
5632 		    dm->run_reason == BTC_RSN_NTFY_INIT ||
5633 		    dm->run_reason == BTC_RSN_NTFY_RADIO_STATE) {
5634 			dm->ost_info_last = dm->ost_info;
5635 			_fw_set_drv_info(rtwdev, CXDRVINFO_OSI);
5636 		}
5637 	}
5638 	btc->dm.tdma_instant_excute = 0;
5639 	wl->pta_reg_mac_chg = false;
5640 }
5641 
_action_by_bt(struct rtw89_dev * rtwdev)5642 static void _action_by_bt(struct rtw89_dev *rtwdev)
5643 {
5644 	struct rtw89_btc *btc = &rtwdev->btc;
5645 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5646 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
5647 	struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
5648 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
5649 	struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
5650 	struct rtw89_btc_dm *dm = &btc->dm;
5651 	u8 profile_map = 0;
5652 
5653 	if (dm->freerun_chk) {
5654 		_action_freerun(rtwdev);
5655 		return;
5656 	}
5657 
5658 	if (bt_linfo->hfp_desc.exist)
5659 		profile_map |= BTC_BT_HFP;
5660 
5661 	if (bt_linfo->hid_desc.exist)
5662 		profile_map |= BTC_BT_HID;
5663 
5664 	if (bt_linfo->a2dp_desc.exist)
5665 		profile_map |= BTC_BT_A2DP;
5666 
5667 	if (bt_linfo->pan_desc.exist)
5668 		profile_map |= BTC_BT_PAN;
5669 
5670 	switch (profile_map) {
5671 	case BTC_BT_NOPROFILE:
5672 		if (pan.active)
5673 			_action_bt_pan(rtwdev);
5674 		else
5675 			_action_bt_idle(rtwdev);
5676 		break;
5677 	case BTC_BT_HFP:
5678 		_action_bt_hfp(rtwdev);
5679 		break;
5680 	case BTC_BT_HFP | BTC_BT_HID:
5681 	case BTC_BT_HID:
5682 		_action_bt_hid(rtwdev);
5683 		break;
5684 	case BTC_BT_A2DP:
5685 		if (a2dp.sink)
5686 			_action_bt_a2dpsink(rtwdev);
5687 		else if (bt_linfo->multi_link.now && !hid.pair_cnt)
5688 			_action_bt_a2dp_pan(rtwdev);
5689 		else
5690 			_action_bt_a2dp(rtwdev);
5691 		break;
5692 	case BTC_BT_PAN:
5693 		_action_bt_pan(rtwdev);
5694 		break;
5695 	case BTC_BT_A2DP | BTC_BT_HFP:
5696 	case BTC_BT_A2DP | BTC_BT_HID:
5697 	case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID:
5698 		if (a2dp.sink)
5699 			_action_bt_a2dpsink(rtwdev);
5700 		else if (pan.active)
5701 			_action_bt_a2dp_pan_hid(rtwdev);
5702 		else
5703 			_action_bt_a2dp_hid(rtwdev);
5704 		break;
5705 	case BTC_BT_A2DP | BTC_BT_PAN:
5706 		if (a2dp.sink)
5707 			_action_bt_a2dpsink(rtwdev);
5708 		else
5709 			_action_bt_a2dp_pan(rtwdev);
5710 		break;
5711 	case BTC_BT_PAN | BTC_BT_HFP:
5712 	case BTC_BT_PAN | BTC_BT_HID:
5713 	case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID:
5714 		_action_bt_pan_hid(rtwdev);
5715 		break;
5716 	case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID:
5717 	case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP:
5718 	default:
5719 		if (a2dp.sink)
5720 			_action_bt_a2dpsink(rtwdev);
5721 		else
5722 			_action_bt_a2dp_pan_hid(rtwdev);
5723 		break;
5724 	}
5725 }
5726 
_action_wl_2g_sta(struct rtw89_dev * rtwdev)5727 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev)
5728 {
5729 	_action_by_bt(rtwdev);
5730 }
5731 
_action_wl_25g_mcc(struct rtw89_dev * rtwdev)5732 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev)
5733 {
5734 	struct rtw89_btc *btc = &rtwdev->btc;
5735 	u16 policy_type = BTC_CXP_OFF_BT;
5736 
5737 	if (btc->ant_type == BTC_ANT_SHARED) {
5738 		if (btc->cx.wl.status.map._4way)
5739 			policy_type = BTC_CXP_OFFE_WL;
5740 		else if (btc->cx.wl.status.val & btc_scanning_map.val)
5741 			policy_type = BTC_CXP_OFFE_2GBWMIXB;
5742 		else if (btc->cx.bt.link_info.status.map.connect == 0)
5743 			policy_type = BTC_CXP_OFFE_2GISOB;
5744 		else
5745 			policy_type = BTC_CXP_OFFE_2GBWISOB;
5746 	} else { /* dedicated-antenna */
5747 		policy_type = BTC_CXP_OFF_EQ0;
5748 	}
5749 
5750 	btc->dm.e2g_slot_limit = BTC_E2G_LIMIT_DEF;
5751 
5752 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
5753 	_set_policy(rtwdev, policy_type, BTC_ACT_WL_25G_MCC);
5754 }
5755 
_action_wl_scan(struct rtw89_dev * rtwdev)5756 static void _action_wl_scan(struct rtw89_dev *rtwdev)
5757 {
5758 	struct rtw89_btc *btc = &rtwdev->btc;
5759 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5760 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5761 
5762 	if (btc->cx.state_map != BTC_WLINKING &&
5763 	    RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
5764 		_action_wl_25g_mcc(rtwdev);
5765 		rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n");
5766 	} else if (rtwdev->dbcc_en) {
5767 		if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G &&
5768 		    wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
5769 			_action_wl_5g(rtwdev);
5770 		else
5771 			_action_by_bt(rtwdev);
5772 	} else {
5773 		if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G)
5774 			_action_wl_5g(rtwdev);
5775 		else
5776 			_action_by_bt(rtwdev);
5777 	}
5778 }
5779 
_action_wl_2g_mcc(struct rtw89_dev * rtwdev)5780 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev)
5781 {	struct rtw89_btc *btc = &rtwdev->btc;
5782 
5783 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5784 
5785 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5786 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
5787 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
5788 				    BTC_ACT_WL_2G_MCC);
5789 		else
5790 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF,
5791 				    BTC_ACT_WL_2G_MCC);
5792 	} else { /* dedicated-antenna */
5793 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC);
5794 	}
5795 }
5796 
_action_wl_2g_scc(struct rtw89_dev * rtwdev)5797 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev)
5798 {
5799 	struct rtw89_btc *btc = &rtwdev->btc;
5800 
5801 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5802 
5803 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5804 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
5805 			_set_policy(rtwdev,
5806 				    BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC);
5807 		else
5808 			_set_policy(rtwdev,
5809 				    BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC);
5810 	} else { /* dedicated-antenna */
5811 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC);
5812 	}
5813 }
5814 
_action_wl_2g_scc_v1(struct rtw89_dev * rtwdev)5815 static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev)
5816 {
5817 	struct rtw89_btc *btc = &rtwdev->btc;
5818 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5819 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5820 	struct rtw89_btc_dm *dm = &btc->dm;
5821 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
5822 	u16 policy_type = BTC_CXP_OFF_BT;
5823 	u32 dur;
5824 
5825 	if (btc->ant_type == BTC_ANT_DEDICATED) {
5826 		policy_type = BTC_CXP_OFF_EQ0;
5827 	} else {
5828 		/* shared-antenna */
5829 		switch (wl_rinfo->mrole_type) {
5830 		case BTC_WLMROLE_STA_GC:
5831 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5832 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
5833 			dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5834 			_action_by_bt(rtwdev);
5835 			return;
5836 		case BTC_WLMROLE_STA_STA:
5837 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5838 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
5839 			dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5840 			_action_by_bt(rtwdev);
5841 			return;
5842 		case BTC_WLMROLE_STA_GC_NOA:
5843 		case BTC_WLMROLE_STA_GO:
5844 		case BTC_WLMROLE_STA_GO_NOA:
5845 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5846 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
5847 			dur = wl_rinfo->mrole_noa_duration;
5848 
5849 			if (wl->status.map._4way) {
5850 				dm->wl_scc.ebt_null = 0;
5851 				policy_type = BTC_CXP_OFFE_WL;
5852 			} else if (bt->link_info.status.map.connect == 0) {
5853 				dm->wl_scc.ebt_null = 0;
5854 				policy_type = BTC_CXP_OFFE_2GISOB;
5855 			} else if (bt->link_info.a2dp_desc.exist &&
5856 				   dur < btc->bt_req_len) {
5857 				dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5858 				policy_type = BTC_CXP_OFFE_2GBWMIXB2;
5859 			} else if (bt->link_info.a2dp_desc.exist ||
5860 				   bt->link_info.pan_desc.exist) {
5861 				dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5862 				policy_type = BTC_CXP_OFFE_2GBWISOB;
5863 			} else {
5864 				dm->wl_scc.ebt_null = 0;
5865 				policy_type = BTC_CXP_OFFE_2GBWISOB;
5866 			}
5867 			break;
5868 		default:
5869 			break;
5870 		}
5871 	}
5872 
5873 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5874 	_set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5875 }
5876 
_action_wl_2g_scc_v2(struct rtw89_dev * rtwdev)5877 static void _action_wl_2g_scc_v2(struct rtw89_dev *rtwdev)
5878 {
5879 	struct rtw89_btc *btc = &rtwdev->btc;
5880 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5881 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5882 	struct rtw89_btc_dm *dm = &btc->dm;
5883 	struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2;
5884 	struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
5885 	u32 dur, mrole_type, mrole_noa_duration;
5886 	u16 policy_type = BTC_CXP_OFF_BT;
5887 
5888 	if (btc->ver->fwlrole == 2) {
5889 		mrole_type = rinfo_v2->mrole_type;
5890 		mrole_noa_duration = rinfo_v2->mrole_noa_duration;
5891 	} else if (btc->ver->fwlrole == 7) {
5892 		mrole_type = rinfo_v7->mrole_type;
5893 		mrole_noa_duration = rinfo_v7->mrole_noa_duration;
5894 	} else {
5895 		return;
5896 	}
5897 
5898 	if (btc->ant_type == BTC_ANT_DEDICATED) {
5899 		policy_type = BTC_CXP_OFF_EQ0;
5900 	} else {
5901 		/* shared-antenna */
5902 		switch (mrole_type) {
5903 		case BTC_WLMROLE_STA_GC:
5904 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5905 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
5906 			dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5907 			_action_by_bt(rtwdev);
5908 			return;
5909 		case BTC_WLMROLE_STA_STA:
5910 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5911 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
5912 			dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5913 			_action_by_bt(rtwdev);
5914 			return;
5915 		case BTC_WLMROLE_STA_GC_NOA:
5916 		case BTC_WLMROLE_STA_GO:
5917 		case BTC_WLMROLE_STA_GO_NOA:
5918 			dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5919 			dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
5920 			dur = mrole_noa_duration;
5921 
5922 			if (wl->status.map._4way) {
5923 				dm->wl_scc.ebt_null = 0;
5924 				policy_type = BTC_CXP_OFFE_WL;
5925 			} else if (bt->link_info.status.map.connect == 0) {
5926 				dm->wl_scc.ebt_null = 0;
5927 				policy_type = BTC_CXP_OFFE_2GISOB;
5928 			} else if (bt->link_info.a2dp_desc.exist &&
5929 				   dur < btc->bt_req_len) {
5930 				dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5931 				policy_type = BTC_CXP_OFFE_2GBWMIXB2;
5932 			} else if (bt->link_info.a2dp_desc.exist ||
5933 				   bt->link_info.pan_desc.exist) {
5934 				dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5935 				policy_type = BTC_CXP_OFFE_2GBWISOB;
5936 			} else {
5937 				dm->wl_scc.ebt_null = 0;
5938 				policy_type = BTC_CXP_OFFE_2GBWISOB;
5939 			}
5940 			break;
5941 		default:
5942 			break;
5943 		}
5944 	}
5945 
5946 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5947 	_set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5948 }
5949 
_action_wl_2g_scc_v8(struct rtw89_dev * rtwdev)5950 static void _action_wl_2g_scc_v8(struct rtw89_dev *rtwdev)
5951 {
5952 	struct rtw89_btc *btc = &rtwdev->btc;
5953 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5954 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5955 	struct rtw89_btc_dm *dm = &btc->dm;
5956 	u16 policy_type = BTC_CXP_OFF_BT;
5957 
5958 	if (btc->ant_type == BTC_ANT_SHARED) {
5959 		if (wl->status.map._4way)
5960 			policy_type = BTC_CXP_OFFE_WL;
5961 		else if (bt->link_info.status.map.connect == 0)
5962 			policy_type = BTC_CXP_OFFE_2GISOB;
5963 		else
5964 			policy_type = BTC_CXP_OFFE_2GBWISOB;
5965 	} else {
5966 		policy_type = BTC_CXP_OFF_EQ0;
5967 	}
5968 
5969 	dm->e2g_slot_limit = BTC_E2G_LIMIT_DEF;
5970 
5971 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5972 	_set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5973 }
5974 
_action_wl_2g_ap(struct rtw89_dev * rtwdev)5975 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
5976 {
5977 	struct rtw89_btc *btc = &rtwdev->btc;
5978 
5979 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5980 
5981 	if (btc->ant_type == BTC_ANT_SHARED) {
5982 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
5983 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
5984 				    BTC_ACT_WL_2G_AP);
5985 		else
5986 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP);
5987 	} else {/* dedicated-antenna */
5988 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP);
5989 	}
5990 }
5991 
_action_wl_2g_go(struct rtw89_dev * rtwdev)5992 static void _action_wl_2g_go(struct rtw89_dev *rtwdev)
5993 {
5994 	struct rtw89_btc *btc = &rtwdev->btc;
5995 
5996 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5997 
5998 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5999 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
6000 			_set_policy(rtwdev,
6001 				    BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO);
6002 		else
6003 			_set_policy(rtwdev,
6004 				    BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO);
6005 	} else { /* dedicated-antenna */
6006 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO);
6007 	}
6008 }
6009 
_action_wl_2g_gc(struct rtw89_dev * rtwdev)6010 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev)
6011 {
6012 	struct rtw89_btc *btc = &rtwdev->btc;
6013 
6014 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6015 
6016 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6017 		_action_by_bt(rtwdev);
6018 	} else {/* dedicated-antenna */
6019 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC);
6020 	}
6021 }
6022 
_action_wl_2g_nan(struct rtw89_dev * rtwdev)6023 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev)
6024 {
6025 	struct rtw89_btc *btc = &rtwdev->btc;
6026 
6027 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6028 
6029 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6030 		if (btc->cx.bt.link_info.profile_cnt.now == 0)
6031 			_set_policy(rtwdev,
6032 				    BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN);
6033 		else
6034 			_set_policy(rtwdev,
6035 				    BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN);
6036 	} else { /* dedicated-antenna */
6037 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN);
6038 	}
6039 }
6040 
_read_scbd(struct rtw89_dev * rtwdev)6041 static u32 _read_scbd(struct rtw89_dev *rtwdev)
6042 {
6043 	const struct rtw89_chip_info *chip = rtwdev->chip;
6044 	struct rtw89_btc *btc = &rtwdev->btc;
6045 	u32 scbd_val = 0;
6046 
6047 	if (!chip->scbd)
6048 		return 0;
6049 
6050 	scbd_val = rtw89_mac_get_sb(rtwdev);
6051 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n",
6052 		    scbd_val);
6053 
6054 	btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++;
6055 	return scbd_val;
6056 }
6057 
_write_scbd(struct rtw89_dev * rtwdev,u32 val,bool state)6058 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state)
6059 {
6060 	const struct rtw89_chip_info *chip = rtwdev->chip;
6061 	struct rtw89_btc *btc = &rtwdev->btc;
6062 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6063 	u32 scbd_val = 0;
6064 	u8 force_exec = false;
6065 
6066 	if (!chip->scbd)
6067 		return;
6068 
6069 	scbd_val = state ? wl->scbd | val : wl->scbd & ~val;
6070 
6071 	if (val & BTC_WSCB_ACTIVE || val & BTC_WSCB_ON)
6072 		force_exec = true;
6073 
6074 	if (scbd_val != wl->scbd || force_exec) {
6075 		wl->scbd = scbd_val;
6076 		wl->scbd_change = true;
6077 	}
6078 }
6079 
6080 static u8
_update_rssi_state(struct rtw89_dev * rtwdev,u8 pre_state,u8 rssi,u8 thresh)6081 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh)
6082 {
6083 	const struct rtw89_chip_info *chip = rtwdev->chip;
6084 	u8 next_state, tol = chip->rssi_tol;
6085 
6086 	if (pre_state == BTC_RSSI_ST_LOW ||
6087 	    pre_state == BTC_RSSI_ST_STAY_LOW) {
6088 		if (rssi >= (thresh + tol))
6089 			next_state = BTC_RSSI_ST_HIGH;
6090 		else
6091 			next_state = BTC_RSSI_ST_STAY_LOW;
6092 	} else {
6093 		if (rssi < thresh)
6094 			next_state = BTC_RSSI_ST_LOW;
6095 		else
6096 			next_state = BTC_RSSI_ST_STAY_HIGH;
6097 	}
6098 
6099 	return next_state;
6100 }
6101 
6102 static
_update_dbcc_band(struct rtw89_dev * rtwdev,enum rtw89_phy_idx phy_idx)6103 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
6104 {
6105 	struct rtw89_btc *btc = &rtwdev->btc;
6106 
6107 	btc->cx.wl.dbcc_info.real_band[phy_idx] =
6108 		btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ?
6109 		btc->cx.wl.dbcc_info.scan_band[phy_idx] :
6110 		btc->cx.wl.dbcc_info.op_band[phy_idx];
6111 }
6112 
_update_wl_info(struct rtw89_dev * rtwdev)6113 static void _update_wl_info(struct rtw89_dev *rtwdev)
6114 {
6115 	struct rtw89_btc *btc = &rtwdev->btc;
6116 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6117 	struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6118 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
6119 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6120 	u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
6121 	u8 cnt_2g = 0, cnt_5g = 0, phy;
6122 	u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0};
6123 	bool b2g = false, b5g = false, client_joined = false;
6124 
6125 	memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6126 
6127 	for (i = 0; i < RTW89_PORT_NUM; i++) {
6128 		/* check if role active? */
6129 		if (!wl_linfo[i].active)
6130 			continue;
6131 
6132 		cnt_active++;
6133 		wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role;
6134 		wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid;
6135 		wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy;
6136 		wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band;
6137 		wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
6138 		wl_rinfo->active_role[cnt_active - 1].connected = 0;
6139 
6140 		wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
6141 
6142 		phy = wl_linfo[i].phy;
6143 
6144 		/* check dbcc role */
6145 		if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) {
6146 			wl_dinfo->role[phy] = wl_linfo[i].role;
6147 			wl_dinfo->op_band[phy] = wl_linfo[i].band;
6148 			_update_dbcc_band(rtwdev, phy);
6149 			_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6150 		}
6151 
6152 		if (wl_linfo[i].connected == MLME_NO_LINK) {
6153 			continue;
6154 		} else if (wl_linfo[i].connected == MLME_LINKING) {
6155 			cnt_connecting++;
6156 		} else {
6157 			cnt_connect++;
6158 			if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6159 			     wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6160 			     wl_linfo[i].client_cnt > 1)
6161 				client_joined = true;
6162 		}
6163 
6164 		wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
6165 		wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch;
6166 		wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw;
6167 		wl_rinfo->active_role[cnt_active - 1].connected = 1;
6168 
6169 		/* only care 2 roles + BT coex */
6170 		if (wl_linfo[i].band != RTW89_BAND_2G) {
6171 			if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
6172 				wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
6173 			cnt_5g++;
6174 			b5g = true;
6175 		} else {
6176 			if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
6177 				wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
6178 			cnt_2g++;
6179 			b2g = true;
6180 		}
6181 	}
6182 
6183 	wl_rinfo->connect_cnt = cnt_connect;
6184 
6185 	/* Be careful to change the following sequence!! */
6186 	if (cnt_connect == 0) {
6187 		wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6188 		wl_rinfo->role_map.role.none = 1;
6189 	} else if (!b2g && b5g) {
6190 		wl_rinfo->link_mode = BTC_WLINK_5G;
6191 	} else if (wl_rinfo->role_map.role.nan) {
6192 		wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
6193 	} else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
6194 		wl_rinfo->link_mode = BTC_WLINK_OTHER;
6195 	} else  if (b2g && b5g && cnt_connect == 2) {
6196 		if (rtwdev->dbcc_en) {
6197 			switch (wl_dinfo->role[RTW89_PHY_0]) {
6198 			case RTW89_WIFI_ROLE_STATION:
6199 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6200 				break;
6201 			case RTW89_WIFI_ROLE_P2P_GO:
6202 				wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6203 				break;
6204 			case RTW89_WIFI_ROLE_P2P_CLIENT:
6205 				wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6206 				break;
6207 			case RTW89_WIFI_ROLE_AP:
6208 				wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6209 				break;
6210 			default:
6211 				wl_rinfo->link_mode = BTC_WLINK_OTHER;
6212 				break;
6213 			}
6214 		} else {
6215 			wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
6216 		}
6217 	} else if (!b5g && cnt_connect == 2) {
6218 		if (wl_rinfo->role_map.role.station &&
6219 		    (wl_rinfo->role_map.role.p2p_go ||
6220 		    wl_rinfo->role_map.role.p2p_gc ||
6221 		    wl_rinfo->role_map.role.ap)) {
6222 			if (wl_2g_ch[0] == wl_2g_ch[1])
6223 				wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
6224 			else
6225 				wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6226 		} else {
6227 			wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6228 		}
6229 	} else if (!b5g && cnt_connect == 1) {
6230 		if (wl_rinfo->role_map.role.station)
6231 			wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6232 		else if (wl_rinfo->role_map.role.ap)
6233 			wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6234 		else if (wl_rinfo->role_map.role.p2p_go)
6235 			wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6236 		else if (wl_rinfo->role_map.role.p2p_gc)
6237 			wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6238 		else
6239 			wl_rinfo->link_mode = BTC_WLINK_OTHER;
6240 	}
6241 
6242 	/* if no client_joined, don't care P2P-GO/AP role */
6243 	if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6244 		if (!client_joined) {
6245 			if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6246 			    wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6247 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6248 				wl_rinfo->connect_cnt = 1;
6249 			} else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6250 				 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6251 				wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6252 				wl_rinfo->connect_cnt = 0;
6253 			}
6254 		}
6255 	}
6256 
6257 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
6258 		    "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6259 		    cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6260 
6261 	_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6262 }
6263 
_update_wl_info_v1(struct rtw89_dev * rtwdev)6264 static void _update_wl_info_v1(struct rtw89_dev *rtwdev)
6265 {
6266 	struct rtw89_btc *btc = &rtwdev->btc;
6267 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6268 	struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6269 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
6270 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6271 	u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
6272 	u8 cnt_2g = 0, cnt_5g = 0, phy;
6273 	u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
6274 	bool b2g = false, b5g = false, client_joined = false;
6275 	u8 i;
6276 
6277 	memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6278 
6279 	for (i = 0; i < RTW89_PORT_NUM; i++) {
6280 		if (!wl_linfo[i].active)
6281 			continue;
6282 
6283 		cnt_active++;
6284 		wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role;
6285 		wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid;
6286 		wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy;
6287 		wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band;
6288 		wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
6289 		wl_rinfo->active_role_v1[cnt_active - 1].connected = 0;
6290 
6291 		wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
6292 
6293 		phy = wl_linfo[i].phy;
6294 
6295 		if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) {
6296 			wl_dinfo->role[phy] = wl_linfo[i].role;
6297 			wl_dinfo->op_band[phy] = wl_linfo[i].band;
6298 			_update_dbcc_band(rtwdev, phy);
6299 			_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6300 		}
6301 
6302 		if (wl_linfo[i].connected == MLME_NO_LINK) {
6303 			continue;
6304 		} else if (wl_linfo[i].connected == MLME_LINKING) {
6305 			cnt_connecting++;
6306 		} else {
6307 			cnt_connect++;
6308 			if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6309 			     wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6310 			     wl_linfo[i].client_cnt > 1)
6311 				client_joined = true;
6312 		}
6313 
6314 		wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
6315 		wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch;
6316 		wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw;
6317 		wl_rinfo->active_role_v1[cnt_active - 1].connected = 1;
6318 
6319 		/* only care 2 roles + BT coex */
6320 		if (wl_linfo[i].band != RTW89_BAND_2G) {
6321 			if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
6322 				wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
6323 			cnt_5g++;
6324 			b5g = true;
6325 		} else {
6326 			if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
6327 				wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
6328 			cnt_2g++;
6329 			b2g = true;
6330 		}
6331 	}
6332 
6333 	wl_rinfo->connect_cnt = cnt_connect;
6334 
6335 	/* Be careful to change the following sequence!! */
6336 	if (cnt_connect == 0) {
6337 		wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6338 		wl_rinfo->role_map.role.none = 1;
6339 	} else if (!b2g && b5g) {
6340 		wl_rinfo->link_mode = BTC_WLINK_5G;
6341 	} else if (wl_rinfo->role_map.role.nan) {
6342 		wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
6343 	} else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
6344 		wl_rinfo->link_mode = BTC_WLINK_OTHER;
6345 	} else  if (b2g && b5g && cnt_connect == 2) {
6346 		if (rtwdev->dbcc_en) {
6347 			switch (wl_dinfo->role[RTW89_PHY_0]) {
6348 			case RTW89_WIFI_ROLE_STATION:
6349 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6350 				break;
6351 			case RTW89_WIFI_ROLE_P2P_GO:
6352 				wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6353 				break;
6354 			case RTW89_WIFI_ROLE_P2P_CLIENT:
6355 				wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6356 				break;
6357 			case RTW89_WIFI_ROLE_AP:
6358 				wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6359 				break;
6360 			default:
6361 				wl_rinfo->link_mode = BTC_WLINK_OTHER;
6362 				break;
6363 			}
6364 		} else {
6365 			wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
6366 		}
6367 	} else if (!b5g && cnt_connect == 2) {
6368 		if (wl_rinfo->role_map.role.station &&
6369 		    (wl_rinfo->role_map.role.p2p_go ||
6370 		    wl_rinfo->role_map.role.p2p_gc ||
6371 		    wl_rinfo->role_map.role.ap)) {
6372 			if (wl_2g_ch[0] == wl_2g_ch[1])
6373 				wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
6374 			else
6375 				wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6376 		} else {
6377 			wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6378 		}
6379 	} else if (!b5g && cnt_connect == 1) {
6380 		if (wl_rinfo->role_map.role.station)
6381 			wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6382 		else if (wl_rinfo->role_map.role.ap)
6383 			wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6384 		else if (wl_rinfo->role_map.role.p2p_go)
6385 			wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6386 		else if (wl_rinfo->role_map.role.p2p_gc)
6387 			wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6388 		else
6389 			wl_rinfo->link_mode = BTC_WLINK_OTHER;
6390 	}
6391 
6392 	/* if no client_joined, don't care P2P-GO/AP role */
6393 	if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6394 		if (!client_joined) {
6395 			if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6396 			    wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6397 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6398 				wl_rinfo->connect_cnt = 1;
6399 			} else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6400 				 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6401 				wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6402 				wl_rinfo->connect_cnt = 0;
6403 			}
6404 		}
6405 	}
6406 
6407 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
6408 		    "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6409 		    cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6410 
6411 	_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6412 }
6413 
_update_wl_info_v2(struct rtw89_dev * rtwdev)6414 static void _update_wl_info_v2(struct rtw89_dev *rtwdev)
6415 {
6416 	struct rtw89_btc *btc = &rtwdev->btc;
6417 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6418 	struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6419 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2;
6420 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6421 	u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
6422 	u8 cnt_2g = 0, cnt_5g = 0, phy;
6423 	u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
6424 	bool b2g = false, b5g = false, client_joined = false;
6425 	u8 i;
6426 
6427 	memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6428 
6429 	for (i = 0; i < RTW89_PORT_NUM; i++) {
6430 		if (!wl_linfo[i].active)
6431 			continue;
6432 
6433 		cnt_active++;
6434 		wl_rinfo->active_role_v2[cnt_active - 1].role = wl_linfo[i].role;
6435 		wl_rinfo->active_role_v2[cnt_active - 1].pid = wl_linfo[i].pid;
6436 		wl_rinfo->active_role_v2[cnt_active - 1].phy = wl_linfo[i].phy;
6437 		wl_rinfo->active_role_v2[cnt_active - 1].band = wl_linfo[i].band;
6438 		wl_rinfo->active_role_v2[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
6439 		wl_rinfo->active_role_v2[cnt_active - 1].connected = 0;
6440 
6441 		wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
6442 
6443 		phy = wl_linfo[i].phy;
6444 
6445 		if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) {
6446 			wl_dinfo->role[phy] = wl_linfo[i].role;
6447 			wl_dinfo->op_band[phy] = wl_linfo[i].band;
6448 			_update_dbcc_band(rtwdev, phy);
6449 			_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6450 		}
6451 
6452 		if (wl_linfo[i].connected == MLME_NO_LINK) {
6453 			continue;
6454 		} else if (wl_linfo[i].connected == MLME_LINKING) {
6455 			cnt_connecting++;
6456 		} else {
6457 			cnt_connect++;
6458 			if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6459 			     wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6460 			     wl_linfo[i].client_cnt > 1)
6461 				client_joined = true;
6462 		}
6463 
6464 		wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
6465 		wl_rinfo->active_role_v2[cnt_active - 1].ch = wl_linfo[i].ch;
6466 		wl_rinfo->active_role_v2[cnt_active - 1].bw = wl_linfo[i].bw;
6467 		wl_rinfo->active_role_v2[cnt_active - 1].connected = 1;
6468 
6469 		/* only care 2 roles + BT coex */
6470 		if (wl_linfo[i].band != RTW89_BAND_2G) {
6471 			if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
6472 				wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
6473 			cnt_5g++;
6474 			b5g = true;
6475 		} else {
6476 			if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
6477 				wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
6478 			cnt_2g++;
6479 			b2g = true;
6480 		}
6481 	}
6482 
6483 	wl_rinfo->connect_cnt = cnt_connect;
6484 
6485 	/* Be careful to change the following sequence!! */
6486 	if (cnt_connect == 0) {
6487 		wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6488 		wl_rinfo->role_map.role.none = 1;
6489 	} else if (!b2g && b5g) {
6490 		wl_rinfo->link_mode = BTC_WLINK_5G;
6491 	} else if (wl_rinfo->role_map.role.nan) {
6492 		wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
6493 	} else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
6494 		wl_rinfo->link_mode = BTC_WLINK_OTHER;
6495 	} else  if (b2g && b5g && cnt_connect == 2) {
6496 		if (rtwdev->dbcc_en) {
6497 			switch (wl_dinfo->role[RTW89_PHY_0]) {
6498 			case RTW89_WIFI_ROLE_STATION:
6499 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6500 				break;
6501 			case RTW89_WIFI_ROLE_P2P_GO:
6502 				wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6503 				break;
6504 			case RTW89_WIFI_ROLE_P2P_CLIENT:
6505 				wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6506 				break;
6507 			case RTW89_WIFI_ROLE_AP:
6508 				wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6509 				break;
6510 			default:
6511 				wl_rinfo->link_mode = BTC_WLINK_OTHER;
6512 				break;
6513 			}
6514 		} else {
6515 			wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
6516 		}
6517 	} else if (!b5g && cnt_connect == 2) {
6518 		if (wl_rinfo->role_map.role.station &&
6519 		    (wl_rinfo->role_map.role.p2p_go ||
6520 		    wl_rinfo->role_map.role.p2p_gc ||
6521 		    wl_rinfo->role_map.role.ap)) {
6522 			if (wl_2g_ch[0] == wl_2g_ch[1])
6523 				wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
6524 			else
6525 				wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6526 		} else {
6527 			wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6528 		}
6529 	} else if (!b5g && cnt_connect == 1) {
6530 		if (wl_rinfo->role_map.role.station)
6531 			wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6532 		else if (wl_rinfo->role_map.role.ap)
6533 			wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6534 		else if (wl_rinfo->role_map.role.p2p_go)
6535 			wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6536 		else if (wl_rinfo->role_map.role.p2p_gc)
6537 			wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6538 		else
6539 			wl_rinfo->link_mode = BTC_WLINK_OTHER;
6540 	}
6541 
6542 	/* if no client_joined, don't care P2P-GO/AP role */
6543 	if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6544 		if (!client_joined) {
6545 			if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6546 			    wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6547 				wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6548 				wl_rinfo->connect_cnt = 1;
6549 			} else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6550 				 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6551 				wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6552 				wl_rinfo->connect_cnt = 0;
6553 			}
6554 		}
6555 	}
6556 
6557 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
6558 		    "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6559 		    cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6560 
6561 	_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6562 }
6563 
6564 #define BTC_CHK_HANG_MAX 3
6565 #define BTC_SCB_INV_VALUE GENMASK(31, 0)
6566 
_get_role_link_mode(u8 role)6567 static u8 _get_role_link_mode(u8 role)
6568 {
6569 	switch (role) {
6570 	case RTW89_WIFI_ROLE_STATION:
6571 		return BTC_WLINK_2G_STA;
6572 	case RTW89_WIFI_ROLE_P2P_GO:
6573 		return BTC_WLINK_2G_GO;
6574 	case RTW89_WIFI_ROLE_P2P_CLIENT:
6575 		return BTC_WLINK_2G_GC;
6576 	case RTW89_WIFI_ROLE_AP:
6577 		return BTC_WLINK_2G_AP;
6578 	default:
6579 		return BTC_WLINK_OTHER;
6580 	}
6581 }
6582 
_chk_role_ch_group(const struct rtw89_btc_chdef * r1,const struct rtw89_btc_chdef * r2)6583 static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1,
6584 			       const struct rtw89_btc_chdef *r2)
6585 {
6586 	if (r1->chan != r2->chan) { /* primary ch is different */
6587 		return false;
6588 	} else if (r1->bw == RTW89_CHANNEL_WIDTH_40 &&
6589 		   r2->bw == RTW89_CHANNEL_WIDTH_40) {
6590 		if (r1->offset != r2->offset)
6591 			return false;
6592 	}
6593 	return true;
6594 }
6595 
_chk_dbcc(struct rtw89_dev * rtwdev,struct rtw89_btc_chdef * ch,u8 * phy,u8 * role,u8 link_cnt)6596 static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch,
6597 		    u8 *phy, u8 *role, u8 link_cnt)
6598 {
6599 	struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6600 	struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
6601 	struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8;
6602 	bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false;
6603 	u8 j, k, dbcc_2g_cid, dbcc_2g_cid2, dbcc_2g_phy, pta_req_band;
6604 
6605 	/* find out the 2G-PHY by connect-id ->ch  */
6606 	for (j = 0; j < link_cnt; j++) {
6607 		if (ch[j].center_ch <= 14) {
6608 			is_2g_ch_exist = true;
6609 			break;
6610 		}
6611 	}
6612 
6613 	/* If no any 2G-port exist, it's impossible because 5G-exclude */
6614 	if (!is_2g_ch_exist)
6615 		return BTC_WLINK_5G;
6616 
6617 	dbcc_2g_cid = j;
6618 	dbcc_2g_phy = phy[dbcc_2g_cid];
6619 
6620 	if (dbcc_2g_phy == RTW89_PHY_1)
6621 		pta_req_band = RTW89_PHY_1;
6622 	else
6623 		pta_req_band = RTW89_PHY_0;
6624 
6625 	if (rtwdev->btc.ver->fwlrole == 7) {
6626 		rinfo_v7->dbcc_2g_phy = dbcc_2g_phy;
6627 	} else if (rtwdev->btc.ver->fwlrole == 8) {
6628 		rinfo_v8->dbcc_2g_phy = dbcc_2g_phy;
6629 		rinfo_v8->pta_req_band = pta_req_band;
6630 	}
6631 
6632 	/* connect_cnt <= 2 */
6633 	if (link_cnt < BTC_TDMA_WLROLE_MAX)
6634 		return (_get_role_link_mode((role[dbcc_2g_cid])));
6635 
6636 	/* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */
6637 	for (k = 0; k < link_cnt; k++) {
6638 		if (k == dbcc_2g_cid)
6639 			continue;
6640 
6641 		if (phy[k] == dbcc_2g_phy) {
6642 			is_multi_role_in_2g_phy = true;
6643 			dbcc_2g_cid2 = k;
6644 			break;
6645 		}
6646 	}
6647 
6648 	/* Single-role in 2G-PHY */
6649 	if (!is_multi_role_in_2g_phy)
6650 		return (_get_role_link_mode(role[dbcc_2g_cid]));
6651 
6652 	/* 2-role in 2G-PHY */
6653 	if (ch[dbcc_2g_cid2].center_ch > 14)
6654 		return BTC_WLINK_25G_MCC;
6655 	else if (_chk_role_ch_group(&ch[dbcc_2g_cid], &ch[dbcc_2g_cid2]))
6656 		return BTC_WLINK_2G_SCC;
6657 	else
6658 		return BTC_WLINK_2G_MCC;
6659 }
6660 
_update_role_link_mode(struct rtw89_dev * rtwdev,bool client_joined,u32 noa)6661 static void _update_role_link_mode(struct rtw89_dev *rtwdev,
6662 				   bool client_joined, u32 noa)
6663 {
6664 	struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &rtwdev->btc.cx.wl.role_info_v8;
6665 	struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &rtwdev->btc.cx.wl.role_info_v7;
6666 	u8 role_ver = rtwdev->btc.ver->fwlrole;
6667 	u32 type = BTC_WLMROLE_NONE, dur = 0;
6668 	u8 link_mode, connect_cnt;
6669 	u32 wl_role;
6670 
6671 	if (role_ver == 7) {
6672 		wl_role = rinfo_v7->role_map;
6673 		link_mode = rinfo_v7->link_mode;
6674 		connect_cnt = rinfo_v7->connect_cnt;
6675 	} else if (role_ver == 8) {
6676 		wl_role = rinfo_v8->role_map;
6677 		link_mode = rinfo_v8->link_mode;
6678 		connect_cnt = rinfo_v8->connect_cnt;
6679 	} else {
6680 		return;
6681 	}
6682 
6683 	/* if no client_joined, don't care P2P-GO/AP role */
6684 	if (((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
6685 	     (wl_role & BIT(RTW89_WIFI_ROLE_AP))) && !client_joined) {
6686 		if (link_mode == BTC_WLINK_2G_SCC) {
6687 			if (role_ver == 7) {
6688 				rinfo_v7->link_mode = BTC_WLINK_2G_STA;
6689 				rinfo_v7->connect_cnt--;
6690 			} else if (role_ver == 8) {
6691 				rinfo_v8->link_mode = BTC_WLINK_2G_STA;
6692 				rinfo_v8->connect_cnt--;
6693 			}
6694 		} else if (link_mode == BTC_WLINK_2G_GO ||
6695 			   link_mode == BTC_WLINK_2G_AP) {
6696 			if (role_ver == 7) {
6697 				rinfo_v7->link_mode = BTC_WLINK_NOLINK;
6698 				rinfo_v7->connect_cnt--;
6699 			} else if (role_ver == 8) {
6700 				rinfo_v8->link_mode = BTC_WLINK_NOLINK;
6701 				rinfo_v8->connect_cnt--;
6702 			}
6703 		}
6704 	}
6705 
6706 	/* Identify 2-Role type  */
6707 	if (connect_cnt >= 2 &&
6708 	    (link_mode == BTC_WLINK_2G_SCC ||
6709 	     link_mode == BTC_WLINK_2G_MCC ||
6710 	     link_mode == BTC_WLINK_25G_MCC ||
6711 	     link_mode == BTC_WLINK_5G)) {
6712 		if ((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
6713 		    (wl_role & BIT(RTW89_WIFI_ROLE_AP)))
6714 			type = noa ? BTC_WLMROLE_STA_GO_NOA : BTC_WLMROLE_STA_GO;
6715 		else if (wl_role & BIT(RTW89_WIFI_ROLE_P2P_CLIENT))
6716 			type = noa ? BTC_WLMROLE_STA_GC_NOA : BTC_WLMROLE_STA_GC;
6717 		else
6718 			type = BTC_WLMROLE_STA_STA;
6719 
6720 		dur = noa;
6721 	}
6722 
6723 	if (role_ver == 7) {
6724 		rinfo_v7->mrole_type = type;
6725 		rinfo_v7->mrole_noa_duration = dur;
6726 	} else if (role_ver == 8) {
6727 		rinfo_v8->mrole_type = type;
6728 		rinfo_v8->mrole_noa_duration = dur;
6729 	}
6730 }
6731 
_update_wl_info_v7(struct rtw89_dev * rtwdev,u8 rid)6732 static void _update_wl_info_v7(struct rtw89_dev *rtwdev, u8 rid)
6733 {
6734 	struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER];
6735 	struct rtw89_btc *btc = &rtwdev->btc;
6736 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6737 	struct rtw89_btc_wl_role_info_v7 *wl_rinfo = &wl->role_info_v7;
6738 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6739 	struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6740 	struct rtw89_btc_wl_active_role_v7 *act_role = NULL;
6741 	u8 i, mode, cnt = 0, cnt_2g = 0, cnt_5g = 0, phy_now = RTW89_PHY_NUM, phy_dbcc;
6742 	bool b2g = false, b5g = false, client_joined = false, client_inc_2g = false;
6743 	u8 client_cnt_last[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6744 	u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6745 	u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6746 	u8 mac = RTW89_MAC_0, dbcc_2g_phy = RTW89_PHY_0;
6747 	u32 noa_duration = 0;
6748 
6749 	memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6750 
6751 	for (i = 0; i < RTW89_PORT_NUM; i++) {
6752 		if (!wl_linfo[i].active || wl_linfo[i].phy >= RTW89_PHY_NUM)
6753 			continue;
6754 
6755 		act_role = &wl_rinfo->active_role[i];
6756 		act_role->role = wl_linfo[i].role;
6757 
6758 		/* check if role connect? */
6759 		if (wl_linfo[i].connected == MLME_NO_LINK) {
6760 			act_role->connected = 0;
6761 			continue;
6762 		} else if (wl_linfo[i].connected == MLME_LINKING) {
6763 			continue;
6764 		}
6765 
6766 		cnt++;
6767 		act_role->connected = 1;
6768 		act_role->pid = wl_linfo[i].pid;
6769 		act_role->phy = wl_linfo[i].phy;
6770 		act_role->band = wl_linfo[i].band;
6771 		act_role->ch = wl_linfo[i].ch;
6772 		act_role->bw = wl_linfo[i].bw;
6773 		act_role->noa = wl_linfo[i].noa;
6774 		act_role->noa_dur = wl_linfo[i].noa_duration;
6775 		cid_ch[cnt - 1] = wl_linfo[i].chdef;
6776 		cid_phy[cnt - 1] = wl_linfo[i].phy;
6777 		cid_role[cnt - 1] = wl_linfo[i].role;
6778 		wl_rinfo->role_map |= BIT(wl_linfo[i].role);
6779 
6780 		if (rid == i)
6781 			phy_now = act_role->phy;
6782 
6783 		if (wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6784 		    wl_linfo[i].role == RTW89_WIFI_ROLE_AP) {
6785 			if (wl_linfo[i].client_cnt > 1)
6786 				client_joined = true;
6787 			if (client_cnt_last[i] < wl_linfo[i].client_cnt &&
6788 			    wl_linfo[i].chdef.band == RTW89_BAND_2G)
6789 				client_inc_2g = true;
6790 			act_role->client_cnt = wl_linfo[i].client_cnt;
6791 		} else {
6792 			act_role->client_cnt = 0;
6793 		}
6794 
6795 		if (act_role->noa && act_role->noa_dur > 0)
6796 			noa_duration = act_role->noa_dur;
6797 
6798 		if (rtwdev->dbcc_en) {
6799 			phy_dbcc = wl_linfo[i].phy;
6800 			wl_dinfo->role[phy_dbcc] |= BIT(wl_linfo[i].role);
6801 			wl_dinfo->op_band[phy_dbcc] = wl_linfo[i].chdef.band;
6802 		}
6803 
6804 		if (wl_linfo[i].chdef.band != RTW89_BAND_2G) {
6805 			cnt_5g++;
6806 			b5g = true;
6807 		} else {
6808 			if (((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6809 			      wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6810 			     client_joined) ||
6811 			    wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_CLIENT)
6812 				wl_rinfo->p2p_2g = 1;
6813 
6814 			if ((wl_linfo[i].mode & BIT(BTC_WL_MODE_11B)) ||
6815 			    (wl_linfo[i].mode & BIT(BTC_WL_MODE_11G)))
6816 				wl->bg_mode = 1;
6817 			else if (wl_linfo[i].mode & BIT(BTC_WL_MODE_HE))
6818 				wl->he_mode = true;
6819 
6820 			cnt_2g++;
6821 			b2g = true;
6822 		}
6823 
6824 		if (act_role->band == RTW89_BAND_5G && act_role->ch >= 100)
6825 			wl->is_5g_hi_channel = 1;
6826 		else
6827 			wl->is_5g_hi_channel = 0;
6828 	}
6829 
6830 	wl_rinfo->connect_cnt = cnt;
6831 	wl->client_cnt_inc_2g = client_inc_2g;
6832 
6833 	if (cnt == 0) {
6834 		mode = BTC_WLINK_NOLINK;
6835 		wl_rinfo->role_map = BIT(RTW89_WIFI_ROLE_NONE);
6836 	} else if (!b2g && b5g) {
6837 		mode = BTC_WLINK_5G;
6838 	} else if (wl_rinfo->role_map & BIT(RTW89_WIFI_ROLE_NAN)) {
6839 		mode = BTC_WLINK_2G_NAN;
6840 	} else if (cnt > BTC_TDMA_WLROLE_MAX) {
6841 		mode = BTC_WLINK_OTHER;
6842 	} else if (rtwdev->dbcc_en) {
6843 		mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt);
6844 
6845 		/* correct 2G-located PHY band for gnt ctrl */
6846 		if (dbcc_2g_phy < RTW89_PHY_NUM)
6847 			wl_dinfo->op_band[dbcc_2g_phy] = RTW89_BAND_2G;
6848 	} else if (b2g && b5g && cnt == 2) {
6849 		mode = BTC_WLINK_25G_MCC;
6850 	} else if (!b5g && cnt == 2) { /* cnt_connect = 2 */
6851 		if (_chk_role_ch_group(&cid_ch[0], &cid_ch[cnt - 1]))
6852 			mode = BTC_WLINK_2G_SCC;
6853 		else
6854 			mode = BTC_WLINK_2G_MCC;
6855 	} else if (!b5g && cnt == 1) { /* cnt_connect = 1 */
6856 		mode = _get_role_link_mode(cid_role[0]);
6857 	} else {
6858 		mode = BTC_WLINK_NOLINK;
6859 	}
6860 
6861 	wl_rinfo->link_mode = mode;
6862 	_update_role_link_mode(rtwdev, client_joined, noa_duration);
6863 
6864 	/* todo DBCC related event */
6865 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] wl_info phy_now=%d\n", phy_now);
6866 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
6867 		    "[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g);
6868 
6869 	if (wl_rinfo->dbcc_en != rtwdev->dbcc_en) {
6870 		wl_rinfo->dbcc_chg = 1;
6871 		wl_rinfo->dbcc_en = rtwdev->dbcc_en;
6872 		btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++;
6873 	}
6874 
6875 	if (rtwdev->dbcc_en) {
6876 		wl_rinfo->dbcc_2g_phy = dbcc_2g_phy;
6877 
6878 		if (dbcc_2g_phy == RTW89_PHY_1)
6879 			mac = RTW89_MAC_1;
6880 
6881 		_update_dbcc_band(rtwdev, RTW89_PHY_0);
6882 		_update_dbcc_band(rtwdev, RTW89_PHY_1);
6883 	}
6884 	_wl_req_mac(rtwdev, mac);
6885 	_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6886 }
6887 
_update_wl_link_mode(struct rtw89_dev * rtwdev,u8 hw_band,u8 type)6888 static u8 _update_wl_link_mode(struct rtw89_dev *rtwdev, u8 hw_band, u8 type)
6889 {
6890 	struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6891 	struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info;
6892 	u8 mode = BTC_WLINK_NOLINK;
6893 
6894 	switch (type) {
6895 	case RTW89_MR_WTYPE_NONE: /* no-link */
6896 		mode = BTC_WLINK_NOLINK;
6897 		break;
6898 	case RTW89_MR_WTYPE_NONMLD:  /* Non_MLO 1-role 2+0/0+2 */
6899 	case RTW89_MR_WTYPE_MLD1L1R: /* MLO only-1 link 2+0/0+2 */
6900 		if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) {
6901 			mode = BTC_WLINK_5G;
6902 		} else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) {
6903 			mode = BTC_WLINK_2G_GO;
6904 		} else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT) {
6905 			if (wl->role_info_v8.p2p_2g)
6906 				mode = BTC_WLINK_2G_GC;
6907 			else
6908 				mode = BTC_WLINK_2G_STA;
6909 		}
6910 		break;
6911 	case RTW89_MR_WTYPE_NONMLD_NONMLD: /* Non_MLO 2-role 2+0/0+2 */
6912 	case RTW89_MR_WTYPE_MLD1L1R_NONMLD: /* MLO only-1 link + P2P 2+0/0+2 */
6913 		if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) {
6914 			mode = BTC_WLINK_5G;
6915 		} else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_5GHZ ||
6916 			   mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_6GHZ) {
6917 			mode = BTC_WLINK_25G_MCC;
6918 		} else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ) {
6919 			mode = BTC_WLINK_2G_MCC;
6920 		} else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_2GHZ) {
6921 			mode = BTC_WLINK_2G_SCC;
6922 		}
6923 		break;
6924 	case RTW89_MR_WTYPE_MLD2L1R: /* MLO_MLSR 2+0/0+2 */
6925 		if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G)
6926 			mode = BTC_WLINK_5G;
6927 		else if (wl->role_info_v8.p2p_2g)
6928 			mode = BTC_WLINK_2G_GC;
6929 		else
6930 			mode = BTC_WLINK_2G_STA;
6931 		break;
6932 	case RTW89_MR_WTYPE_MLD2L1R_NONMLD: /* MLO_MLSR + P2P 2+0/0+2 */
6933 	case RTW89_MR_WTYPE_MLD2L2R_NONMLD: /* MLO_MLMR + P2P 1+1/2+2 */
6934 		/* driver may doze 1-link to
6935 		 * 2G+5G   -> TDMA slot switch by E2G/E5G
6936 		 * 5G only -> TDMA slot switch by E5G
6937 		 */
6938 		mode = BTC_WLINK_25G_MCC;
6939 		break;
6940 	case RTW89_MR_WTYPE_MLD2L2R: /* MLO_MLMR  1+1/2+2 */
6941 		if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) {
6942 			mode = BTC_WLINK_5G;
6943 		} else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) {
6944 			mode = BTC_WLINK_2G_GO;
6945 		} else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT) {
6946 			if (wl->role_info_v8.p2p_2g)
6947 				mode = BTC_WLINK_2G_GC;
6948 			else
6949 				mode = BTC_WLINK_2G_STA;
6950 		}
6951 		break;
6952 	}
6953 	return mode;
6954 }
6955 
_update_wl_mlo_info(struct rtw89_dev * rtwdev)6956 static void _update_wl_mlo_info(struct rtw89_dev *rtwdev)
6957 {
6958 	struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6959 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
6960 	struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info;
6961 	struct rtw89_mr_chanctx_info qinfo;
6962 	u8 track_band = RTW89_PHY_0;
6963 	u8 rf_band = RTW89_BAND_2G;
6964 	u8 i, type;
6965 
6966 	/* parse MLO info form PHL API for each HW-band */
6967 	for (i = RTW89_MAC_0; i <= RTW89_MAC_1; i++) {
6968 		memset(&qinfo, 0, sizeof(qinfo));
6969 
6970 		rtw89_query_mr_chanctx_info(rtwdev, i, &qinfo);
6971 		mlo_info->wmode[i] = qinfo.wmode;
6972 		mlo_info->ch_type[i] = qinfo.ctxtype;
6973 		mlo_info->wtype = qinfo.wtype;
6974 
6975 		if (mlo_info->ch_type[i] == RTW89_MR_CTX1_5GHZ ||
6976 		    mlo_info->ch_type[i] == RTW89_MR_CTX2_5GHZ ||
6977 		    mlo_info->ch_type[i] == RTW89_MR_CTX2_5GHZ_6GHZ)
6978 			mlo_info->hwb_rf_band[i] = RTW89_BAND_5G;
6979 		else if (mlo_info->ch_type[i] == RTW89_MR_CTX1_6GHZ ||
6980 			 mlo_info->ch_type[i] == RTW89_MR_CTX2_6GHZ)
6981 			mlo_info->hwb_rf_band[i] = RTW89_BAND_6G;
6982 		else /* check if "2G-included" or unknown in each HW-band */
6983 			mlo_info->hwb_rf_band[i] = RTW89_BAND_2G;
6984 	}
6985 
6986 	mlo_info->link_status = rtwdev->mlo_dbcc_mode;
6987 	type = mlo_info->wtype;
6988 
6989 	if (mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R ||
6990 	    mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R ||
6991 	    mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R ||
6992 	    mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R_NONMLD ||
6993 	    mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD ||
6994 	    mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R_NONMLD)
6995 		mlo_info->mlo_en = 1;
6996 	else
6997 		mlo_info->mlo_en = 0;
6998 
6999 	if (mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_NONE &&
7000 	    mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_UNKNOWN &&
7001 	    mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_NONE &&
7002 	    mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_UNKNOWN)
7003 		mlo_info->dual_hw_band_en = 1; /* two HW-hand link exist */
7004 	else
7005 		mlo_info->dual_hw_band_en = 0;
7006 
7007 	if (mlo_info->link_status == MLO_2_PLUS_0_2RF ||
7008 	    mlo_info->link_status == MLO_0_PLUS_2_2RF ||
7009 	    mlo_info->link_status == MLO_2_PLUS_2_2RF)
7010 		mlo_info->mlo_adie = 2;
7011 	else
7012 		mlo_info->mlo_adie = 1;
7013 
7014 	switch (mlo_info->link_status) {
7015 	default:
7016 	case MLO_2_PLUS_0_1RF: /* 2+0 */
7017 	case MLO_2_PLUS_0_2RF:
7018 		mlo_info->rf_combination = BTC_MLO_RF_2_PLUS_0;
7019 		track_band = RTW89_MAC_0;
7020 		rf_band = mlo_info->hwb_rf_band[RTW89_MAC_0];
7021 		mlo_info->path_rf_band[BTC_RF_S0] = rf_band;
7022 		mlo_info->path_rf_band[BTC_RF_S1] = rf_band;
7023 
7024 		wl_rinfo->pta_req_band = RTW89_MAC_0;
7025 		wl_rinfo->dbcc_2g_phy = RTW89_PHY_0;
7026 		wl_rinfo->dbcc_en = 0;
7027 		break;
7028 	case MLO_0_PLUS_2_1RF: /* 0+2 */
7029 	case MLO_0_PLUS_2_2RF:
7030 		mlo_info->rf_combination = BTC_MLO_RF_0_PLUS_2;
7031 		track_band = RTW89_MAC_1;
7032 		rf_band = mlo_info->hwb_rf_band[RTW89_MAC_1];
7033 		mlo_info->path_rf_band[BTC_RF_S0] = rf_band;
7034 		mlo_info->path_rf_band[BTC_RF_S1] = rf_band;
7035 
7036 		wl_rinfo->pta_req_band = RTW89_MAC_1;
7037 		wl_rinfo->dbcc_2g_phy = RTW89_PHY_1;
7038 		wl_rinfo->dbcc_en = 0;
7039 		break;
7040 	case MLO_1_PLUS_1_1RF: /* 1+1 */
7041 	case MLO_1_PLUS_1_2RF: /* 1+1 */
7042 	case MLO_2_PLUS_2_2RF: /* 2+2 */
7043 	case DBCC_LEGACY: /* DBCC 1+1 */
7044 		if (mlo_info->link_status == MLO_2_PLUS_2_2RF)
7045 			mlo_info->rf_combination = BTC_MLO_RF_2_PLUS_2;
7046 		else
7047 			mlo_info->rf_combination = BTC_MLO_RF_1_PLUS_1;
7048 
7049 		if (mlo_info->hwb_rf_band[RTW89_MAC_0] == RTW89_BAND_2G)
7050 			track_band = RTW89_MAC_0;
7051 		else
7052 			track_band = RTW89_MAC_1;
7053 
7054 		mlo_info->path_rf_band[BTC_RF_S0] =
7055 					mlo_info->hwb_rf_band[RTW89_MAC_0];
7056 		mlo_info->path_rf_band[BTC_RF_S1] =
7057 					mlo_info->hwb_rf_band[RTW89_MAC_1];
7058 
7059 		/* Check ch count from ch_type @ 2.4G HW-band, and modify type */
7060 		if (mlo_info->ch_type[track_band] == RTW89_MR_CTX1_2GHZ)
7061 			type = RTW89_MR_WTYPE_NONMLD; /* only 1-role at 2G */
7062 		else
7063 			type = RTW89_MR_WTYPE_NONMLD_NONMLD;
7064 
7065 		if (mlo_info->hwb_rf_band[RTW89_MAC_0] == RTW89_BAND_2G) {
7066 			wl_rinfo->pta_req_band = RTW89_MAC_0;
7067 			wl_rinfo->dbcc_2g_phy = RTW89_PHY_0;
7068 		} else {
7069 			wl_rinfo->pta_req_band = RTW89_MAC_1;
7070 			wl_rinfo->dbcc_2g_phy = RTW89_PHY_1;
7071 		}
7072 
7073 		if (mlo_info->wmode[RTW89_MAC_0] == RTW89_MR_WMODE_NONE &&
7074 		    mlo_info->wmode[RTW89_MAC_1] == RTW89_MR_WMODE_NONE)
7075 			wl_rinfo->dbcc_en = 0;
7076 		else
7077 			wl_rinfo->dbcc_en = 1;
7078 		break;
7079 	}
7080 
7081 	wl_rinfo->link_mode = _update_wl_link_mode(rtwdev, track_band, type);
7082 
7083 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(), mode=%s, pta_band=%d",
7084 		    __func__, id_to_linkmode(wl_rinfo->link_mode),
7085 		    wl_rinfo->pta_req_band);
7086 }
7087 
_update_wl_non_mlo_info(struct rtw89_dev * rtwdev)7088 static void _update_wl_non_mlo_info(struct rtw89_dev *rtwdev)
7089 {
7090 	struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
7091 	struct rtw89_btc_wl_rlink *rlink = NULL;
7092 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
7093 	struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7094 	u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7095 	u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7096 	bool b2g = false, b5g = false, outloop = false;
7097 	u8 mode = BTC_WLINK_NOLINK;
7098 	u8 cnt_2g = 0, cnt_5g = 0;
7099 	u8 i, j, cnt = 0;
7100 
7101 	for (j = RTW89_PHY_0; j < RTW89_PHY_NUM; j++) {
7102 		for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
7103 			rlink = &wl_rinfo->rlink[i][j];
7104 
7105 			if (!rlink->active || !rlink->connected)
7106 				continue;
7107 
7108 			if (cnt >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER) {
7109 				outloop = true;
7110 				break;
7111 			}
7112 
7113 			cid_ch[cnt] = wl->rlink_info[i][j].chdef;
7114 			cid_phy[cnt] = rlink->phy;
7115 			cid_role[cnt] = rlink->role;
7116 			cnt++;
7117 
7118 			if (rlink->rf_band != RTW89_BAND_2G) {
7119 				cnt_5g++;
7120 				b5g = true;
7121 			} else {
7122 				cnt_2g++;
7123 				b2g = true;
7124 			}
7125 		}
7126 		if (outloop)
7127 			break;
7128 	}
7129 
7130 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7131 		    "[BTC], %s(): cnt_2g=%d, cnt_5g=%d\n", __func__, cnt_2g, cnt_5g);
7132 
7133 	wl_rinfo->dbcc_en = rtwdev->dbcc_en;
7134 	/* Be careful to change the following sequence!! */
7135 	if (cnt == 0) {
7136 		mode = BTC_WLINK_NOLINK;
7137 	} else if (!b2g && b5g) {
7138 		mode = BTC_WLINK_5G;
7139 	} else if (wl_rinfo->dbcc_en) {
7140 		mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt);
7141 	} else if (b2g && b5g) {
7142 		mode = BTC_WLINK_25G_MCC;
7143 	} else if (!b5g && cnt >= 2) {
7144 		if (_chk_role_ch_group(&cid_ch[0], &cid_ch[1]))
7145 			mode = BTC_WLINK_2G_SCC;
7146 		else
7147 			mode = BTC_WLINK_2G_MCC;
7148 	} else if (!b5g) { /* cnt_connect = 1 */
7149 		mode = _get_role_link_mode(cid_role[0]);
7150 	}
7151 
7152 	wl_rinfo->link_mode = mode;
7153 }
7154 
_modify_role_link_mode(struct rtw89_dev * rtwdev)7155 static void _modify_role_link_mode(struct rtw89_dev *rtwdev)
7156 {
7157 	struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
7158 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
7159 	u8 go_cleint_exist = wl->go_client_exist;
7160 	u8 link_mode = wl_rinfo->link_mode;
7161 	u32 role_map = wl_rinfo->role_map;
7162 	u8 noa_exist = wl->noa_exist;
7163 	u32 mrole = BTC_WLMROLE_NONE;
7164 
7165 	/* if no client_joined, don't care P2P-GO/AP role */
7166 	if (((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
7167 	     (role_map & BIT(RTW89_WIFI_ROLE_AP))) && !go_cleint_exist) {
7168 		if (link_mode == BTC_WLINK_2G_SCC) {
7169 			wl_rinfo->link_mode = BTC_WLINK_2G_STA;
7170 		} else if (link_mode == BTC_WLINK_2G_GO ||
7171 			   link_mode == BTC_WLINK_2G_AP) {
7172 			wl_rinfo->link_mode = BTC_WLINK_NOLINK;
7173 		}
7174 	}
7175 
7176 	/* Identify 2-Role type */
7177 	if  (link_mode == BTC_WLINK_2G_SCC ||
7178 	     link_mode == BTC_WLINK_2G_MCC ||
7179 	     link_mode == BTC_WLINK_25G_MCC ||
7180 	     link_mode == BTC_WLINK_5G) {
7181 		if ((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
7182 		    (role_map & BIT(RTW89_WIFI_ROLE_AP))) {
7183 			if (noa_exist)
7184 				mrole = BTC_WLMROLE_STA_GO_NOA;
7185 			else
7186 				mrole = BTC_WLMROLE_STA_GO;
7187 		} else if (role_map & BIT(RTW89_WIFI_ROLE_P2P_CLIENT)) {
7188 			if (noa_exist)
7189 				mrole = BTC_WLMROLE_STA_GC_NOA;
7190 			else
7191 				mrole = BTC_WLMROLE_STA_GC;
7192 		} else {
7193 			mrole = BTC_WLMROLE_STA_STA;
7194 		}
7195 	}
7196 
7197 	wl_rinfo->mrole_type = mrole;
7198 
7199 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7200 		    "[BTC], %s(): link_mode=%s, mrole_type=%d\n", __func__,
7201 		    id_to_linkmode(wl_rinfo->link_mode), wl_rinfo->mrole_type);
7202 }
7203 
_update_wl_info_v8(struct rtw89_dev * rtwdev,u8 role_id,u8 rlink_id,enum btc_role_state state)7204 static void _update_wl_info_v8(struct rtw89_dev *rtwdev, u8 role_id, u8 rlink_id,
7205 			       enum btc_role_state state)
7206 {
7207 	struct rtw89_btc_wl_rlink *rlink = NULL;
7208 	struct rtw89_btc_wl_link_info *wl_linfo;
7209 	struct rtw89_btc *btc = &rtwdev->btc;
7210 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7211 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
7212 	bool client_joined = false, noa_exist = false, p2p_exist = false;
7213 	bool is_5g_hi_channel = false, bg_mode = false, dbcc_en_ori;
7214 	u8 i, j, link_mode_ori;
7215 	u32 role_map = 0;
7216 
7217 	if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id >= RTW89_MAC_NUM)
7218 		return;
7219 
7220 	/* Extract wl->link_info[role_id][rlink_id] to wl->role_info
7221 	 * role_id: role index
7222 	 * rlink_id: rlink index (= HW-band index)
7223 	 * pid: port_index
7224 	 */
7225 
7226 	wl_linfo = &wl->rlink_info[role_id][rlink_id];
7227 	rlink = &wl_rinfo->rlink[role_id][rlink_id];
7228 
7229 	rlink->role = wl_linfo->role;
7230 	rlink->active = wl_linfo->active; /* Doze or not */
7231 	rlink->pid = wl_linfo->pid;
7232 	rlink->phy = wl_linfo->phy;
7233 	rlink->rf_band = wl_linfo->band;
7234 	rlink->ch = wl_linfo->ch;
7235 	rlink->bw = wl_linfo->bw;
7236 	rlink->noa = wl_linfo->noa;
7237 	rlink->noa_dur = wl_linfo->noa_duration / 1000;
7238 	rlink->client_cnt = wl_linfo->client_cnt;
7239 	rlink->mode = wl_linfo->mode;
7240 
7241 	switch (wl_linfo->connected) {
7242 	case MLME_NO_LINK:
7243 		rlink->connected = 0;
7244 		break;
7245 	case MLME_LINKED:
7246 		rlink->connected = 1;
7247 		break;
7248 	default:
7249 		return;
7250 	}
7251 
7252 	for (j = RTW89_MAC_0; j <= RTW89_MAC_1; j++) {
7253 		for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
7254 			rlink = &wl_rinfo->rlink[i][j];
7255 
7256 			if (!rlink->active || !rlink->connected)
7257 				continue;
7258 
7259 			role_map |= BIT(rlink->role);
7260 
7261 			/* only one noa-role exist */
7262 			if (rlink->noa && rlink->noa_dur > 0)
7263 				noa_exist = true;
7264 
7265 			/* for WL 5G-Rx interfered with BT issue */
7266 			if (rlink->rf_band == RTW89_BAND_5G) {
7267 				if (rlink->ch >= 100)
7268 					is_5g_hi_channel = true;
7269 
7270 				continue;
7271 			}
7272 
7273 			/* only if client connect for p2p-Go/AP */
7274 			if ((rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
7275 			     rlink->role == RTW89_WIFI_ROLE_AP) &&
7276 			     rlink->client_cnt > 1) {
7277 				p2p_exist = true;
7278 				client_joined = true;
7279 			}
7280 
7281 			/* Identify if P2P-Go (GO/GC/AP) exist at 2G band */
7282 			if (rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)
7283 				p2p_exist = true;
7284 
7285 			if ((rlink->mode & BIT(BTC_WL_MODE_11B)) ||
7286 			    (rlink->mode & BIT(BTC_WL_MODE_11G)))
7287 				bg_mode = true;
7288 		}
7289 	}
7290 
7291 	link_mode_ori = wl_rinfo->link_mode;
7292 	wl->is_5g_hi_channel = is_5g_hi_channel;
7293 	wl->bg_mode = bg_mode;
7294 	wl->go_client_exist = client_joined;
7295 	wl->noa_exist = noa_exist;
7296 	wl_rinfo->p2p_2g = p2p_exist;
7297 	wl_rinfo->role_map = role_map;
7298 
7299 	dbcc_en_ori = wl_rinfo->dbcc_en;
7300 
7301 	if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) {
7302 		/* for MLO-supported, link-mode from driver directly */
7303 		_update_wl_mlo_info(rtwdev);
7304 	} else {
7305 		/* for non-MLO-supported, link-mode by BTC */
7306 		_update_wl_non_mlo_info(rtwdev);
7307 	}
7308 
7309 	_modify_role_link_mode(rtwdev);
7310 
7311 	if (link_mode_ori != wl_rinfo->link_mode)
7312 		wl->link_mode_chg = true;
7313 
7314 	if (wl_rinfo->dbcc_en != dbcc_en_ori) {
7315 		wl->dbcc_chg = true;
7316 		btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++;
7317 	}
7318 }
7319 
rtw89_coex_act1_work(struct wiphy * wiphy,struct wiphy_work * work)7320 void rtw89_coex_act1_work(struct wiphy *wiphy, struct wiphy_work *work)
7321 {
7322 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7323 						coex_act1_work.work);
7324 	struct rtw89_btc *btc = &rtwdev->btc;
7325 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7326 	struct rtw89_btc_cx *cx = &btc->cx;
7327 	struct rtw89_btc_wl_info *wl = &cx->wl;
7328 
7329 	lockdep_assert_wiphy(wiphy);
7330 
7331 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7332 	dm->cnt_notify[BTC_NCNT_TIMER]++;
7333 	if (wl->status.map._4way)
7334 		wl->status.map._4way = false;
7335 	if (wl->status.map.connecting)
7336 		wl->status.map.connecting = false;
7337 
7338 	_run_coex(rtwdev, BTC_RSN_ACT1_WORK);
7339 }
7340 
rtw89_coex_bt_devinfo_work(struct wiphy * wiphy,struct wiphy_work * work)7341 void rtw89_coex_bt_devinfo_work(struct wiphy *wiphy, struct wiphy_work *work)
7342 {
7343 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7344 						coex_bt_devinfo_work.work);
7345 	struct rtw89_btc *btc = &rtwdev->btc;
7346 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7347 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
7348 
7349 	lockdep_assert_wiphy(wiphy);
7350 
7351 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7352 	dm->cnt_notify[BTC_NCNT_TIMER]++;
7353 	a2dp->play_latency = 0;
7354 	_run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK);
7355 }
7356 
rtw89_coex_rfk_chk_work(struct wiphy * wiphy,struct wiphy_work * work)7357 void rtw89_coex_rfk_chk_work(struct wiphy *wiphy, struct wiphy_work *work)
7358 {
7359 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7360 						coex_rfk_chk_work.work);
7361 	struct rtw89_btc *btc = &rtwdev->btc;
7362 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7363 	struct rtw89_btc_cx *cx = &btc->cx;
7364 	struct rtw89_btc_wl_info *wl = &cx->wl;
7365 
7366 	lockdep_assert_wiphy(wiphy);
7367 
7368 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7369 	dm->cnt_notify[BTC_NCNT_TIMER]++;
7370 	if (wl->rfk_info.state != BTC_WRFK_STOP) {
7371 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7372 			    "[BTC], %s(): RFK timeout\n", __func__);
7373 		cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++;
7374 		dm->error.map.wl_rfk_timeout = true;
7375 		wl->rfk_info.state = BTC_WRFK_STOP;
7376 		_write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
7377 		_run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK);
7378 	}
7379 }
7380 
_update_bt_scbd(struct rtw89_dev * rtwdev,bool only_update)7381 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update)
7382 {
7383 	const struct rtw89_chip_info *chip = rtwdev->chip;
7384 	struct rtw89_btc *btc = &rtwdev->btc;
7385 	struct rtw89_btc_cx *cx = &btc->cx;
7386 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
7387 	u32 val;
7388 	bool status_change = false;
7389 
7390 	if (!chip->scbd)
7391 		return;
7392 
7393 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
7394 
7395 	val = _read_scbd(rtwdev);
7396 	if (val == BTC_SCB_INV_VALUE) {
7397 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7398 			    "[BTC], %s(): return by invalid scbd value\n",
7399 			    __func__);
7400 		return;
7401 	}
7402 
7403 	if (!(val & BTC_BSCB_ON))
7404 		bt->enable.now = 0;
7405 	else
7406 		bt->enable.now = 1;
7407 
7408 	if (bt->enable.now != bt->enable.last)
7409 		status_change = true;
7410 
7411 	/* reset bt info if bt re-enable */
7412 	if (bt->enable.now && !bt->enable.last) {
7413 		_reset_btc_var(rtwdev, BTC_RESET_BTINFO);
7414 		cx->cnt_bt[BTC_BCNT_REENABLE]++;
7415 		bt->enable.now = 1;
7416 	}
7417 
7418 	bt->enable.last = bt->enable.now;
7419 	bt->scbd = val;
7420 	bt->mbx_avl = !!(val & BTC_BSCB_ACT);
7421 
7422 	if (bt->whql_test != !!(val & BTC_BSCB_WHQL))
7423 		status_change = true;
7424 
7425 	bt->whql_test = !!(val & BTC_BSCB_WHQL);
7426 	bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE;
7427 	bt->link_info.a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT);
7428 
7429 	bt->lna_constrain = !!(val & BTC_BSCB_BT_LNAB0) +
7430 			    !!(val & BTC_BSCB_BT_LNAB1) * 2 + 4;
7431 
7432 	/* if rfk run 1->0 */
7433 	if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN))
7434 		status_change = true;
7435 
7436 	bt->rfk_info.map.run  = !!(val & BTC_BSCB_RFK_RUN);
7437 	bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ);
7438 	bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
7439 	bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT);
7440 	if (bt->run_patch_code != !!(val & BTC_BSCB_PATCH_CODE))
7441 		status_change = true;
7442 	bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
7443 
7444 	if (!only_update && status_change)
7445 		_run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
7446 }
7447 
7448 #define BTC_BTINFO_PWR_LEN 5
_update_bt_txpwr_info(struct rtw89_dev * rtwdev,u8 * buf,u32 len)7449 static void _update_bt_txpwr_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
7450 {
7451 	struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt;
7452 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
7453 
7454 	if (len != BTC_BTINFO_PWR_LEN)
7455 		return;
7456 
7457 	if (!memcmp(bt->txpwr_info, buf, sizeof(bt->txpwr_info))) {
7458 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7459 			    "[BTC], %s return by info duplicate!\n", __func__);
7460 		return;
7461 	}
7462 
7463 	memcpy(bt->txpwr_info, buf, BTC_BTINFO_MAX);
7464 	memcpy(&b->bt_txpwr_desc, &buf[2], sizeof(b->bt_txpwr_desc));
7465 }
7466 
_chk_wl_rfk_request(struct rtw89_dev * rtwdev)7467 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev)
7468 {
7469 	struct rtw89_btc *btc = &rtwdev->btc;
7470 	struct rtw89_btc_cx *cx = &btc->cx;
7471 	struct rtw89_btc_bt_info *bt = &cx->bt;
7472 
7473 	_update_bt_scbd(rtwdev, true);
7474 
7475 	cx->cnt_wl[BTC_WCNT_RFK_REQ]++;
7476 
7477 	if ((bt->rfk_info.map.run || bt->rfk_info.map.req) &&
7478 	    !bt->rfk_info.map.timeout) {
7479 		cx->cnt_wl[BTC_WCNT_RFK_REJECT]++;
7480 	} else {
7481 		cx->cnt_wl[BTC_WCNT_RFK_GO]++;
7482 		return true;
7483 	}
7484 	return false;
7485 }
7486 
7487 static
_run_coex(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason)7488 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
7489 {
7490 	struct rtw89_btc *btc = &rtwdev->btc;
7491 	const struct rtw89_btc_ver *ver = btc->ver;
7492 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7493 	struct rtw89_btc_cx *cx = &btc->cx;
7494 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7495 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
7496 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
7497 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
7498 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
7499 	struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
7500 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
7501 	u8 mode, igno_bt, always_freerun;
7502 
7503 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
7504 
7505 	dm->run_reason = reason;
7506 	_update_dm_step(rtwdev, reason);
7507 	_update_btc_state_map(rtwdev);
7508 
7509 	if (ver->fwlrole == 0)
7510 		mode = wl_rinfo->link_mode;
7511 	else if (ver->fwlrole == 1)
7512 		mode = wl_rinfo_v1->link_mode;
7513 	else if (ver->fwlrole == 2)
7514 		mode = wl_rinfo_v2->link_mode;
7515 	else if (ver->fwlrole == 7)
7516 		mode = wl_rinfo_v7->link_mode;
7517 	else if (ver->fwlrole == 8)
7518 		mode = wl_rinfo_v8->link_mode;
7519 	else
7520 		return;
7521 
7522 	if (ver->fcxctrl == 7) {
7523 		igno_bt = btc->ctrl.ctrl_v7.igno_bt;
7524 		always_freerun = btc->ctrl.ctrl_v7.always_freerun;
7525 	} else {
7526 		igno_bt = btc->ctrl.ctrl.igno_bt;
7527 		always_freerun = btc->ctrl.ctrl.always_freerun;
7528 	}
7529 
7530 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
7531 		    __func__, reason, mode);
7532 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
7533 		    __func__, dm->wl_only, dm->bt_only);
7534 
7535 	/* Be careful to change the following function sequence!! */
7536 	if (btc->manual_ctrl) {
7537 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7538 			    "[BTC], %s(): return for Manual CTRL!!\n",
7539 			    __func__);
7540 		return;
7541 	}
7542 
7543 	if (igno_bt &&
7544 	    (reason == BTC_RSN_UPDATE_BT_INFO ||
7545 	     reason == BTC_RSN_UPDATE_BT_SCBD)) {
7546 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7547 			    "[BTC], %s(): return for Stop Coex DM!!\n",
7548 			    __func__);
7549 		return;
7550 	}
7551 
7552 	if (!wl->status.map.init_ok) {
7553 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7554 			    "[BTC], %s(): return for WL init fail!!\n",
7555 			    __func__);
7556 		return;
7557 	}
7558 
7559 	if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
7560 	    wl->status.map.lps_pre == wl->status.map.lps) {
7561 		if (reason == BTC_RSN_NTFY_POWEROFF ||
7562 		    reason == BTC_RSN_NTFY_RADIO_STATE) {
7563 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
7564 				    "[BTC], %s(): return for WL rf off state no change!!\n",
7565 				    __func__);
7566 			return;
7567 		}
7568 		if (wl->status.map.rf_off == 1 ||
7569 		    wl->status.map.lps == BTC_LPS_RF_OFF) {
7570 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
7571 				    "[BTC], %s(): return for WL rf off state!!\n",
7572 				    __func__);
7573 			return;
7574 		}
7575 	}
7576 
7577 	dm->freerun = false;
7578 	dm->cnt_dm[BTC_DCNT_RUN]++;
7579 	dm->fddt_train = BTC_FDDT_DISABLE;
7580 	bt->scan_rx_low_pri = false;
7581 	igno_bt = false;
7582 
7583 	dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */
7584 
7585 	if (always_freerun) {
7586 		_action_freerun(rtwdev);
7587 		igno_bt = true;
7588 		goto exit;
7589 	}
7590 
7591 	if (dm->wl_only) {
7592 		_action_wl_only(rtwdev);
7593 		igno_bt = true;
7594 		goto exit;
7595 	}
7596 
7597 	if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) {
7598 		_action_wl_off(rtwdev, mode);
7599 		igno_bt = true;
7600 		goto exit;
7601 	}
7602 
7603 	if (reason == BTC_RSN_NTFY_INIT) {
7604 		_action_wl_init(rtwdev);
7605 		goto exit;
7606 	}
7607 
7608 	if (!cx->bt.enable.now && !cx->other.type) {
7609 		_action_bt_off(rtwdev);
7610 		goto exit;
7611 	}
7612 
7613 	if (cx->bt.whql_test) {
7614 		_action_bt_whql(rtwdev);
7615 		goto exit;
7616 	}
7617 
7618 	if (wl->rfk_info.state != BTC_WRFK_STOP) {
7619 		_action_wl_rfk(rtwdev);
7620 		goto exit;
7621 	}
7622 
7623 	if (wl->status.val & btc_scanning_map.val && !wl->rfk_info.con_rfk) {
7624 		_action_wl_scan(rtwdev);
7625 		bt->scan_rx_low_pri = true;
7626 		goto exit;
7627 	}
7628 
7629 	switch (mode) {
7630 	case BTC_WLINK_NOLINK:
7631 		_action_wl_nc(rtwdev);
7632 		break;
7633 	case BTC_WLINK_2G_STA:
7634 		if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
7635 			bt->scan_rx_low_pri = true;
7636 		_action_wl_2g_sta(rtwdev);
7637 		break;
7638 	case BTC_WLINK_2G_AP:
7639 		bt->scan_rx_low_pri = true;
7640 		_action_wl_2g_ap(rtwdev);
7641 		break;
7642 	case BTC_WLINK_2G_GO:
7643 		bt->scan_rx_low_pri = true;
7644 		_action_wl_2g_go(rtwdev);
7645 		break;
7646 	case BTC_WLINK_2G_GC:
7647 		bt->scan_rx_low_pri = true;
7648 		_action_wl_2g_gc(rtwdev);
7649 		break;
7650 	case BTC_WLINK_2G_SCC:
7651 		bt->scan_rx_low_pri = true;
7652 		if (ver->fwlrole == 0)
7653 			_action_wl_2g_scc(rtwdev);
7654 		else if (ver->fwlrole == 1)
7655 			_action_wl_2g_scc_v1(rtwdev);
7656 		else if (ver->fwlrole == 2 || ver->fwlrole == 7)
7657 			_action_wl_2g_scc_v2(rtwdev);
7658 		else if (ver->fwlrole == 8)
7659 			_action_wl_2g_scc_v8(rtwdev);
7660 		break;
7661 	case BTC_WLINK_2G_MCC:
7662 		bt->scan_rx_low_pri = true;
7663 		_action_wl_2g_mcc(rtwdev);
7664 		break;
7665 	case BTC_WLINK_25G_MCC:
7666 		bt->scan_rx_low_pri = true;
7667 		_action_wl_25g_mcc(rtwdev);
7668 		break;
7669 	case BTC_WLINK_5G:
7670 		_action_wl_5g(rtwdev);
7671 		break;
7672 	case BTC_WLINK_2G_NAN:
7673 		_action_wl_2g_nan(rtwdev);
7674 		break;
7675 	default:
7676 		_action_wl_other(rtwdev);
7677 		break;
7678 	}
7679 
7680 exit:
7681 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__);
7682 	if (ver->fcxctrl == 7)
7683 		btc->ctrl.ctrl_v7.igno_bt = igno_bt;
7684 	else
7685 		btc->ctrl.ctrl.igno_bt = igno_bt;
7686 	_action_common(rtwdev);
7687 }
7688 
rtw89_btc_ntfy_poweron(struct rtw89_dev * rtwdev)7689 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
7690 {
7691 	struct rtw89_btc *btc = &rtwdev->btc;
7692 
7693 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
7694 	btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++;
7695 }
7696 
rtw89_btc_ntfy_poweroff(struct rtw89_dev * rtwdev)7697 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
7698 {
7699 	struct rtw89_btc *btc = &rtwdev->btc;
7700 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7701 
7702 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
7703 	btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
7704 
7705 	btc->cx.wl.status.map.rf_off = 1;
7706 	btc->cx.wl.status.map.busy = 0;
7707 	wl->status.map.lps = BTC_LPS_OFF;
7708 
7709 	_write_scbd(rtwdev, BTC_WSCB_ALL, false);
7710 	_run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
7711 
7712 	rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
7713 
7714 	btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
7715 }
7716 
_set_init_info(struct rtw89_dev * rtwdev)7717 static void _set_init_info(struct rtw89_dev *rtwdev)
7718 {
7719 	const struct rtw89_chip_info *chip = rtwdev->chip;
7720 	struct rtw89_btc *btc = &rtwdev->btc;
7721 	const struct rtw89_btc_ver *ver = btc->ver;
7722 	struct rtw89_btc_dm *dm = &btc->dm;
7723 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7724 
7725 	if (ver->fcxinit == 7) {
7726 		dm->init_info.init_v7.wl_only = (u8)dm->wl_only;
7727 		dm->init_info.init_v7.bt_only = (u8)dm->bt_only;
7728 		dm->init_info.init_v7.wl_init_ok = (u8)wl->status.map.init_ok;
7729 		dm->init_info.init_v7.cx_other = btc->cx.other.type;
7730 		dm->init_info.init_v7.wl_guard_ch = chip->afh_guard_ch;
7731 		dm->init_info.init_v7.module = btc->mdinfo.md_v7;
7732 	} else {
7733 		dm->init_info.init.wl_only = (u8)dm->wl_only;
7734 		dm->init_info.init.bt_only = (u8)dm->bt_only;
7735 		dm->init_info.init.wl_init_ok = (u8)wl->status.map.init_ok;
7736 		dm->init_info.init.dbcc_en = rtwdev->dbcc_en;
7737 		dm->init_info.init.cx_other = btc->cx.other.type;
7738 		dm->init_info.init.wl_guard_ch = chip->afh_guard_ch;
7739 		dm->init_info.init.module = btc->mdinfo.md;
7740 	}
7741 }
7742 
rtw89_btc_ntfy_init(struct rtw89_dev * rtwdev,u8 mode)7743 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
7744 {
7745 	struct rtw89_btc *btc = &rtwdev->btc;
7746 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7747 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7748 	const struct rtw89_chip_info *chip = rtwdev->chip;
7749 	const struct rtw89_btc_ver *ver = btc->ver;
7750 
7751 	_reset_btc_var(rtwdev, BTC_RESET_ALL);
7752 	btc->dm.run_reason = BTC_RSN_NONE;
7753 	btc->dm.run_action = BTC_ACT_NONE;
7754 	if (ver->fcxctrl == 7)
7755 		btc->ctrl.ctrl_v7.igno_bt = true;
7756 	else
7757 		btc->ctrl.ctrl.igno_bt = true;
7758 
7759 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7760 		    "[BTC], %s(): mode=%d\n", __func__, mode);
7761 
7762 	wl->coex_mode = mode;
7763 	dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
7764 	dm->wl_only = mode == BTC_MODE_WL ? 1 : 0;
7765 	dm->bt_only = mode == BTC_MODE_BT ? 1 : 0;
7766 	wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0;
7767 
7768 	chip->ops->btc_set_rfe(rtwdev);
7769 	chip->ops->btc_init_cfg(rtwdev);
7770 
7771 	if (!wl->status.map.init_ok) {
7772 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7773 			    "[BTC], %s(): return for WL init fail!!\n",
7774 			    __func__);
7775 		dm->error.map.init = true;
7776 		return;
7777 	}
7778 
7779 	_write_scbd(rtwdev,
7780 		    BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
7781 	_update_bt_scbd(rtwdev, true);
7782 	if (rtw89_mac_get_ctrl_path(rtwdev)) {
7783 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7784 			    "[BTC], %s(): PTA owner warning!!\n",
7785 			    __func__);
7786 		dm->error.map.pta_owner = true;
7787 	}
7788 
7789 	_set_init_info(rtwdev);
7790 	_set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR);
7791 	btc_fw_set_monreg(rtwdev);
7792 	rtw89_btc_fw_set_slots(rtwdev);
7793 	_fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
7794 	_fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
7795 
7796 	_run_coex(rtwdev, BTC_RSN_NTFY_INIT);
7797 }
7798 
rtw89_btc_ntfy_scan_start(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)7799 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
7800 {
7801 	struct rtw89_btc *btc = &rtwdev->btc;
7802 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7803 
7804 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7805 		    "[BTC], %s(): phy_idx=%d, band=%d\n",
7806 		    __func__, phy_idx, band);
7807 
7808 	if (phy_idx >= RTW89_PHY_NUM)
7809 		return;
7810 
7811 	btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
7812 	wl->status.map.scan = true;
7813 	wl->scan_info.band[phy_idx] = band;
7814 	wl->scan_info.phy_map |= BIT(phy_idx);
7815 	_fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
7816 
7817 	if (rtwdev->dbcc_en) {
7818 		wl->dbcc_info.scan_band[phy_idx] = band;
7819 		_update_dbcc_band(rtwdev, phy_idx);
7820 		_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7821 	}
7822 
7823 	_run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START);
7824 }
7825 
rtw89_btc_ntfy_scan_finish(struct rtw89_dev * rtwdev,u8 phy_idx)7826 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
7827 {
7828 	struct rtw89_btc *btc = &rtwdev->btc;
7829 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7830 
7831 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7832 		    "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
7833 	btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
7834 
7835 	wl->status.map.scan = false;
7836 	wl->scan_info.phy_map &= ~BIT(phy_idx);
7837 	_fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
7838 
7839 	if (rtwdev->dbcc_en) {
7840 		_update_dbcc_band(rtwdev, phy_idx);
7841 		_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7842 	}
7843 
7844 	btc->dm.tdma_instant_excute = 1;
7845 
7846 	_run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
7847 }
7848 
rtw89_btc_ntfy_switch_band(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)7849 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
7850 {
7851 	struct rtw89_btc *btc = &rtwdev->btc;
7852 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7853 
7854 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7855 		    "[BTC], %s(): phy_idx=%d, band=%d\n",
7856 		    __func__, phy_idx, band);
7857 
7858 	if (phy_idx >= RTW89_PHY_NUM)
7859 		return;
7860 
7861 	btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
7862 
7863 	if (rtwdev->dbcc_en) {
7864 		wl->dbcc_info.scan_band[phy_idx] = band;
7865 		_update_dbcc_band(rtwdev, phy_idx);
7866 		_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7867 	}
7868 	_run_coex(rtwdev, BTC_RSN_NTFY_SWBAND);
7869 }
7870 
rtw89_btc_ntfy_specific_packet(struct rtw89_dev * rtwdev,enum btc_pkt_type pkt_type)7871 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev,
7872 				    enum btc_pkt_type pkt_type)
7873 {
7874 	struct rtw89_btc *btc = &rtwdev->btc;
7875 	struct rtw89_btc_cx *cx = &btc->cx;
7876 	struct rtw89_btc_wl_info *wl = &cx->wl;
7877 	struct rtw89_btc_bt_link_info *b = &cx->bt.link_info;
7878 	struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
7879 	struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
7880 	u32 cnt;
7881 	u32 delay = RTW89_COEX_ACT1_WORK_PERIOD;
7882 	bool delay_work = false;
7883 
7884 	switch (pkt_type) {
7885 	case PACKET_DHCP:
7886 		cnt = ++cx->cnt_wl[BTC_WCNT_DHCP];
7887 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7888 			    "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt);
7889 		wl->status.map.connecting = true;
7890 		delay_work = true;
7891 		break;
7892 	case PACKET_EAPOL:
7893 		cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
7894 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7895 			    "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt);
7896 		wl->status.map._4way = true;
7897 		delay_work = true;
7898 		if (hfp->exist || hid->exist)
7899 			delay /= 2;
7900 		break;
7901 	case PACKET_EAPOL_END:
7902 		cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
7903 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7904 			    "[BTC], %s(): EAPOL_End cnt=%d\n",
7905 			    __func__, cnt);
7906 		wl->status.map._4way = false;
7907 		wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work);
7908 		break;
7909 	case PACKET_ARP:
7910 		cnt = ++cx->cnt_wl[BTC_WCNT_ARP];
7911 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7912 			    "[BTC], %s(): ARP cnt=%d\n", __func__, cnt);
7913 		return;
7914 	case PACKET_ICMP:
7915 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7916 			    "[BTC], %s(): ICMP pkt\n", __func__);
7917 		return;
7918 	default:
7919 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7920 			    "[BTC], %s(): unknown packet type %d\n",
7921 			    __func__, pkt_type);
7922 		return;
7923 	}
7924 
7925 	if (delay_work) {
7926 		wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work);
7927 		wiphy_delayed_work_queue(rtwdev->hw->wiphy,
7928 					 &rtwdev->coex_act1_work, delay);
7929 	}
7930 
7931 	btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
7932 	_run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET);
7933 }
7934 
rtw89_btc_ntfy_eapol_packet_work(struct wiphy * wiphy,struct wiphy_work * work)7935 void rtw89_btc_ntfy_eapol_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7936 {
7937 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7938 						btc.eapol_notify_work);
7939 
7940 	lockdep_assert_wiphy(wiphy);
7941 
7942 	rtw89_leave_ps_mode(rtwdev);
7943 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL);
7944 }
7945 
rtw89_btc_ntfy_arp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)7946 void rtw89_btc_ntfy_arp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7947 {
7948 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7949 						btc.arp_notify_work);
7950 
7951 	lockdep_assert_wiphy(wiphy);
7952 
7953 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP);
7954 }
7955 
rtw89_btc_ntfy_dhcp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)7956 void rtw89_btc_ntfy_dhcp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7957 {
7958 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7959 						btc.dhcp_notify_work);
7960 
7961 	lockdep_assert_wiphy(wiphy);
7962 
7963 	rtw89_leave_ps_mode(rtwdev);
7964 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP);
7965 }
7966 
rtw89_btc_ntfy_icmp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)7967 void rtw89_btc_ntfy_icmp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7968 {
7969 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7970 						btc.icmp_notify_work);
7971 
7972 	lockdep_assert_wiphy(wiphy);
7973 
7974 	rtw89_leave_ps_mode(rtwdev);
7975 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP);
7976 }
7977 
_update_bt_rssi_level(struct rtw89_dev * rtwdev,u8 rssi)7978 static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi)
7979 {
7980 	const struct rtw89_chip_info *chip = rtwdev->chip;
7981 	struct rtw89_btc *btc = &rtwdev->btc;
7982 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
7983 	u8 *rssi_st, rssi_th, rssi_level = 0;
7984 	u8 i;
7985 
7986 	/* for rssi locate in which {40, 36, 31, 28}
7987 	 * if rssi >= 40% (-60dBm) --> rssi_level = 4
7988 	 * if 36% <= rssi < 40%    --> rssi_level = 3
7989 	 * if 31% <= rssi < 36%    --> rssi_level = 2
7990 	 * if 28% <= rssi < 31%    --> rssi_level = 1
7991 	 * if rssi < 28%           --> rssi_level = 0
7992 	 */
7993 
7994 	/* check if rssi across bt_rssi_thres boundary */
7995 	for (i = 0; i < BTC_BT_RSSI_THMAX; i++) {
7996 		rssi_th = chip->bt_rssi_thres[i];
7997 		rssi_st = &bt->link_info.rssi_state[i];
7998 
7999 		*rssi_st = _update_rssi_state(rtwdev, *rssi_st, rssi, rssi_th);
8000 
8001 		if (BTC_RSSI_HIGH(*rssi_st)) {
8002 			rssi_level = BTC_BT_RSSI_THMAX - i;
8003 			break;
8004 		}
8005 	}
8006 	return rssi_level;
8007 }
8008 
_update_zb_coex_tbl(struct rtw89_dev * rtwdev)8009 static void _update_zb_coex_tbl(struct rtw89_dev *rtwdev)
8010 {
8011 	u8 mode = rtwdev->btc.cx.wl.role_info.link_mode;
8012 	u32 zb_tbl0 = 0xda5a5a5a, zb_tbl1 = 0xda5a5a5a;
8013 
8014 	if (mode == BTC_WLINK_5G || rtwdev->btc.dm.freerun) {
8015 		zb_tbl0 = 0xffffffff;
8016 		zb_tbl1 = 0xffffffff;
8017 	} else if (mode == BTC_WLINK_25G_MCC) {
8018 		zb_tbl0 = 0xffffffff; /* for E5G slot */
8019 		zb_tbl1 = 0xda5a5a5a; /* for E2G slot */
8020 	}
8021 	rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_0, zb_tbl0);
8022 	rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_1, zb_tbl1);
8023 }
8024 
8025 #define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4)
8026 
_update_bt_info(struct rtw89_dev * rtwdev,u8 * buf,u32 len)8027 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
8028 {
8029 	const struct rtw89_chip_info *chip = rtwdev->chip;
8030 	struct rtw89_btc *btc = &rtwdev->btc;
8031 	struct rtw89_btc_cx *cx = &btc->cx;
8032 	struct rtw89_btc_bt_info *bt = &cx->bt;
8033 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
8034 	struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
8035 	struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
8036 	struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
8037 	struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc;
8038 	union btc_btinfo btinfo;
8039 
8040 	if (buf[BTC_BTINFO_L1] != 6)
8041 		return;
8042 
8043 	if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) {
8044 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8045 			    "[BTC], %s(): return by bt-info duplicate!!\n",
8046 			    __func__);
8047 		cx->cnt_bt[BTC_BCNT_INFOSAME]++;
8048 		return;
8049 	}
8050 
8051 	memcpy(bt->raw_info, buf, BTC_BTINFO_MAX);
8052 
8053 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
8054 		    "[BTC], %s(): bt_info[2]=0x%02x\n",
8055 		    __func__, bt->raw_info[2]);
8056 
8057 	b->profile_cnt.last = b->profile_cnt.now;
8058 	b->profile_cnt.now = 0;
8059 	hid->type = 0;
8060 
8061 	/* parse raw info low-Byte2 */
8062 	btinfo.val = bt->raw_info[BTC_BTINFO_L2];
8063 	b->status.map.connect = btinfo.lb2.connect;
8064 	b->status.map.sco_busy = btinfo.lb2.sco_busy;
8065 	b->status.map.acl_busy = btinfo.lb2.acl_busy;
8066 	b->status.map.inq_pag = btinfo.lb2.inq_pag;
8067 	bt->inq_pag.now = btinfo.lb2.inq_pag;
8068 	cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
8069 
8070 	hfp->exist = btinfo.lb2.hfp;
8071 	b->profile_cnt.now += (u8)hfp->exist;
8072 	hid->exist = btinfo.lb2.hid;
8073 	b->profile_cnt.now += (u8)hid->exist;
8074 	a2dp->exist = btinfo.lb2.a2dp;
8075 	b->profile_cnt.now += (u8)a2dp->exist;
8076 	pan->exist = btinfo.lb2.pan;
8077 	b->profile_cnt.now += (u8)pan->exist;
8078 	btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK);
8079 
8080 	/* parse raw info low-Byte3 */
8081 	btinfo.val = bt->raw_info[BTC_BTINFO_L3];
8082 	if (btinfo.lb3.retry != 0)
8083 		cx->cnt_bt[BTC_BCNT_RETRY]++;
8084 	b->cqddr = btinfo.lb3.cqddr;
8085 	cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
8086 	bt->inq = btinfo.lb3.inq;
8087 	cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
8088 	bt->pag = btinfo.lb3.pag;
8089 
8090 	b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
8091 	/* parse raw info high-Byte0 */
8092 	btinfo.val = bt->raw_info[BTC_BTINFO_H0];
8093 	/* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/
8094 	b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi);
8095 	bt->rssi_level = _update_bt_rssi_level(rtwdev, b->rssi);
8096 	btc->dm.trx_info.bt_rssi = bt->rssi_level;
8097 
8098 	/* parse raw info high-Byte1 */
8099 	btinfo.val = bt->raw_info[BTC_BTINFO_H1];
8100 	b->status.map.ble_connect = btinfo.hb1.ble_connect;
8101 	if (btinfo.hb1.ble_connect) {
8102 		if (hid->exist)
8103 			hid->type |= BTC_HID_BLE;
8104 		else if (btinfo.hb1.voice)
8105 			hid->type |= BTC_HID_RCU_VOICE;
8106 		else
8107 			hid->type |= BTC_HID_RCU;
8108 	}
8109 
8110 	cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
8111 	bt->reinit = btinfo.hb1.reinit;
8112 	cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
8113 	b->relink.now = btinfo.hb1.relink;
8114 	cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
8115 	bt->igno_wl = btinfo.hb1.igno_wl;
8116 
8117 	if (bt->igno_wl && !cx->wl.status.map.rf_off)
8118 		_set_bt_ignore_wlan_act(rtwdev, false);
8119 
8120 	bt->ble_scan_en = btinfo.hb1.ble_scan;
8121 
8122 	cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
8123 	b->role_sw = btinfo.hb1.role_sw;
8124 
8125 	b->multi_link.now = btinfo.hb1.multi_link;
8126 
8127 	/* parse raw info high-Byte2 */
8128 	btinfo.val = bt->raw_info[BTC_BTINFO_H2];
8129 	pan->active = !!btinfo.hb2.pan_active;
8130 
8131 	cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
8132 	b->afh_update = btinfo.hb2.afh_update;
8133 	a2dp->active = btinfo.hb2.a2dp_active;
8134 	b->slave_role = btinfo.hb2.slave;
8135 	hid->slot_info = btinfo.hb2.hid_slot;
8136 	hid->pair_cnt = btinfo.hb2.hid_cnt;
8137 	if (!b->status.map.ble_connect || hid->pair_cnt > 1)
8138 		hid->type |= (hid->slot_info == BTC_HID_218 ?
8139 			      BTC_HID_218 : BTC_HID_418);
8140 	/* parse raw info high-Byte3 */
8141 	btinfo.val = bt->raw_info[BTC_BTINFO_H3];
8142 	a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
8143 
8144 	if (b->tx_3m != (u32)btinfo.hb3.tx_3m)
8145 		cx->cnt_bt[BTC_BCNT_RATECHG]++;
8146 	b->tx_3m = (u32)btinfo.hb3.tx_3m;
8147 
8148 	a2dp->sink = btinfo.hb3.a2dp_sink;
8149 
8150 	if (!a2dp->exist_last && a2dp->exist) {
8151 		a2dp->vendor_id = 0;
8152 		a2dp->flush_time = 0;
8153 		a2dp->play_latency = 1;
8154 		wiphy_delayed_work_queue(rtwdev->hw->wiphy,
8155 					 &rtwdev->coex_bt_devinfo_work,
8156 					 RTW89_COEX_BT_DEVINFO_WORK_PERIOD);
8157 	}
8158 
8159 	_run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
8160 }
8161 
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)8162 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev,
8163 			      struct rtw89_vif_link *rtwvif_link,
8164 			      struct rtw89_sta_link *rtwsta_link,
8165 			      enum btc_role_state state)
8166 {
8167 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
8168 						       rtwvif_link->chanctx_idx);
8169 	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
8170 	struct ieee80211_bss_conf *bss_conf;
8171 	struct ieee80211_link_sta *link_sta;
8172 	struct rtw89_btc *btc = &rtwdev->btc;
8173 	const struct rtw89_btc_ver *ver = btc->ver;
8174 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8175 	struct rtw89_btc_wl_link_info r = {0};
8176 	struct rtw89_btc_wl_link_info *wlinfo = NULL;
8177 	u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type;
8178 
8179 	rcu_read_lock();
8180 
8181 	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
8182 
8183 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
8184 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
8185 		    "[BTC], role is STA=%d\n",
8186 		    vif->type == NL80211_IFTYPE_STATION);
8187 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif_link->port);
8188 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
8189 		    chan->band_type, chan->channel, chan->band_width);
8190 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
8191 		    state == BTC_ROLE_MSTS_STA_CONN_END);
8192 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
8193 		    "[BTC], bcn_period=%d dtim_period=%d\n",
8194 		    bss_conf->beacon_int, bss_conf->dtim_period);
8195 
8196 	if (rtwsta_link) {
8197 		link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
8198 
8199 		rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
8200 			    rtwsta_link->mac_id);
8201 
8202 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8203 			    "[BTC], STA support HE=%d VHT=%d HT=%d\n",
8204 			    link_sta->he_cap.has_he,
8205 			    link_sta->vht_cap.vht_supported,
8206 			    link_sta->ht_cap.ht_supported);
8207 		if (link_sta->he_cap.has_he)
8208 			mode |= BIT(BTC_WL_MODE_HE);
8209 		if (link_sta->vht_cap.vht_supported)
8210 			mode |= BIT(BTC_WL_MODE_VHT);
8211 		if (link_sta->ht_cap.ht_supported)
8212 			mode |= BIT(BTC_WL_MODE_HT);
8213 
8214 		r.mode = mode;
8215 	}
8216 
8217 	if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) {
8218 		rcu_read_unlock();
8219 		return;
8220 	}
8221 
8222 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
8223 		    "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role);
8224 
8225 	r.role = rtwvif_link->wifi_role;
8226 	r.phy = rtwvif_link->phy_idx;
8227 	r.pid = rtwvif_link->port;
8228 	r.active = true;
8229 	r.connected = MLME_LINKED;
8230 	r.bcn_period = bss_conf->beacon_int;
8231 	r.dtim_period = bss_conf->dtim_period;
8232 	r.band = chan->band_type;
8233 	r.ch = chan->channel;
8234 	r.bw = chan->band_width;
8235 	r.chdef.band = chan->band_type;
8236 	r.chdef.center_ch = chan->channel;
8237 	r.chdef.bw = chan->band_width;
8238 	r.chdef.chan = chan->primary_channel;
8239 	ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr);
8240 
8241 	rcu_read_unlock();
8242 
8243 	if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION)
8244 		r.mac_id = rtwsta_link->mac_id;
8245 
8246 	btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
8247 
8248 	wlinfo = &wl->link_info[r.pid];
8249 
8250 	if (ver->fwlrole == 0) {
8251 		*wlinfo = r;
8252 		_update_wl_info(rtwdev);
8253 	} else if (ver->fwlrole == 1) {
8254 		*wlinfo = r;
8255 		_update_wl_info_v1(rtwdev);
8256 	} else if (ver->fwlrole == 2) {
8257 		*wlinfo = r;
8258 		_update_wl_info_v2(rtwdev);
8259 	} else if (ver->fwlrole == 7) {
8260 		*wlinfo = r;
8261 		_update_wl_info_v7(rtwdev, r.pid);
8262 	} else if (ver->fwlrole == 8) {
8263 		rlink_id = rtwvif_link->mac_idx;
8264 		wlinfo = &wl->rlink_info[r.pid][rlink_id];
8265 		*wlinfo = r;
8266 		link_mode_ori = wl->role_info_v8.link_mode;
8267 		pta_req_mac_ori = wl->pta_req_mac;
8268 		_update_wl_info_v8(rtwdev, r.pid, rlink_id, state);
8269 
8270 		if (wl->role_info_v8.link_mode != link_mode_ori) {
8271 			wl->role_info_v8.link_mode_chg = 1;
8272 			if (ver->fcxinit == 7)
8273 				wa_type = btc->mdinfo.md_v7.wa_type;
8274 			else
8275 				wa_type = btc->mdinfo.md.wa_type;
8276 
8277 			if (wa_type & BTC_WA_HFP_ZB)
8278 				_update_zb_coex_tbl(rtwdev);
8279 		}
8280 
8281 		if (wl->pta_req_mac != pta_req_mac_ori)
8282 			wl->pta_reg_mac_chg = 1;
8283 	}
8284 
8285 	if (wlinfo->role == RTW89_WIFI_ROLE_STATION &&
8286 	    wlinfo->connected == MLME_NO_LINK)
8287 		btc->dm.leak_ap = 0;
8288 
8289 	if (state == BTC_ROLE_MSTS_STA_CONN_START)
8290 		wl->status.map.connecting = 1;
8291 	else
8292 		wl->status.map.connecting = 0;
8293 
8294 	if (state == BTC_ROLE_MSTS_STA_DIS_CONN ||
8295 	    state == BTC_ROLE_MSTS_STA_CONN_END)
8296 		wl->status.map._4way = false;
8297 
8298 	_run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
8299 }
8300 
rtw89_btc_ntfy_radio_state(struct rtw89_dev * rtwdev,enum btc_rfctrl rf_state)8301 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state)
8302 {
8303 	const struct rtw89_chip_info *chip = rtwdev->chip;
8304 	struct rtw89_btc *btc = &rtwdev->btc;
8305 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8306 	u32 val;
8307 
8308 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
8309 		    __func__, rf_state);
8310 	btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
8311 
8312 	switch (rf_state) {
8313 	case BTC_RFCTRL_WL_OFF:
8314 		wl->status.map.rf_off = 1;
8315 		wl->status.map.lps = BTC_LPS_OFF;
8316 		wl->status.map.busy = 0;
8317 		break;
8318 	case BTC_RFCTRL_FW_CTRL:
8319 		wl->status.map.rf_off = 0;
8320 		wl->status.map.lps = BTC_LPS_RF_OFF;
8321 		wl->status.map.busy = 0;
8322 		break;
8323 	case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */
8324 		wl->status.map.rf_off = 0;
8325 		wl->status.map.lps = BTC_LPS_RF_ON;
8326 		wl->status.map.busy = 0;
8327 		break;
8328 	case BTC_RFCTRL_WL_ON:
8329 	default:
8330 		wl->status.map.rf_off = 0;
8331 		wl->status.map.lps = BTC_LPS_OFF;
8332 		break;
8333 	}
8334 
8335 	if (rf_state == BTC_RFCTRL_WL_ON) {
8336 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, true);
8337 		val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG;
8338 		_write_scbd(rtwdev, val, true);
8339 		_update_bt_scbd(rtwdev, true);
8340 		chip->ops->btc_init_cfg(rtwdev);
8341 	} else {
8342 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false);
8343 		if (rf_state == BTC_RFCTRL_FW_CTRL)
8344 			_write_scbd(rtwdev, BTC_WSCB_ACTIVE, false);
8345 		else if (rf_state == BTC_RFCTRL_WL_OFF)
8346 			_write_scbd(rtwdev, BTC_WSCB_ALL, false);
8347 		else
8348 			_write_scbd(rtwdev, BTC_WSCB_ACTIVE, false);
8349 
8350 		if (rf_state == BTC_RFCTRL_LPS_WL_ON &&
8351 		    wl->status.map.lps_pre != BTC_LPS_OFF)
8352 			_update_bt_scbd(rtwdev, true);
8353 	}
8354 
8355 	btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
8356 	btc->dm.tdma_instant_excute = 1;
8357 
8358 	_run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
8359 	wl->status.map.rf_off_pre = wl->status.map.rf_off;
8360 	wl->status.map.lps_pre = wl->status.map.lps;
8361 }
8362 
_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_path,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)8363 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path,
8364 			 enum btc_wl_rfk_type type,
8365 			 enum btc_wl_rfk_state state)
8366 {
8367 	struct rtw89_btc *btc = &rtwdev->btc;
8368 	struct rtw89_btc_cx *cx = &btc->cx;
8369 	struct rtw89_btc_wl_info *wl = &cx->wl;
8370 	bool result = BTC_WRFK_REJECT;
8371 
8372 	wl->rfk_info.type = type;
8373 	wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path);
8374 	wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path);
8375 	wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path);
8376 
8377 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
8378 		    "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
8379 		    __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
8380 		    type, state);
8381 
8382 	switch (state) {
8383 	case BTC_WRFK_START:
8384 		result = _chk_wl_rfk_request(rtwdev);
8385 		wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP;
8386 
8387 		_write_scbd(rtwdev, BTC_WSCB_WLRFK, result);
8388 
8389 		btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
8390 		break;
8391 	case BTC_WRFK_ONESHOT_START:
8392 	case BTC_WRFK_ONESHOT_STOP:
8393 		if (wl->rfk_info.state == BTC_WRFK_STOP) {
8394 			result = BTC_WRFK_REJECT;
8395 		} else {
8396 			result = BTC_WRFK_ALLOW;
8397 			wl->rfk_info.state = state;
8398 		}
8399 		break;
8400 	case BTC_WRFK_STOP:
8401 		result = BTC_WRFK_ALLOW;
8402 		wl->rfk_info.state = BTC_WRFK_STOP;
8403 
8404 		_write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
8405 		wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_rfk_chk_work);
8406 		break;
8407 	default:
8408 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8409 			    "[BTC], %s() warning state=%d\n", __func__, state);
8410 		break;
8411 	}
8412 
8413 	if (result == BTC_WRFK_ALLOW) {
8414 		if (wl->rfk_info.state == BTC_WRFK_START ||
8415 		    wl->rfk_info.state == BTC_WRFK_STOP)
8416 			_run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK);
8417 
8418 		if (wl->rfk_info.state == BTC_WRFK_START)
8419 			wiphy_delayed_work_queue(rtwdev->hw->wiphy,
8420 						 &rtwdev->coex_rfk_chk_work,
8421 						 RTW89_COEX_RFK_CHK_WORK_PERIOD);
8422 	}
8423 
8424 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
8425 		    "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
8426 		    __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
8427 
8428 	return result == BTC_WRFK_ALLOW;
8429 }
8430 
rtw89_btc_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_map,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)8431 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
8432 			   enum btc_wl_rfk_type type,
8433 			   enum btc_wl_rfk_state state)
8434 {
8435 	u8 band;
8436 	bool allow;
8437 	int ret;
8438 
8439 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
8440 
8441 	band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map);
8442 
8443 	rtw89_debug(rtwdev, RTW89_DBG_RFK,
8444 		    "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n",
8445 		    band == RTW89_BAND_2G ? "2G" :
8446 		    band == RTW89_BAND_5G ? "5G" : "6G",
8447 		    !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)),
8448 		    type,
8449 		    FIELD_GET(BTC_RFK_PATH_MAP, phy_map),
8450 		    state == BTC_WRFK_STOP ? "RFK_STOP" :
8451 		    state == BTC_WRFK_START ? "RFK_START" :
8452 		    state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" :
8453 		    "ONE-SHOT_STOP");
8454 
8455 	if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) {
8456 		_ntfy_wl_rfk(rtwdev, phy_map, type, state);
8457 		return;
8458 	}
8459 
8460 	ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false,
8461 				rtwdev, phy_map, type, state);
8462 	if (ret) {
8463 		rtw89_warn(rtwdev, "RFK notify timeout\n");
8464 		rtwdev->is_bt_iqk_timeout = true;
8465 	}
8466 }
8467 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk);
8468 
8469 struct rtw89_btc_wl_sta_iter_data {
8470 	struct rtw89_dev *rtwdev;
8471 	u8 busy_all;
8472 	u8 dir_all;
8473 	u8 rssi_map_all;
8474 	bool is_sta_change;
8475 	bool is_traffic_change;
8476 };
8477 
8478 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)8479 void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link,
8480 				  struct rtw89_sta_link *rtwsta_link,
8481 				  struct rtw89_btc_wl_sta_iter_data *iter_data)
8482 {
8483 	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
8484 	struct rtw89_dev *rtwdev = iter_data->rtwdev;
8485 	struct rtw89_btc *btc = &rtwdev->btc;
8486 	struct rtw89_btc_dm *dm = &btc->dm;
8487 	const struct rtw89_btc_ver *ver = btc->ver;
8488 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8489 	struct rtw89_btc_wl_link_info *link_info = NULL;
8490 	struct rtw89_traffic_stats *link_info_t = NULL;
8491 	struct rtw89_traffic_stats *stats = &rtwvif->stats;
8492 	const struct rtw89_chip_info *chip = rtwdev->chip;
8493 	struct rtw89_btc_wl_role_info *r;
8494 	struct rtw89_btc_wl_role_info_v1 *r1;
8495 	u32 last_tx_rate, last_rx_rate;
8496 	u16 last_tx_lvl, last_rx_lvl;
8497 	u8 port = rtwvif_link->port;
8498 	u8 rssi;
8499 	u8 busy = 0;
8500 	u8 dir = 0;
8501 	u8 rssi_map = 0;
8502 	u8 i = 0;
8503 	bool is_sta_change = false, is_traffic_change = false;
8504 
8505 	rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR;
8506 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
8507 
8508 	if (btc->ver->fwlrole != 8)
8509 		link_info = &wl->link_info[port];
8510 	else
8511 		link_info = &wl->rlink_info[port][rtwvif_link->mac_idx];
8512 
8513 	link_info->stat.traffic = *stats;
8514 	link_info_t = &link_info->stat.traffic;
8515 
8516 	if (link_info->connected == MLME_NO_LINK) {
8517 		link_info->rx_rate_drop_cnt = 0;
8518 		return;
8519 	}
8520 
8521 	link_info->stat.rssi = rssi;
8522 	for (i = 0; i < BTC_WL_RSSI_THMAX; i++) {
8523 		link_info->rssi_state[i] =
8524 			_update_rssi_state(rtwdev,
8525 					   link_info->rssi_state[i],
8526 					   link_info->stat.rssi,
8527 					   chip->wl_rssi_thres[i]);
8528 		if (BTC_RSSI_LOW(link_info->rssi_state[i]))
8529 			rssi_map |= BIT(i);
8530 
8531 		if (btc->ant_type == BTC_ANT_DEDICATED &&
8532 		    BTC_RSSI_CHANGE(link_info->rssi_state[i]))
8533 			is_sta_change = true;
8534 	}
8535 	iter_data->rssi_map_all |= rssi_map;
8536 
8537 	last_tx_rate = link_info_t->tx_rate;
8538 	last_rx_rate = link_info_t->rx_rate;
8539 	last_tx_lvl = (u16)link_info_t->tx_tfc_lv;
8540 	last_rx_lvl = (u16)link_info_t->rx_tfc_lv;
8541 
8542 	if (stats->tx_tfc_lv != RTW89_TFC_IDLE ||
8543 	    stats->rx_tfc_lv != RTW89_TFC_IDLE)
8544 		busy = 1;
8545 
8546 	if (stats->tx_tfc_lv > stats->rx_tfc_lv)
8547 		dir = RTW89_TFC_UL;
8548 	else
8549 		dir = RTW89_TFC_DL;
8550 
8551 	link_info = &wl->link_info[port];
8552 	if (link_info->busy != busy || link_info->dir != dir) {
8553 		is_sta_change = true;
8554 		link_info->busy = busy;
8555 		link_info->dir = dir;
8556 	}
8557 
8558 	iter_data->busy_all |= busy;
8559 	iter_data->dir_all |= BIT(dir);
8560 
8561 	if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
8562 	    last_rx_rate > RTW89_HW_RATE_CCK2 &&
8563 	    link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
8564 		link_info->rx_rate_drop_cnt++;
8565 
8566 	if (last_tx_rate != rtwsta_link->ra_report.hw_rate ||
8567 	    last_rx_rate != rtwsta_link->rx_hw_rate ||
8568 	    last_tx_lvl != link_info_t->tx_tfc_lv ||
8569 	    last_rx_lvl != link_info_t->rx_tfc_lv)
8570 		is_traffic_change = true;
8571 
8572 	link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate;
8573 	link_info_t->rx_rate = rtwsta_link->rx_hw_rate;
8574 
8575 	if (link_info->role == RTW89_WIFI_ROLE_STATION ||
8576 	    link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) {
8577 		dm->trx_info.tx_rate = link_info_t->tx_rate;
8578 		dm->trx_info.rx_rate = link_info_t->rx_rate;
8579 	}
8580 
8581 	if (ver->fwlrole == 0) {
8582 		r = &wl->role_info;
8583 		r->active_role[port].tx_lvl = stats->tx_tfc_lv;
8584 		r->active_role[port].rx_lvl = stats->rx_tfc_lv;
8585 		r->active_role[port].tx_rate = rtwsta_link->ra_report.hw_rate;
8586 		r->active_role[port].rx_rate = rtwsta_link->rx_hw_rate;
8587 	} else if (ver->fwlrole == 1) {
8588 		r1 = &wl->role_info_v1;
8589 		r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv;
8590 		r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv;
8591 		r1->active_role_v1[port].tx_rate = rtwsta_link->ra_report.hw_rate;
8592 		r1->active_role_v1[port].rx_rate = rtwsta_link->rx_hw_rate;
8593 	}
8594 
8595 	dm->trx_info.tx_lvl = stats->tx_tfc_lv;
8596 	dm->trx_info.rx_lvl = stats->rx_tfc_lv;
8597 	dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate;
8598 	dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate;
8599 	dm->trx_info.tx_tp = link_info_t->tx_throughput;
8600 	dm->trx_info.rx_tp = link_info_t->rx_throughput;
8601 
8602 	/* Trigger coex-run if 0x10980 reg-value is diff with coex setup */
8603 	if ((dm->wl_btg_rx_rb != dm->wl_btg_rx &&
8604 	     dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) ||
8605 	     (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
8606 	      dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND))
8607 		iter_data->is_sta_change = true;
8608 
8609 	if (is_sta_change)
8610 		iter_data->is_sta_change = true;
8611 
8612 	if (is_traffic_change)
8613 		iter_data->is_traffic_change = true;
8614 }
8615 
rtw89_btc_ntfy_wl_sta_iter(void * data,struct ieee80211_sta * sta)8616 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
8617 {
8618 	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
8619 	struct rtw89_btc_wl_sta_iter_data *iter_data =
8620 				(struct rtw89_btc_wl_sta_iter_data *)data;
8621 	struct rtw89_vif_link *rtwvif_link;
8622 	struct rtw89_sta_link *rtwsta_link;
8623 	unsigned int link_id;
8624 
8625 	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
8626 		rtwvif_link = rtwsta_link->rtwvif_link;
8627 		__rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data);
8628 	}
8629 }
8630 
8631 #define BTC_NHM_CHK_INTVL 20
8632 
rtw89_btc_ntfy_wl_sta(struct rtw89_dev * rtwdev)8633 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
8634 {
8635 	struct rtw89_btc *btc = &rtwdev->btc;
8636 	struct rtw89_btc_dm *dm = &btc->dm;
8637 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8638 	struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev};
8639 	u8 i;
8640 
8641 	ieee80211_iterate_stations_atomic(rtwdev->hw,
8642 					  rtw89_btc_ntfy_wl_sta_iter,
8643 					  &data);
8644 
8645 	wl->rssi_level = 0;
8646 	btc->dm.cnt_notify[BTC_NCNT_WL_STA]++;
8647 	for (i = BTC_WL_RSSI_THMAX; i > 0; i--) {
8648 		/* set RSSI level 4 ~ 0 if rssi bit map match */
8649 		if (data.rssi_map_all & BIT(i - 1)) {
8650 			wl->rssi_level = i;
8651 			break;
8652 		}
8653 	}
8654 
8655 	if (dm->trx_info.wl_rssi != wl->rssi_level)
8656 		dm->trx_info.wl_rssi = wl->rssi_level;
8657 
8658 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n",
8659 		    __func__, !!wl->status.map.busy);
8660 
8661 	_write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy));
8662 
8663 	if (data.is_traffic_change)
8664 		_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
8665 	if (data.is_sta_change) {
8666 		wl->status.map.busy = data.busy_all;
8667 		wl->status.map.traffic_dir = data.dir_all;
8668 		_run_coex(rtwdev, BTC_RSN_NTFY_WL_STA);
8669 	} else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >=
8670 		   btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) {
8671 		btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
8672 			btc->dm.cnt_notify[BTC_NCNT_WL_STA];
8673 	} else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] <
8674 		   btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) {
8675 		btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
8676 		btc->dm.cnt_notify[BTC_NCNT_WL_STA];
8677 	}
8678 }
8679 
rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev * rtwdev,u8 func)8680 static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func)
8681 {
8682 	struct rtw89_btc *btc = &rtwdev->btc;
8683 	const struct rtw89_btc_ver *ver = btc->ver;
8684 
8685 	switch (func) {
8686 	case BTF_EVNT_RPT:
8687 	case BTF_EVNT_BT_INFO:
8688 	case BTF_EVNT_BT_SCBD:
8689 	case BTF_EVNT_BT_REG:
8690 	case BTF_EVNT_CX_RUNINFO:
8691 	case BTF_EVNT_BT_PSD:
8692 		return func;
8693 	case BTF_EVNT_BT_DEV_INFO:
8694 		if (ver->fwc2hfunc == 0)
8695 			return BTF_EVNT_BUF_OVERFLOW;
8696 		else
8697 			return BTF_EVNT_BT_DEV_INFO;
8698 	case BTF_EVNT_BT_LEAUDIO_INFO:
8699 		if (ver->fwc2hfunc == 0)
8700 			return BTF_EVNT_C2H_LOOPBACK;
8701 		else if (ver->fwc2hfunc == 1)
8702 			return BTF_EVNT_BUF_OVERFLOW;
8703 		else if (ver->fwc2hfunc == 2)
8704 			return func;
8705 		else if (ver->fwc2hfunc == 3)
8706 			return BTF_EVNT_BUF_OVERFLOW;
8707 		else
8708 			return BTF_EVNT_MAX;
8709 	case BTF_EVNT_BUF_OVERFLOW:
8710 		if (ver->fwc2hfunc == 0)
8711 			return BTF_EVNT_MAX;
8712 		else if (ver->fwc2hfunc == 1)
8713 			return BTF_EVNT_C2H_LOOPBACK;
8714 		else if (ver->fwc2hfunc == 2)
8715 			return func;
8716 		else if (ver->fwc2hfunc == 3)
8717 			return BTF_EVNT_C2H_LOOPBACK;
8718 		else
8719 			return BTF_EVNT_MAX;
8720 	case BTF_EVNT_C2H_LOOPBACK:
8721 		if (ver->fwc2hfunc == 2)
8722 			return func;
8723 		else if (ver->fwc2hfunc == 3)
8724 			return BTF_EVNT_BT_LEAUDIO_INFO;
8725 		else
8726 			return BTF_EVNT_MAX;
8727 	case BTF_EVNT_BT_QUERY_TXPWR:
8728 		if (ver->fwc2hfunc == 3)
8729 			return func;
8730 		else
8731 			return BTF_EVNT_MAX;
8732 	case BTF_EVNT_MAX:
8733 	default:
8734 		return BTF_EVNT_MAX;
8735 	}
8736 }
8737 
rtw89_btc_c2h_handle(struct rtw89_dev * rtwdev,struct sk_buff * skb,u32 len,u8 class,u8 func)8738 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
8739 			  u32 len, u8 class, u8 func)
8740 {
8741 	struct rtw89_btc *btc = &rtwdev->btc;
8742 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
8743 	u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN];
8744 
8745 	len -= RTW89_C2H_HEADER_LEN;
8746 
8747 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
8748 		    "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n",
8749 		    __func__, len, class, func);
8750 
8751 	if (class != BTFC_FW_EVENT)
8752 		return;
8753 
8754 	func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func);
8755 	pfwinfo->cnt_c2h++;
8756 
8757 	switch (func) {
8758 	case BTF_EVNT_BUF_OVERFLOW:
8759 		pfwinfo->event[func]++;
8760 		break;
8761 	case BTF_EVNT_RPT:
8762 		pfwinfo->event[func]++;
8763 		/* Don't need rtw89_leave_ps_mode() */
8764 		btc_fw_event(rtwdev, func, buf, len);
8765 		break;
8766 	case BTF_EVNT_BT_INFO:
8767 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8768 			    "[BTC], handle C2H BT INFO with data %8ph\n", buf);
8769 		btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++;
8770 		_update_bt_info(rtwdev, buf, len);
8771 		break;
8772 	case BTF_EVNT_BT_SCBD:
8773 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8774 			    "[BTC], handle C2H BT SCBD with data %8ph\n", buf);
8775 		btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++;
8776 		_update_bt_scbd(rtwdev, false);
8777 		break;
8778 	case BTF_EVNT_BT_PSD:
8779 		break;
8780 	case BTF_EVNT_BT_REG:
8781 		btc->dbg.rb_done = true;
8782 		btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf));
8783 
8784 		break;
8785 	case BTF_EVNT_C2H_LOOPBACK:
8786 		btc->dbg.rb_done = true;
8787 		btc->dbg.rb_val = buf[0];
8788 		break;
8789 	case BTF_EVNT_CX_RUNINFO:
8790 		btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
8791 		break;
8792 	case BTF_EVNT_BT_QUERY_TXPWR:
8793 		btc->cx.cnt_bt[BTC_BCNT_BTTXPWR_UPDATE]++;
8794 		_update_bt_txpwr_info(rtwdev, buf, len);
8795 	}
8796 }
8797 
8798 #define BTC_CX_FW_OFFLOAD 0
8799 
_show_cx_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)8800 static int _show_cx_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
8801 {
8802 	union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo;
8803 	const struct rtw89_chip_info *chip = rtwdev->chip;
8804 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
8805 	struct rtw89_hal *hal = &rtwdev->hal;
8806 	struct rtw89_btc *btc = &rtwdev->btc;
8807 	struct rtw89_btc_dm *dm = &btc->dm;
8808 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
8809 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8810 	u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
8811 	u8 cv, rfe, iso, ant_num, ant_single_pos;
8812 	char *p = buf, *end = buf + bufsz;
8813 
8814 	if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
8815 		return 0;
8816 
8817 	p += scnprintf(p, end - p,
8818 		       "\n========== [BTC COEX INFO (%s)] ==========\n",
8819 		       chip_id_str(chip->chip_id));
8820 
8821 	ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION);
8822 	ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION);
8823 	ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION);
8824 	id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION);
8825 	p += scnprintf(p, end - p, " %-15s : Coex:%d.%d.%d(branch:%d), ",
8826 		       "[coex_version]", ver_main, ver_sub, ver_hotfix,
8827 		       id_branch);
8828 
8829 	ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
8830 	ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex);
8831 	ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex);
8832 	id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex);
8833 	p += scnprintf(p, end - p, "WL_FW_coex:%d.%d.%d(branch:%d)",
8834 		       ver_main, ver_sub, ver_hotfix, id_branch);
8835 
8836 	ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired);
8837 	ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired);
8838 	ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
8839 	p += scnprintf(p, end - p, "(%s, desired:%d.%d.%d), ",
8840 		       (wl->ver_info.fw_coex >= chip->wlcx_desired ?
8841 			"Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
8842 
8843 	p += scnprintf(p, end - p, "BT_FW_coex:%d(%s, desired:%d)\n",
8844 		       bt->ver_info.fw_coex,
8845 		       (bt->ver_info.fw_coex >= ver->bt_desired ?
8846 			"Match" : "Mismatch"), ver->bt_desired);
8847 
8848 	if (bt->enable.now && bt->ver_info.fw == 0)
8849 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true);
8850 	else
8851 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false);
8852 
8853 	ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw);
8854 	ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw);
8855 	ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw);
8856 	id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw);
8857 	p += scnprintf(p, end - p,
8858 		       " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n",
8859 		       "[sub_module]",
8860 		       ver_main, ver_sub, ver_hotfix, id_branch,
8861 		       bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM");
8862 
8863 	if (ver->fcxinit == 7) {
8864 		cv = md->md_v7.kt_ver;
8865 		rfe = md->md_v7.rfe_type;
8866 		iso = md->md_v7.ant.isolation;
8867 		ant_num = md->md_v7.ant.num;
8868 		ant_single_pos = md->md_v7.ant.single_pos;
8869 	} else {
8870 		cv = md->md.cv;
8871 		rfe = md->md.rfe_type;
8872 		iso = md->md.ant.isolation;
8873 		ant_num = md->md.ant.num;
8874 		ant_single_pos = md->md.ant.single_pos;
8875 	}
8876 
8877 	p += scnprintf(p, end - p,
8878 		       " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s",
8879 		       "[hw_info]", cv, rfe, iso, ant_num,
8880 		       ant_num > 1 ? "" :
8881 		       ant_single_pos ? "1Ant_Pos:S1, " : "1Ant_Pos:S0, ");
8882 
8883 	p += scnprintf(p, end - p,
8884 		       "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n",
8885 		       btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss,
8886 		       hal->rx_nss);
8887 
8888 	return p - buf;
8889 }
8890 
_show_wl_role_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)8891 static int _show_wl_role_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
8892 {
8893 	struct rtw89_btc *btc = &rtwdev->btc;
8894 	struct rtw89_btc_wl_link_info *plink = NULL;
8895 	struct rtw89_traffic_stats *t;
8896 	char *p = buf, *end = buf + bufsz;
8897 	u8 i, j;
8898 
8899 	for (i = 0; i < btc->ver->max_role_num; i++) {
8900 		for (j = 0; j < RTW89_MAC_NUM; j++) {
8901 			if (btc->ver->fwlrole == 8)
8902 				plink = &btc->cx.wl.rlink_info[i][j];
8903 			else
8904 				plink = &btc->cx.wl.link_info[i];
8905 
8906 			if (!plink->active)
8907 				continue;
8908 
8909 			p += scnprintf(p, end - p,
8910 				       " [port_%d]        : role=%d(phy-%d), connect=%s(client_cnt=%d), mode=%d, center_ch=%d, bw=%d",
8911 				       plink->pid, plink->role, plink->phy,
8912 				       id_to_mlme_state(plink->connected),
8913 				       plink->client_cnt - 1, plink->mode,
8914 				       plink->ch, plink->bw);
8915 
8916 			if (plink->connected == MLME_NO_LINK)
8917 				continue;
8918 
8919 			p += scnprintf(p, end - p,
8920 				       ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n",
8921 				       plink->mac_id, plink->tx_time, plink->tx_retry);
8922 
8923 			p += scnprintf(p, end - p,
8924 				       " [port_%d]        : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
8925 				       plink->pid, 110 - plink->stat.rssi,
8926 				       plink->stat.rssi, plink->busy,
8927 				       plink->dir == RTW89_TFC_UL ? "UL" : "DL");
8928 
8929 			t = &plink->stat.traffic;
8930 
8931 			p += scnprintf(p, end - p,
8932 				       "tx[rate:%d/busy_level:%d], ",
8933 				       t->tx_rate, t->tx_tfc_lv);
8934 
8935 			p += scnprintf(p, end - p,
8936 				       "rx[rate:%d/busy_level:%d/drop:%d]\n",
8937 				       t->rx_rate,
8938 				       t->rx_tfc_lv, plink->rx_rate_drop_cnt);
8939 		}
8940 	}
8941 	return p - buf;
8942 }
8943 
_show_wl_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)8944 static int _show_wl_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
8945 {
8946 	struct rtw89_btc *btc = &rtwdev->btc;
8947 	const struct rtw89_btc_ver *ver = btc->ver;
8948 	struct rtw89_btc_cx *cx = &btc->cx;
8949 	struct rtw89_btc_wl_info *wl = &cx->wl;
8950 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
8951 	struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
8952 	struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
8953 	struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
8954 	struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
8955 	char *p = buf, *end = buf + bufsz;
8956 	u8 mode;
8957 
8958 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
8959 		return 0;
8960 
8961 	p += scnprintf(p, end - p, "========== [WL Status] ==========\n");
8962 
8963 	if (ver->fwlrole == 0)
8964 		mode = wl_rinfo->link_mode;
8965 	else if (ver->fwlrole == 1)
8966 		mode = wl_rinfo_v1->link_mode;
8967 	else if (ver->fwlrole == 2)
8968 		mode = wl_rinfo_v2->link_mode;
8969 	else if (ver->fwlrole == 7)
8970 		mode = wl_rinfo_v7->link_mode;
8971 	else if (ver->fwlrole == 8)
8972 		mode = wl_rinfo_v8->link_mode;
8973 	else
8974 		goto out;
8975 
8976 	p += scnprintf(p, end - p, " %-15s : link_mode:%s, ", "[status]",
8977 		       id_to_linkmode(mode));
8978 
8979 	p += scnprintf(p, end - p,
8980 		       "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ",
8981 		       wl->status.map.rf_off, wl->status.map.lps,
8982 		       wl->status.map.scan ? "Y" : "N",
8983 		       wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
8984 
8985 	p += scnprintf(p, end - p,
8986 		       "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n",
8987 		       wl->status.map.connecting ? "Y" : "N",
8988 		       wl->status.map.roaming ?  "Y" : "N",
8989 		       wl->status.map._4way ? "Y" : "N",
8990 		       wl->status.map.init_ok ? "Y" : "N");
8991 
8992 	p += _show_wl_role_info(rtwdev, p, end - p);
8993 
8994 out:
8995 	return p - buf;
8996 }
8997 
8998 enum btc_bt_a2dp_type {
8999 	BTC_A2DP_LEGACY = 0,
9000 	BTC_A2DP_TWS_SNIFF = 1,
9001 	BTC_A2DP_TWS_RELAY = 2,
9002 };
9003 
_show_bt_profile_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9004 static int _show_bt_profile_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9005 {
9006 	struct rtw89_btc *btc = &rtwdev->btc;
9007 	struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
9008 	struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
9009 	struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
9010 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
9011 	struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
9012 	char *p = buf, *end = buf + bufsz;
9013 
9014 	if (hfp.exist) {
9015 		p += scnprintf(p, end - p,
9016 			       " %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
9017 			       "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"),
9018 			       bt_linfo->sut_pwr_level[0],
9019 			       bt_linfo->golden_rx_shift[0]);
9020 	}
9021 
9022 	if (hid.exist) {
9023 		p += scnprintf(p, end - p,
9024 			       "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n",
9025 			       "[HID]",
9026 			       hid.type & BTC_HID_218 ? "2/18," : "",
9027 			       hid.type & BTC_HID_418 ? "4/18," : "",
9028 			       hid.type & BTC_HID_BLE ? "BLE," : "",
9029 			       hid.type & BTC_HID_RCU ? "RCU," : "",
9030 			       hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "",
9031 			       hid.pair_cnt, bt_linfo->sut_pwr_level[1],
9032 			       bt_linfo->golden_rx_shift[1]);
9033 	}
9034 
9035 	if (a2dp.exist) {
9036 		p += scnprintf(p, end - p,
9037 			       " %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
9038 			       "[A2DP]",
9039 			       a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS",
9040 			       a2dp.bitpool, a2dp.flush_time);
9041 
9042 		p += scnprintf(p, end - p,
9043 			       "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n",
9044 			       a2dp.vendor_id, a2dp.device_name,
9045 			       bt_linfo->sut_pwr_level[2],
9046 			       bt_linfo->golden_rx_shift[2]);
9047 	}
9048 
9049 	if (pan.exist) {
9050 		p += scnprintf(p, end - p,
9051 			       " %-15s : sut_pwr:%d, golden-rx:%d\n",
9052 			       "[PAN]",
9053 			       bt_linfo->sut_pwr_level[3],
9054 			       bt_linfo->golden_rx_shift[3]);
9055 	}
9056 
9057 	return p - buf;
9058 }
9059 
_show_bt_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9060 static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9061 {
9062 	struct rtw89_btc *btc = &rtwdev->btc;
9063 	const struct rtw89_btc_ver *ver = btc->ver;
9064 	struct rtw89_btc_cx *cx = &btc->cx;
9065 	struct rtw89_btc_bt_info *bt = &cx->bt;
9066 	struct rtw89_btc_wl_info *wl = &cx->wl;
9067 	u32 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
9068 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
9069 	union rtw89_btc_module_info *md = &btc->mdinfo;
9070 	s8 br_dbm = bt->link_info.bt_txpwr_desc.br_dbm;
9071 	s8 le_dbm = bt->link_info.bt_txpwr_desc.le_dbm;
9072 	char *p = buf, *end = buf + bufsz;
9073 	u8 *afh = bt_linfo->afh_map;
9074 	u8 *afh_le = bt_linfo->afh_map_le;
9075 	u8 bt_pos;
9076 
9077 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
9078 		return 0;
9079 
9080 	if (ver->fcxinit == 7)
9081 		bt_pos = md->md_v7.bt_pos;
9082 	else
9083 		bt_pos = md->md.bt_pos;
9084 
9085 	p += scnprintf(p, end - p, "========== [BT Status] ==========\n");
9086 
9087 	p += scnprintf(p, end - p,
9088 		       " %-15s : enable:%s, btg:%s%s, connect:%s, ",
9089 		       "[status]", bt->enable.now ? "Y" : "N",
9090 		       bt->btg_type ? "Y" : "N",
9091 		       (bt->enable.now && (bt->btg_type != bt_pos) ?
9092 			"(efuse-mismatch!!)" : ""),
9093 		       (bt_linfo->status.map.connect ? "Y" : "N"));
9094 
9095 	p += scnprintf(p, end - p,
9096 		       "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n",
9097 		       bt->igno_wl ? "Y" : "N",
9098 		       bt->mbx_avl ? "Y" : "N", bt->rfk_info.val);
9099 
9100 	p += scnprintf(p, end - p, " %-15s : profile:%s%s%s%s%s ",
9101 		       "[profile]",
9102 		       (bt_linfo->profile_cnt.now == 0) ? "None," : "",
9103 		       bt_linfo->hfp_desc.exist ? "HFP," : "",
9104 		       bt_linfo->hid_desc.exist ? "HID," : "",
9105 		       bt_linfo->a2dp_desc.exist ?
9106 		       (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "",
9107 		       bt_linfo->pan_desc.exist ? "PAN," : "");
9108 
9109 	p += scnprintf(p, end - p,
9110 		       "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n",
9111 		       bt_linfo->multi_link.now ? "Y" : "N",
9112 		       bt_linfo->slave_role ? "Slave" : "Master",
9113 		       bt_linfo->status.map.ble_connect ? "Y" : "N",
9114 		       bt_linfo->cqddr ? "Y" : "N",
9115 		       bt_linfo->a2dp_desc.active ? "Y" : "N",
9116 		       bt_linfo->pan_desc.active ? "Y" : "N");
9117 
9118 	p += scnprintf(p, end - p,
9119 		       " %-15s : rssi:%ddBm(lvl:%d), tx_rate:%dM, %s%s%s",
9120 		       "[link]", bt_linfo->rssi - 100,
9121 		       bt->rssi_level,
9122 		       bt_linfo->tx_3m ? 3 : 2,
9123 		       bt_linfo->status.map.inq_pag ? " inq-page!!" : "",
9124 		       bt_linfo->status.map.acl_busy ? " acl_busy!!" : "",
9125 		       bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : "");
9126 
9127 	p += scnprintf(p, end - p,
9128 		       "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
9129 		       bt_linfo->relink.now ? " ReLink!!" : "",
9130 		       afh[0], afh[1], afh[2], afh[3], afh[4],
9131 		       afh[5], afh[6], afh[7], afh[8], afh[9]);
9132 
9133 	if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
9134 		p += scnprintf(p, end - p,
9135 			       "LE[%02x%02x_%02x_%02x%02x]",
9136 			       afh_le[0], afh_le[1], afh_le[2],
9137 			       afh_le[3], afh_le[4]);
9138 
9139 	p += scnprintf(p, end - p, "wl_ch_map[en:%d/ch:%d/bw:%d]\n",
9140 		       wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw);
9141 
9142 	p += scnprintf(p, end - p,
9143 		       " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
9144 		       "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY],
9145 		       cx->cnt_bt[BTC_BCNT_RELINK],
9146 		       cx->cnt_bt[BTC_BCNT_RATECHG],
9147 		       cx->cnt_bt[BTC_BCNT_REINIT],
9148 		       cx->cnt_bt[BTC_BCNT_REENABLE]);
9149 
9150 	p += scnprintf(p, end - p,
9151 		       "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n",
9152 		       cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH],
9153 		       cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ],
9154 		       cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]);
9155 
9156 	p += _show_bt_profile_info(rtwdev, p, end - p);
9157 
9158 	p += scnprintf(p, end - p,
9159 		       " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n",
9160 		       "[bt_info]", bt->raw_info[2], bt->raw_info[3],
9161 		       bt->raw_info[4], bt->raw_info[5], bt->raw_info[6],
9162 		       bt->raw_info[7],
9163 		       bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
9164 		       cx->cnt_bt[BTC_BCNT_INFOUPDATE],
9165 		       cx->cnt_bt[BTC_BCNT_INFOSAME]);
9166 
9167 	p += scnprintf(p, end - p,
9168 		       " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)",
9169 		       "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX],
9170 		       cx->cnt_bt[BTC_BCNT_HIPRI_TX],
9171 		       cx->cnt_bt[BTC_BCNT_LOPRI_RX],
9172 		       cx->cnt_bt[BTC_BCNT_LOPRI_TX],
9173 		       cx->cnt_bt[BTC_BCNT_POLUT]);
9174 
9175 	if (!bt->scan_info_update) {
9176 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, true);
9177 		p += scnprintf(p, end - p, "\n");
9178 	} else {
9179 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, false);
9180 		if (ver->fcxbtscan == 1) {
9181 			p += scnprintf(p, end - p,
9182 				       "(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)",
9183 				       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win),
9184 				       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl),
9185 				       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win),
9186 				       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl),
9187 				       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win),
9188 				       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl),
9189 				       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win),
9190 				       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl));
9191 		} else if (ver->fcxbtscan == 2) {
9192 			p += scnprintf(p, end - p,
9193 				       "(BG:%d-%d/INIT:%d-%d/LE:%d-%d)",
9194 				       le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win),
9195 				       le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl),
9196 				       le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win),
9197 				       le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl),
9198 				       le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win),
9199 				       le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl));
9200 		}
9201 		p += scnprintf(p, end - p, "\n");
9202 	}
9203 
9204 	if (ver_main >= 9 && bt_linfo->profile_cnt.now)
9205 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_TX_PWR_LVL, true);
9206 	else
9207 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_TX_PWR_LVL, false);
9208 
9209 	if (cx->cnt_bt[BTC_BCNT_BTTXPWR_UPDATE]) {
9210 		p += scnprintf(p, end - p,
9211 			       " %-15s : br_index:0x%x, le_index:0x%x",
9212 			       "[bt_txpwr_lvl]",
9213 			       bt->link_info.bt_txpwr_desc.br_gain_index,
9214 			       bt->link_info.bt_txpwr_desc.le_gain_index);
9215 		p += scnprintf(p, end - p, ", br_dbm:%d dBm", br_dbm);
9216 		p += scnprintf(p, end - p, ", le_dbm:%d dBm", le_dbm);
9217 	} else {
9218 		p += scnprintf(p, end - p,
9219 			       " %-15s : br_index:NA, le_index:NA, br_dbm:%d dBm[def], le_dbm:%d dBm[def]",
9220 			       "[bt_txpwr_lvl]",
9221 			       bt->link_info.bt_txpwr_desc.br_dbm,
9222 			       bt->link_info.bt_txpwr_desc.le_dbm);
9223 	}
9224 	p += scnprintf(p, end - p, "\n");
9225 
9226 	if (bt_linfo->profile_cnt.now || bt_linfo->status.map.ble_connect)
9227 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, true);
9228 	else
9229 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, false);
9230 
9231 	if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
9232 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, true);
9233 	else
9234 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, false);
9235 
9236 	if (bt_linfo->a2dp_desc.exist &&
9237 	    (bt_linfo->a2dp_desc.flush_time == 0 ||
9238 	     bt_linfo->a2dp_desc.vendor_id == 0 ||
9239 	     bt_linfo->a2dp_desc.play_latency == 1))
9240 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, true);
9241 	else
9242 		rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, false);
9243 
9244 	return p - buf;
9245 }
9246 
9247 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e
9248 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
9249 #define CASE_BTC_POLICY_STR(e) \
9250 	case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
9251 #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e
9252 #define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e
9253 #define CASE_BTC_INIT(e) case BTC_MODE_## e: return #e
9254 #define CASE_BTC_ANTPATH_STR(e) case BTC_ANT_##e: return #e
9255 #define CASE_BTC_POLUT_STR(e) case BTC_PLT_## e: return #e
9256 #define CASE_BTC_REGTYPE_STR(e) case REG_## e: return #e
9257 #define CASE_BTC_GDBG_STR(e) case BTC_DBG_## e: return #e
9258 
id_to_polut(u32 id)9259 static const char *id_to_polut(u32 id)
9260 {
9261 	switch (id) {
9262 	CASE_BTC_POLUT_STR(NONE);
9263 	CASE_BTC_POLUT_STR(GNT_BT_TX);
9264 	CASE_BTC_POLUT_STR(GNT_BT_RX);
9265 	CASE_BTC_POLUT_STR(GNT_WL);
9266 	CASE_BTC_POLUT_STR(BT);
9267 	CASE_BTC_POLUT_STR(ALL);
9268 	default:
9269 		return "unknown";
9270 	}
9271 }
9272 
id_to_regtype(u32 id)9273 static const char *id_to_regtype(u32 id)
9274 {
9275 	switch (id) {
9276 	CASE_BTC_REGTYPE_STR(MAC);
9277 	CASE_BTC_REGTYPE_STR(BB);
9278 	CASE_BTC_REGTYPE_STR(RF);
9279 	CASE_BTC_REGTYPE_STR(BT_RF);
9280 	CASE_BTC_REGTYPE_STR(BT_MODEM);
9281 	CASE_BTC_REGTYPE_STR(BT_BLUEWIZE);
9282 	CASE_BTC_REGTYPE_STR(BT_VENDOR);
9283 	CASE_BTC_REGTYPE_STR(BT_LE);
9284 	default:
9285 		return "unknown";
9286 	}
9287 }
9288 
id_to_gdbg(u32 id)9289 static const char *id_to_gdbg(u32 id)
9290 {
9291 	switch (id) {
9292 	CASE_BTC_GDBG_STR(GNT_BT);
9293 	CASE_BTC_GDBG_STR(GNT_WL);
9294 	CASE_BTC_GDBG_STR(BCN_EARLY);
9295 	CASE_BTC_GDBG_STR(WL_NULL0);
9296 	CASE_BTC_GDBG_STR(WL_NULL1);
9297 	CASE_BTC_GDBG_STR(WL_RXISR);
9298 	CASE_BTC_GDBG_STR(TDMA_ENTRY);
9299 	CASE_BTC_GDBG_STR(A2DP_EMPTY);
9300 	CASE_BTC_GDBG_STR(BT_RETRY);
9301 	CASE_BTC_GDBG_STR(BT_RELINK);
9302 	CASE_BTC_GDBG_STR(SLOT_WL);
9303 	CASE_BTC_GDBG_STR(SLOT_BT);
9304 	CASE_BTC_GDBG_STR(WL_ERR);
9305 	CASE_BTC_GDBG_STR(WL_OK);
9306 	CASE_BTC_GDBG_STR(SLOT_B2W);
9307 	CASE_BTC_GDBG_STR(SLOT_W1);
9308 	CASE_BTC_GDBG_STR(SLOT_W2);
9309 	CASE_BTC_GDBG_STR(SLOT_W2B);
9310 	CASE_BTC_GDBG_STR(SLOT_B1);
9311 	CASE_BTC_GDBG_STR(SLOT_B2);
9312 	CASE_BTC_GDBG_STR(SLOT_B3);
9313 	CASE_BTC_GDBG_STR(SLOT_B4);
9314 	CASE_BTC_GDBG_STR(SLOT_LK);
9315 	CASE_BTC_GDBG_STR(SLOT_E2G);
9316 	CASE_BTC_GDBG_STR(SLOT_E5G);
9317 	CASE_BTC_GDBG_STR(SLOT_EBT);
9318 	CASE_BTC_GDBG_STR(SLOT_WLK);
9319 	CASE_BTC_GDBG_STR(SLOT_B1FDD);
9320 	CASE_BTC_GDBG_STR(BT_CHANGE);
9321 	CASE_BTC_GDBG_STR(WL_CCA);
9322 	CASE_BTC_GDBG_STR(BT_LEAUDIO);
9323 	CASE_BTC_GDBG_STR(USER_DEF);
9324 	default:
9325 		return "unknown";
9326 	}
9327 }
9328 
steps_to_str(u16 step)9329 static const char *steps_to_str(u16 step)
9330 {
9331 	switch (step) {
9332 	CASE_BTC_RSN_STR(NONE);
9333 	CASE_BTC_RSN_STR(NTFY_INIT);
9334 	CASE_BTC_RSN_STR(NTFY_SWBAND);
9335 	CASE_BTC_RSN_STR(NTFY_WL_STA);
9336 	CASE_BTC_RSN_STR(NTFY_RADIO_STATE);
9337 	CASE_BTC_RSN_STR(UPDATE_BT_SCBD);
9338 	CASE_BTC_RSN_STR(NTFY_WL_RFK);
9339 	CASE_BTC_RSN_STR(UPDATE_BT_INFO);
9340 	CASE_BTC_RSN_STR(NTFY_SCAN_START);
9341 	CASE_BTC_RSN_STR(NTFY_SCAN_FINISH);
9342 	CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET);
9343 	CASE_BTC_RSN_STR(NTFY_POWEROFF);
9344 	CASE_BTC_RSN_STR(NTFY_ROLE_INFO);
9345 	CASE_BTC_RSN_STR(CMD_SET_COEX);
9346 	CASE_BTC_RSN_STR(ACT1_WORK);
9347 	CASE_BTC_RSN_STR(BT_DEVINFO_WORK);
9348 	CASE_BTC_RSN_STR(RFK_CHK_WORK);
9349 
9350 	CASE_BTC_ACT_STR(NONE);
9351 	CASE_BTC_ACT_STR(WL_ONLY);
9352 	CASE_BTC_ACT_STR(WL_5G);
9353 	CASE_BTC_ACT_STR(WL_OTHER);
9354 	CASE_BTC_ACT_STR(WL_IDLE);
9355 	CASE_BTC_ACT_STR(WL_NC);
9356 	CASE_BTC_ACT_STR(WL_RFK);
9357 	CASE_BTC_ACT_STR(WL_INIT);
9358 	CASE_BTC_ACT_STR(WL_OFF);
9359 	CASE_BTC_ACT_STR(FREERUN);
9360 	CASE_BTC_ACT_STR(BT_WHQL);
9361 	CASE_BTC_ACT_STR(BT_RFK);
9362 	CASE_BTC_ACT_STR(BT_OFF);
9363 	CASE_BTC_ACT_STR(BT_IDLE);
9364 	CASE_BTC_ACT_STR(BT_HFP);
9365 	CASE_BTC_ACT_STR(BT_HID);
9366 	CASE_BTC_ACT_STR(BT_A2DP);
9367 	CASE_BTC_ACT_STR(BT_A2DPSINK);
9368 	CASE_BTC_ACT_STR(BT_PAN);
9369 	CASE_BTC_ACT_STR(BT_A2DP_HID);
9370 	CASE_BTC_ACT_STR(BT_A2DP_PAN);
9371 	CASE_BTC_ACT_STR(BT_PAN_HID);
9372 	CASE_BTC_ACT_STR(BT_A2DP_PAN_HID);
9373 	CASE_BTC_ACT_STR(WL_25G_MCC);
9374 	CASE_BTC_ACT_STR(WL_2G_MCC);
9375 	CASE_BTC_ACT_STR(WL_2G_SCC);
9376 	CASE_BTC_ACT_STR(WL_2G_AP);
9377 	CASE_BTC_ACT_STR(WL_2G_GO);
9378 	CASE_BTC_ACT_STR(WL_2G_GC);
9379 	CASE_BTC_ACT_STR(WL_2G_NAN);
9380 
9381 	CASE_BTC_POLICY_STR(OFF_BT);
9382 	CASE_BTC_POLICY_STR(OFF_WL);
9383 	CASE_BTC_POLICY_STR(OFF_EQ0);
9384 	CASE_BTC_POLICY_STR(OFF_EQ1);
9385 	CASE_BTC_POLICY_STR(OFF_EQ2);
9386 	CASE_BTC_POLICY_STR(OFF_EQ3);
9387 	CASE_BTC_POLICY_STR(OFF_EQ4);
9388 	CASE_BTC_POLICY_STR(OFF_EQ5);
9389 	CASE_BTC_POLICY_STR(OFF_BWB0);
9390 	CASE_BTC_POLICY_STR(OFF_BWB1);
9391 	CASE_BTC_POLICY_STR(OFF_BWB2);
9392 	CASE_BTC_POLICY_STR(OFF_BWB3);
9393 	CASE_BTC_POLICY_STR(OFF_WL2);
9394 	CASE_BTC_POLICY_STR(OFFB_BWB0);
9395 	CASE_BTC_POLICY_STR(OFFE_DEF);
9396 	CASE_BTC_POLICY_STR(OFFE_DEF2);
9397 	CASE_BTC_POLICY_STR(OFFE_2GBWISOB);
9398 	CASE_BTC_POLICY_STR(OFFE_2GISOB);
9399 	CASE_BTC_POLICY_STR(OFFE_2GBWMIXB);
9400 	CASE_BTC_POLICY_STR(OFFE_WL);
9401 	CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2);
9402 	CASE_BTC_POLICY_STR(FIX_TD3030);
9403 	CASE_BTC_POLICY_STR(FIX_TD5050);
9404 	CASE_BTC_POLICY_STR(FIX_TD2030);
9405 	CASE_BTC_POLICY_STR(FIX_TD4010);
9406 	CASE_BTC_POLICY_STR(FIX_TD7010);
9407 	CASE_BTC_POLICY_STR(FIX_TD2060);
9408 	CASE_BTC_POLICY_STR(FIX_TD3060);
9409 	CASE_BTC_POLICY_STR(FIX_TD2080);
9410 	CASE_BTC_POLICY_STR(FIX_TDW1B1);
9411 	CASE_BTC_POLICY_STR(FIX_TD4010ISO);
9412 	CASE_BTC_POLICY_STR(FIX_TD4010ISO_DL);
9413 	CASE_BTC_POLICY_STR(FIX_TD4010ISO_UL);
9414 	CASE_BTC_POLICY_STR(PFIX_TD3030);
9415 	CASE_BTC_POLICY_STR(PFIX_TD5050);
9416 	CASE_BTC_POLICY_STR(PFIX_TD2030);
9417 	CASE_BTC_POLICY_STR(PFIX_TD2060);
9418 	CASE_BTC_POLICY_STR(PFIX_TD3070);
9419 	CASE_BTC_POLICY_STR(PFIX_TD2080);
9420 	CASE_BTC_POLICY_STR(PFIX_TDW1B1);
9421 	CASE_BTC_POLICY_STR(AUTO_TD50B1);
9422 	CASE_BTC_POLICY_STR(AUTO_TD60B1);
9423 	CASE_BTC_POLICY_STR(AUTO_TD20B1);
9424 	CASE_BTC_POLICY_STR(AUTO_TDW1B1);
9425 	CASE_BTC_POLICY_STR(PAUTO_TD50B1);
9426 	CASE_BTC_POLICY_STR(PAUTO_TD60B1);
9427 	CASE_BTC_POLICY_STR(PAUTO_TD20B1);
9428 	CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
9429 	CASE_BTC_POLICY_STR(AUTO2_TD3050);
9430 	CASE_BTC_POLICY_STR(AUTO2_TD3070);
9431 	CASE_BTC_POLICY_STR(AUTO2_TD5050);
9432 	CASE_BTC_POLICY_STR(AUTO2_TD6060);
9433 	CASE_BTC_POLICY_STR(AUTO2_TD2080);
9434 	CASE_BTC_POLICY_STR(AUTO2_TDW1B4);
9435 	CASE_BTC_POLICY_STR(PAUTO2_TD3050);
9436 	CASE_BTC_POLICY_STR(PAUTO2_TD3070);
9437 	CASE_BTC_POLICY_STR(PAUTO2_TD5050);
9438 	CASE_BTC_POLICY_STR(PAUTO2_TD6060);
9439 	CASE_BTC_POLICY_STR(PAUTO2_TD2080);
9440 	CASE_BTC_POLICY_STR(PAUTO2_TDW1B4);
9441 	default:
9442 		return "unknown step";
9443 	}
9444 }
9445 
id_to_slot(u32 id)9446 static const char *id_to_slot(u32 id)
9447 {
9448 	switch (id) {
9449 	CASE_BTC_SLOT_STR(OFF);
9450 	CASE_BTC_SLOT_STR(B2W);
9451 	CASE_BTC_SLOT_STR(W1);
9452 	CASE_BTC_SLOT_STR(W2);
9453 	CASE_BTC_SLOT_STR(W2B);
9454 	CASE_BTC_SLOT_STR(B1);
9455 	CASE_BTC_SLOT_STR(B2);
9456 	CASE_BTC_SLOT_STR(B3);
9457 	CASE_BTC_SLOT_STR(B4);
9458 	CASE_BTC_SLOT_STR(LK);
9459 	CASE_BTC_SLOT_STR(BLK);
9460 	CASE_BTC_SLOT_STR(E2G);
9461 	CASE_BTC_SLOT_STR(E5G);
9462 	CASE_BTC_SLOT_STR(EBT);
9463 	CASE_BTC_SLOT_STR(ENULL);
9464 	CASE_BTC_SLOT_STR(WLK);
9465 	CASE_BTC_SLOT_STR(W1FDD);
9466 	CASE_BTC_SLOT_STR(B1FDD);
9467 	default:
9468 		return "unknown";
9469 	}
9470 }
9471 
id_to_evt(u32 id)9472 static const char *id_to_evt(u32 id)
9473 {
9474 	switch (id) {
9475 	CASE_BTC_EVT_STR(TDMA_ENTRY);
9476 	CASE_BTC_EVT_STR(WL_TMR);
9477 	CASE_BTC_EVT_STR(B1_TMR);
9478 	CASE_BTC_EVT_STR(B2_TMR);
9479 	CASE_BTC_EVT_STR(B3_TMR);
9480 	CASE_BTC_EVT_STR(B4_TMR);
9481 	CASE_BTC_EVT_STR(W2B_TMR);
9482 	CASE_BTC_EVT_STR(B2W_TMR);
9483 	CASE_BTC_EVT_STR(BCN_EARLY);
9484 	CASE_BTC_EVT_STR(A2DP_EMPTY);
9485 	CASE_BTC_EVT_STR(LK_END);
9486 	CASE_BTC_EVT_STR(RX_ISR);
9487 	CASE_BTC_EVT_STR(RX_FC0);
9488 	CASE_BTC_EVT_STR(RX_FC1);
9489 	CASE_BTC_EVT_STR(BT_RELINK);
9490 	CASE_BTC_EVT_STR(BT_RETRY);
9491 	CASE_BTC_EVT_STR(E2G);
9492 	CASE_BTC_EVT_STR(E5G);
9493 	CASE_BTC_EVT_STR(EBT);
9494 	CASE_BTC_EVT_STR(ENULL);
9495 	CASE_BTC_EVT_STR(DRV_WLK);
9496 	CASE_BTC_EVT_STR(BCN_OK);
9497 	CASE_BTC_EVT_STR(BT_CHANGE);
9498 	CASE_BTC_EVT_STR(EBT_EXTEND);
9499 	CASE_BTC_EVT_STR(E2G_NULL1);
9500 	CASE_BTC_EVT_STR(B1FDD_TMR);
9501 	default:
9502 		return "unknown";
9503 	}
9504 }
9505 
id_to_mode(u8 id)9506 static const char *id_to_mode(u8 id)
9507 {
9508 	switch (id) {
9509 	CASE_BTC_INIT(NORMAL);
9510 	CASE_BTC_INIT(WL);
9511 	CASE_BTC_INIT(BT);
9512 	CASE_BTC_INIT(WLOFF);
9513 	default:
9514 		return "unknown";
9515 	}
9516 }
9517 
id_to_ant(u32 id)9518 static const char *id_to_ant(u32 id)
9519 {
9520 	switch (id) {
9521 	CASE_BTC_ANTPATH_STR(WPOWERON);
9522 	CASE_BTC_ANTPATH_STR(WINIT);
9523 	CASE_BTC_ANTPATH_STR(WONLY);
9524 	CASE_BTC_ANTPATH_STR(WOFF);
9525 	CASE_BTC_ANTPATH_STR(W2G);
9526 	CASE_BTC_ANTPATH_STR(W5G);
9527 	CASE_BTC_ANTPATH_STR(W25G);
9528 	CASE_BTC_ANTPATH_STR(FREERUN);
9529 	CASE_BTC_ANTPATH_STR(WRFK);
9530 	CASE_BTC_ANTPATH_STR(BRFK);
9531 	CASE_BTC_ANTPATH_STR(MAX);
9532 	default:
9533 		return "unknown";
9534 	}
9535 }
9536 
9537 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)9538 int scnprintf_segment(char *buf, size_t bufsz, const char *prefix, const u16 *data,
9539 		      u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
9540 {
9541 	char *p = buf, *end = buf + bufsz;
9542 	u8 cur_index;
9543 	u8 i;
9544 
9545 	for (i = 0; i < len ; i++) {
9546 		if ((i % seg_len) == 0)
9547 			p += scnprintf(p, end - p, " %-15s : ", prefix);
9548 		cur_index = (start_idx + i) % ring_len;
9549 		if (i % 3 == 0)
9550 			p += scnprintf(p, end - p, "-> %-20s",
9551 				       steps_to_str(*(data + cur_index)));
9552 		else if (i % 3 == 1)
9553 			p += scnprintf(p, end - p, "-> %-15s",
9554 				       steps_to_str(*(data + cur_index)));
9555 		else
9556 			p += scnprintf(p, end - p, "-> %-13s",
9557 				       steps_to_str(*(data + cur_index)));
9558 		if (i == (len - 1) || (i % seg_len) == (seg_len - 1))
9559 			p += scnprintf(p, end - p, "\n");
9560 	}
9561 
9562 	return p - buf;
9563 }
9564 
_show_dm_step(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9565 static int _show_dm_step(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9566 {
9567 	struct rtw89_btc *btc = &rtwdev->btc;
9568 	struct rtw89_btc_dm *dm = &btc->dm;
9569 	char *p = buf, *end = buf + bufsz;
9570 	u8 start_idx;
9571 	u8 len;
9572 
9573 	len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos;
9574 	start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0;
9575 
9576 	p += scnprintf_segment(p, end - p, "[dm_steps]", dm->dm_step.step, len,
9577 			       6, start_idx, ARRAY_SIZE(dm->dm_step.step));
9578 
9579 	return p - buf;
9580 }
9581 
_show_dm_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9582 static int _show_dm_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9583 {
9584 	struct rtw89_btc *btc = &rtwdev->btc;
9585 	const struct rtw89_btc_ver *ver = btc->ver;
9586 	struct rtw89_btc_dm *dm = &btc->dm;
9587 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9588 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
9589 	char *p = buf, *end = buf + bufsz;
9590 	u8 igno_bt;
9591 
9592 	if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
9593 		return 0;
9594 
9595 	p += scnprintf(p, end - p,
9596 		       "========== [Mechanism Status %s] ==========\n",
9597 		       (btc->manual_ctrl ? "(Manual)" : "(Auto)"));
9598 
9599 	p += scnprintf(p, end - p,
9600 		       " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, init_mode:%s, run_cnt:%d\n",
9601 		       "[status]",
9602 		       btc->ant_type == BTC_ANT_SHARED ? "shared" : "dedicated",
9603 		       steps_to_str(dm->run_reason),
9604 		       steps_to_str(dm->run_action | BTC_ACT_EXT_BIT),
9605 		       id_to_ant(FIELD_GET(GENMASK(7, 0), dm->set_ant_path)),
9606 		       id_to_mode(wl->coex_mode),
9607 		       dm->cnt_dm[BTC_DCNT_RUN]);
9608 
9609 	p += _show_dm_step(rtwdev, p, end - p);
9610 
9611 	if (ver->fcxctrl == 7)
9612 		igno_bt = btc->ctrl.ctrl_v7.igno_bt;
9613 	else
9614 		igno_bt = btc->ctrl.ctrl.igno_bt;
9615 
9616 	p += scnprintf(p, end - p,
9617 		       " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ",
9618 		       "[dm_flag]", dm->wl_only, dm->bt_only, igno_bt,
9619 		       dm->freerun, btc->lps, dm->wl_mimo_ps);
9620 
9621 	p += scnprintf(p, end - p, "leak_ap:%d, fw_offload:%s%s\n",
9622 		       dm->leak_ap,
9623 		       (BTC_CX_FW_OFFLOAD ? "Y" : "N"),
9624 		       (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
9625 			"" : "(Mismatch!!)"));
9626 
9627 	if (dm->rf_trx_para.wl_tx_power == 0xff)
9628 		p += scnprintf(p, end - p,
9629 			       " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ",
9630 			       "[trx_ctrl]", wl->rssi_level,
9631 			       dm->trx_para_level);
9632 
9633 	else
9634 		p += scnprintf(p, end - p,
9635 			       " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ",
9636 			       "[trx_ctrl]", wl->rssi_level,
9637 			       dm->trx_para_level,
9638 			       dm->rf_trx_para.wl_tx_power);
9639 
9640 	p += scnprintf(p, end - p,
9641 		       "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n",
9642 		       dm->rf_trx_para.wl_rx_gain,
9643 		       dm->rf_trx_para.bt_tx_power,
9644 		       dm->rf_trx_para.bt_rx_gain,
9645 		       (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx);
9646 
9647 	p += scnprintf(p, end - p,
9648 		       " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n",
9649 		       "[dm_ctrl]", dm->wl_tx_limit.enable,
9650 		       dm->wl_tx_limit.tx_time,
9651 		       dm->wl_tx_limit.tx_retry, btc->bt_req_len,
9652 		       bt->scan_rx_low_pri);
9653 
9654 	return p - buf;
9655 }
9656 
_show_error(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9657 static int _show_error(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9658 {
9659 	struct rtw89_btc *btc = &rtwdev->btc;
9660 	const struct rtw89_btc_ver *ver = btc->ver;
9661 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9662 	union rtw89_btc_fbtc_cysta_info *pcysta;
9663 	char *p = buf, *end = buf + bufsz;
9664 	u32 except_cnt, exception_map;
9665 
9666 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
9667 	if (ver->fcxcysta == 2) {
9668 		pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
9669 		except_cnt = le32_to_cpu(pcysta->v2.except_cnt);
9670 		exception_map = le32_to_cpu(pcysta->v2.exception);
9671 	} else if (ver->fcxcysta == 3) {
9672 		pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
9673 		except_cnt = le32_to_cpu(pcysta->v3.except_cnt);
9674 		exception_map = le32_to_cpu(pcysta->v3.except_map);
9675 	} else if (ver->fcxcysta == 4) {
9676 		pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
9677 		except_cnt = pcysta->v4.except_cnt;
9678 		exception_map = le32_to_cpu(pcysta->v4.except_map);
9679 	} else if (ver->fcxcysta == 5) {
9680 		pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
9681 		except_cnt = pcysta->v5.except_cnt;
9682 		exception_map = le32_to_cpu(pcysta->v5.except_map);
9683 	} else if (ver->fcxcysta == 7) {
9684 		pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
9685 		except_cnt = pcysta->v7.except_cnt;
9686 		exception_map = le32_to_cpu(pcysta->v7.except_map);
9687 	} else {
9688 		return 0;
9689 	}
9690 
9691 	if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 &&
9692 	    !pfwinfo->len_mismch && !pfwinfo->fver_mismch)
9693 		return 0;
9694 
9695 	p += scnprintf(p, end - p, " %-15s : ", "[error]");
9696 
9697 	if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
9698 		p += scnprintf(p, end - p,
9699 			       "overflow-cnt: %d, ",
9700 			       pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
9701 	}
9702 
9703 	if (pfwinfo->len_mismch) {
9704 		p += scnprintf(p, end - p,
9705 			       "len-mismatch: 0x%x, ",
9706 			       pfwinfo->len_mismch);
9707 	}
9708 
9709 	if (pfwinfo->fver_mismch) {
9710 		p += scnprintf(p, end - p,
9711 			       "fver-mismatch: 0x%x, ",
9712 			       pfwinfo->fver_mismch);
9713 	}
9714 
9715 	/* cycle statistics exceptions */
9716 	if (exception_map || except_cnt) {
9717 		p += scnprintf(p, end - p,
9718 			       "exception-type: 0x%x, exception-cnt = %d",
9719 			       exception_map, except_cnt);
9720 	}
9721 	p += scnprintf(p, end - p, "\n");
9722 
9723 	return p - buf;
9724 }
9725 
_show_fbtc_tdma(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9726 static int _show_fbtc_tdma(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9727 {
9728 	struct rtw89_btc *btc = &rtwdev->btc;
9729 	const struct rtw89_btc_ver *ver = btc->ver;
9730 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9731 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9732 	struct rtw89_btc_fbtc_tdma *t = NULL;
9733 	char *p = buf, *end = buf + bufsz;
9734 
9735 	pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
9736 	if (!pcinfo->valid)
9737 		return 0;
9738 
9739 	if (ver->fcxtdma == 1)
9740 		t = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
9741 	else
9742 		t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma;
9743 
9744 	p += scnprintf(p, end - p,
9745 		       " %-15s : ", "[tdma_policy]");
9746 	p += scnprintf(p, end - p,
9747 		       "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ",
9748 		       (u32)t->type,
9749 		       t->rxflctrl, t->txpause);
9750 
9751 	p += scnprintf(p, end - p,
9752 		       "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ",
9753 		       t->wtgle_n, t->leak_n, t->ext_ctrl);
9754 
9755 	p += scnprintf(p, end - p,
9756 		       "policy_type:%d",
9757 		       (u32)btc->policy_type);
9758 
9759 	p += scnprintf(p, end - p, "\n");
9760 
9761 	return p - buf;
9762 }
9763 
_show_fbtc_slots(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9764 static int _show_fbtc_slots(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9765 {
9766 	struct rtw89_btc *btc = &rtwdev->btc;
9767 	struct rtw89_btc_dm *dm = &btc->dm;
9768 	char *p = buf, *end = buf + bufsz;
9769 	u16 dur, cxtype;
9770 	u32 tbl;
9771 	u8 i = 0;
9772 
9773 	for (i = 0; i < CXST_MAX; i++) {
9774 		if (btc->ver->fcxslots == 1) {
9775 			dur = le16_to_cpu(dm->slot_now.v1[i].dur);
9776 			tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl);
9777 			cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype);
9778 		} else if (btc->ver->fcxslots == 7) {
9779 			dur = le16_to_cpu(dm->slot_now.v7[i].dur);
9780 			tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl);
9781 			cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype);
9782 		} else {
9783 			return 0;
9784 		}
9785 
9786 		if (i % 5 == 0)
9787 			p += scnprintf(p, end - p,
9788 				       " %-15s : %5s[%03d/0x%x/%d]",
9789 				       "[slot_list]",
9790 				       id_to_slot((u32)i),
9791 				       dur, tbl, cxtype);
9792 		else
9793 			p += scnprintf(p, end - p,
9794 				       ", %5s[%03d/0x%x/%d]",
9795 				       id_to_slot((u32)i),
9796 				       dur, tbl, cxtype);
9797 
9798 		if (i % 5 == 4)
9799 			p += scnprintf(p, end - p, "\n");
9800 	}
9801 
9802 	return p - buf;
9803 }
9804 
_show_fbtc_cysta_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9805 static int _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9806 {
9807 	struct rtw89_btc *btc = &rtwdev->btc;
9808 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9809 	struct rtw89_btc_dm *dm = &btc->dm;
9810 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
9811 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9812 	struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL;
9813 	union rtw89_btc_fbtc_rxflct r;
9814 	u16 cycle, c_begin, c_end, store_index;
9815 	char *p = buf, *end = buf + bufsz;
9816 	u8 i, cnt = 0, slot_pair;
9817 
9818 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9819 	if (!pcinfo->valid)
9820 		return 0;
9821 
9822 	pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
9823 	p += scnprintf(p, end - p,
9824 		       " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
9825 		       "[cycle_cnt]",
9826 		       le16_to_cpu(pcysta_le32->cycles),
9827 		       le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]),
9828 		       le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]),
9829 		       le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]),
9830 		       le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK]));
9831 
9832 	for (i = 0; i < CXST_MAX; i++) {
9833 		if (!le32_to_cpu(pcysta_le32->slot_cnt[i]))
9834 			continue;
9835 		p += scnprintf(p, end - p, ", %s:%d", id_to_slot((u32)i),
9836 			       le32_to_cpu(pcysta_le32->slot_cnt[i]));
9837 	}
9838 
9839 	if (dm->tdma_now.rxflctrl) {
9840 		p += scnprintf(p, end - p, ", leak_rx:%d",
9841 			       le32_to_cpu(pcysta_le32->leakrx_cnt));
9842 	}
9843 
9844 	if (le32_to_cpu(pcysta_le32->collision_cnt)) {
9845 		p += scnprintf(p, end - p, ", collision:%d",
9846 			       le32_to_cpu(pcysta_le32->collision_cnt));
9847 	}
9848 
9849 	if (le32_to_cpu(pcysta_le32->skip_cnt)) {
9850 		p += scnprintf(p, end - p, ", skip:%d",
9851 			       le32_to_cpu(pcysta_le32->skip_cnt));
9852 	}
9853 	p += scnprintf(p, end - p, "\n");
9854 
9855 	p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9856 		       "[cycle_time]",
9857 		       le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]),
9858 		       le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]),
9859 		       le16_to_cpu(pcysta_le32->tavg_lk) / 1000,
9860 		       le16_to_cpu(pcysta_le32->tavg_lk) % 1000);
9861 	p += scnprintf(p, end - p, ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
9862 		       le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]),
9863 		       le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]),
9864 		       le16_to_cpu(pcysta_le32->tmax_lk) / 1000,
9865 		       le16_to_cpu(pcysta_le32->tmax_lk) % 1000);
9866 	p += scnprintf(p, end - p, ", maxdiff_t[wl:%d/bt:%d]\n",
9867 		       le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]),
9868 		       le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT]));
9869 
9870 	if (le16_to_cpu(pcysta_le32->cycles) <= 1)
9871 		goto out;
9872 
9873 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
9874 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
9875 
9876 	if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair)
9877 		c_begin = 1;
9878 	else
9879 		c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1;
9880 
9881 	c_end = le16_to_cpu(pcysta_le32->cycles);
9882 
9883 	for (cycle = c_begin; cycle <= c_end; cycle++) {
9884 		cnt++;
9885 		store_index = ((cycle - 1) % slot_pair) * 2;
9886 
9887 		if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1)
9888 			p += scnprintf(p, end - p,
9889 				       " %-15s : ->b%02d->w%02d",
9890 				       "[cycle_step]",
9891 				       le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
9892 				       le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
9893 		else
9894 			p += scnprintf(p, end - p,
9895 				       "->b%02d->w%02d",
9896 				       le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
9897 				       le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
9898 		if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
9899 			p += scnprintf(p, end - p, "\n");
9900 	}
9901 
9902 	if (a2dp->exist) {
9903 		p += scnprintf(p, end - p,
9904 			       " %-15s : a2dp_ept:%d, a2dp_late:%d",
9905 			       "[a2dp_t_sta]",
9906 			       le16_to_cpu(pcysta_le32->a2dpept),
9907 			       le16_to_cpu(pcysta_le32->a2dpeptto));
9908 
9909 		p += scnprintf(p, end - p,
9910 			       ", avg_t:%d, max_t:%d",
9911 			       le16_to_cpu(pcysta_le32->tavg_a2dpept),
9912 			       le16_to_cpu(pcysta_le32->tmax_a2dpept));
9913 		r.val = dm->tdma_now.rxflctrl;
9914 
9915 		if (r.type && r.tgln_n) {
9916 			p += scnprintf(p, end - p,
9917 				       ", cycle[PSTDMA:%d/TDMA:%d], ",
9918 				       le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]),
9919 				       le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF]));
9920 
9921 			p += scnprintf(p, end - p,
9922 				       "avg_t[PSTDMA:%d/TDMA:%d], ",
9923 				       le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]),
9924 				       le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF]));
9925 
9926 			p += scnprintf(p, end - p,
9927 				       "max_t[PSTDMA:%d/TDMA:%d]",
9928 				       le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]),
9929 				       le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF]));
9930 		}
9931 		p += scnprintf(p, end - p, "\n");
9932 	}
9933 
9934 out:
9935 	return p - buf;
9936 }
9937 
_show_fbtc_cysta_v3(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9938 static int _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9939 {
9940 	struct rtw89_btc *btc = &rtwdev->btc;
9941 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
9942 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9943 	struct rtw89_btc_dm *dm = &btc->dm;
9944 	struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx;
9945 	struct rtw89_btc_fbtc_cysta_v3 *pcysta;
9946 	struct rtw89_btc_rpt_cmn_info *pcinfo;
9947 	u8 i, cnt = 0, slot_pair, divide_cnt;
9948 	u16 cycle, c_begin, c_end, store_index;
9949 	char *p = buf, *end = buf + bufsz;
9950 
9951 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9952 	if (!pcinfo->valid)
9953 		return 0;
9954 
9955 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
9956 	p += scnprintf(p, end - p,
9957 		       " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
9958 		       "[cycle_cnt]",
9959 		       le16_to_cpu(pcysta->cycles),
9960 		       le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
9961 		       le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
9962 		       le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
9963 		       le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
9964 
9965 	for (i = 0; i < CXST_MAX; i++) {
9966 		if (!le32_to_cpu(pcysta->slot_cnt[i]))
9967 			continue;
9968 
9969 		p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
9970 			       le32_to_cpu(pcysta->slot_cnt[i]));
9971 	}
9972 
9973 	if (dm->tdma_now.rxflctrl)
9974 		p += scnprintf(p, end - p, ", leak_rx:%d",
9975 			       le32_to_cpu(pcysta->leak_slot.cnt_rximr));
9976 
9977 	if (le32_to_cpu(pcysta->collision_cnt))
9978 		p += scnprintf(p, end - p, ", collision:%d",
9979 			       le32_to_cpu(pcysta->collision_cnt));
9980 
9981 	if (le32_to_cpu(pcysta->skip_cnt))
9982 		p += scnprintf(p, end - p, ", skip:%d",
9983 			       le32_to_cpu(pcysta->skip_cnt));
9984 
9985 	p += scnprintf(p, end - p, "\n");
9986 
9987 	p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9988 		       "[cycle_time]",
9989 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
9990 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
9991 		       le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
9992 		       le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
9993 	p += scnprintf(p, end - p,
9994 		       ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
9995 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
9996 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
9997 		       le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
9998 		       le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
9999 	p += scnprintf(p, end - p,
10000 		       ", maxdiff_t[wl:%d/bt:%d]\n",
10001 		       le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
10002 		       le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
10003 
10004 	cycle = le16_to_cpu(pcysta->cycles);
10005 	if (cycle <= 1)
10006 		goto out;
10007 
10008 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
10009 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10010 
10011 	if (cycle <= slot_pair)
10012 		c_begin = 1;
10013 	else
10014 		c_begin = cycle - slot_pair + 1;
10015 
10016 	c_end = cycle;
10017 
10018 	if (a2dp->exist)
10019 		divide_cnt = 3;
10020 	else
10021 		divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
10022 
10023 	for (cycle = c_begin; cycle <= c_end; cycle++) {
10024 		cnt++;
10025 		store_index = ((cycle - 1) % slot_pair) * 2;
10026 
10027 		if (cnt % divide_cnt == 1)
10028 			p += scnprintf(p, end - p, " %-15s : ",
10029 				       "[cycle_step]");
10030 
10031 		p += scnprintf(p, end - p, "->b%02d",
10032 			       le16_to_cpu(pcysta->slot_step_time[store_index]));
10033 		if (a2dp->exist) {
10034 			a2dp_trx = &pcysta->a2dp_trx[store_index];
10035 			p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10036 				       a2dp_trx->empty_cnt,
10037 				       a2dp_trx->retry_cnt,
10038 				       a2dp_trx->tx_rate ? 3 : 2,
10039 				       a2dp_trx->tx_cnt,
10040 				       a2dp_trx->ack_cnt,
10041 				       a2dp_trx->nack_cnt);
10042 		}
10043 		p += scnprintf(p, end - p, "->w%02d",
10044 			       le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
10045 		if (a2dp->exist) {
10046 			a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
10047 			p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10048 				       a2dp_trx->empty_cnt,
10049 				       a2dp_trx->retry_cnt,
10050 				       a2dp_trx->tx_rate ? 3 : 2,
10051 				       a2dp_trx->tx_cnt,
10052 				       a2dp_trx->ack_cnt,
10053 				       a2dp_trx->nack_cnt);
10054 		}
10055 		if (cnt % divide_cnt == 0 || cnt == c_end)
10056 			p += scnprintf(p, end - p, "\n");
10057 	}
10058 
10059 	if (a2dp->exist) {
10060 		p += scnprintf(p, end - p,
10061 			       " %-15s : a2dp_ept:%d, a2dp_late:%d",
10062 			       "[a2dp_t_sta]",
10063 			       le16_to_cpu(pcysta->a2dp_ept.cnt),
10064 			       le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
10065 
10066 		p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10067 			       le16_to_cpu(pcysta->a2dp_ept.tavg),
10068 			       le16_to_cpu(pcysta->a2dp_ept.tmax));
10069 
10070 		p += scnprintf(p, end - p, "\n");
10071 	}
10072 
10073 out:
10074 	return p - buf;
10075 }
10076 
_show_fbtc_cysta_v4(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10077 static int _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10078 {
10079 	struct rtw89_btc *btc = &rtwdev->btc;
10080 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
10081 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10082 	struct rtw89_btc_dm *dm = &btc->dm;
10083 	struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
10084 	struct rtw89_btc_fbtc_cysta_v4 *pcysta;
10085 	struct rtw89_btc_rpt_cmn_info *pcinfo;
10086 	u8 i, cnt = 0, slot_pair, divide_cnt;
10087 	u16 cycle, c_begin, c_end, store_index;
10088 	char *p = buf, *end = buf + bufsz;
10089 
10090 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10091 	if (!pcinfo->valid)
10092 		return 0;
10093 
10094 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
10095 	p += scnprintf(p, end - p,
10096 		       " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
10097 		       "[cycle_cnt]",
10098 		       le16_to_cpu(pcysta->cycles),
10099 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
10100 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
10101 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
10102 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
10103 
10104 	for (i = 0; i < CXST_MAX; i++) {
10105 		if (!le16_to_cpu(pcysta->slot_cnt[i]))
10106 			continue;
10107 
10108 		p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
10109 			       le16_to_cpu(pcysta->slot_cnt[i]));
10110 	}
10111 
10112 	if (dm->tdma_now.rxflctrl)
10113 		p += scnprintf(p, end - p, ", leak_rx:%d",
10114 			       le32_to_cpu(pcysta->leak_slot.cnt_rximr));
10115 
10116 	if (pcysta->collision_cnt)
10117 		p += scnprintf(p, end - p, ", collision:%d",
10118 			       pcysta->collision_cnt);
10119 
10120 	if (le16_to_cpu(pcysta->skip_cnt))
10121 		p += scnprintf(p, end - p, ", skip:%d",
10122 			       le16_to_cpu(pcysta->skip_cnt));
10123 
10124 	p += scnprintf(p, end - p, "\n");
10125 
10126 	p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
10127 		       "[cycle_time]",
10128 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
10129 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
10130 		       le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
10131 		       le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
10132 	p += scnprintf(p, end - p,
10133 		       ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
10134 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
10135 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
10136 		       le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
10137 		       le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
10138 	p += scnprintf(p, end - p,
10139 		       ", maxdiff_t[wl:%d/bt:%d]\n",
10140 		       le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
10141 		       le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
10142 
10143 	cycle = le16_to_cpu(pcysta->cycles);
10144 	if (cycle <= 1)
10145 		goto out;
10146 
10147 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
10148 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10149 
10150 	if (cycle <= slot_pair)
10151 		c_begin = 1;
10152 	else
10153 		c_begin = cycle - slot_pair + 1;
10154 
10155 	c_end = cycle;
10156 
10157 	if (a2dp->exist)
10158 		divide_cnt = 3;
10159 	else
10160 		divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
10161 
10162 	for (cycle = c_begin; cycle <= c_end; cycle++) {
10163 		cnt++;
10164 		store_index = ((cycle - 1) % slot_pair) * 2;
10165 
10166 		if (cnt % divide_cnt == 1)
10167 			p += scnprintf(p, end - p, " %-15s : ",
10168 				       "[cycle_step]");
10169 
10170 		p += scnprintf(p, end - p, "->b%02d",
10171 			       le16_to_cpu(pcysta->slot_step_time[store_index]));
10172 		if (a2dp->exist) {
10173 			a2dp_trx = &pcysta->a2dp_trx[store_index];
10174 			p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10175 				       a2dp_trx->empty_cnt,
10176 				       a2dp_trx->retry_cnt,
10177 				       a2dp_trx->tx_rate ? 3 : 2,
10178 				       a2dp_trx->tx_cnt,
10179 				       a2dp_trx->ack_cnt,
10180 				       a2dp_trx->nack_cnt);
10181 		}
10182 		p += scnprintf(p, end - p, "->w%02d",
10183 			       le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
10184 		if (a2dp->exist) {
10185 			a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
10186 			p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10187 				       a2dp_trx->empty_cnt,
10188 				       a2dp_trx->retry_cnt,
10189 				       a2dp_trx->tx_rate ? 3 : 2,
10190 				       a2dp_trx->tx_cnt,
10191 				       a2dp_trx->ack_cnt,
10192 				       a2dp_trx->nack_cnt);
10193 		}
10194 		if (cnt % divide_cnt == 0 || cnt == c_end)
10195 			p += scnprintf(p, end - p, "\n");
10196 	}
10197 
10198 	if (a2dp->exist) {
10199 		p += scnprintf(p, end - p,
10200 			       " %-15s : a2dp_ept:%d, a2dp_late:%d",
10201 			       "[a2dp_t_sta]",
10202 			       le16_to_cpu(pcysta->a2dp_ept.cnt),
10203 			       le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
10204 
10205 		p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10206 			       le16_to_cpu(pcysta->a2dp_ept.tavg),
10207 			       le16_to_cpu(pcysta->a2dp_ept.tmax));
10208 
10209 		p += scnprintf(p, end - p, "\n");
10210 	}
10211 
10212 out:
10213 	return p - buf;
10214 }
10215 
_show_fbtc_cysta_v5(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10216 static int _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10217 {
10218 	struct rtw89_btc *btc = &rtwdev->btc;
10219 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
10220 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10221 	struct rtw89_btc_dm *dm = &btc->dm;
10222 	struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
10223 	struct rtw89_btc_fbtc_cysta_v5 *pcysta;
10224 	struct rtw89_btc_rpt_cmn_info *pcinfo;
10225 	u8 i, cnt = 0, slot_pair, divide_cnt;
10226 	u16 cycle, c_begin, c_end, store_index;
10227 	char *p = buf, *end = buf + bufsz;
10228 
10229 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10230 	if (!pcinfo->valid)
10231 		return 0;
10232 
10233 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
10234 	p += scnprintf(p, end - p,
10235 		       " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
10236 		       "[cycle_cnt]",
10237 		       le16_to_cpu(pcysta->cycles),
10238 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
10239 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
10240 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
10241 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
10242 
10243 	for (i = 0; i < CXST_MAX; i++) {
10244 		if (!le16_to_cpu(pcysta->slot_cnt[i]))
10245 			continue;
10246 
10247 		p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
10248 			       le16_to_cpu(pcysta->slot_cnt[i]));
10249 	}
10250 
10251 	if (dm->tdma_now.rxflctrl)
10252 		p += scnprintf(p, end - p, ", leak_rx:%d",
10253 			       le32_to_cpu(pcysta->leak_slot.cnt_rximr));
10254 
10255 	if (pcysta->collision_cnt)
10256 		p += scnprintf(p, end - p, ", collision:%d",
10257 			       pcysta->collision_cnt);
10258 
10259 	if (le16_to_cpu(pcysta->skip_cnt))
10260 		p += scnprintf(p, end - p, ", skip:%d",
10261 			       le16_to_cpu(pcysta->skip_cnt));
10262 
10263 	p += scnprintf(p, end - p, "\n");
10264 
10265 	p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
10266 		       "[cycle_time]",
10267 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
10268 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
10269 		       le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
10270 		       le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
10271 	p += scnprintf(p, end - p,
10272 		       ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n",
10273 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
10274 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
10275 		       le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
10276 		       le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
10277 
10278 	cycle = le16_to_cpu(pcysta->cycles);
10279 	if (cycle <= 1)
10280 		goto out;
10281 
10282 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
10283 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10284 
10285 	if (cycle <= slot_pair)
10286 		c_begin = 1;
10287 	else
10288 		c_begin = cycle - slot_pair + 1;
10289 
10290 	c_end = cycle;
10291 
10292 	if (a2dp->exist)
10293 		divide_cnt = 3;
10294 	else
10295 		divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
10296 
10297 	if (c_begin > c_end)
10298 		goto out;
10299 
10300 	for (cycle = c_begin; cycle <= c_end; cycle++) {
10301 		cnt++;
10302 		store_index = ((cycle - 1) % slot_pair) * 2;
10303 
10304 		if (cnt % divide_cnt == 1)
10305 			p += scnprintf(p, end - p, " %-15s : ",
10306 				       "[cycle_step]");
10307 
10308 		p += scnprintf(p, end - p, "->b%02d",
10309 			       le16_to_cpu(pcysta->slot_step_time[store_index]));
10310 		if (a2dp->exist) {
10311 			a2dp_trx = &pcysta->a2dp_trx[store_index];
10312 			p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10313 				       a2dp_trx->empty_cnt,
10314 				       a2dp_trx->retry_cnt,
10315 				       a2dp_trx->tx_rate ? 3 : 2,
10316 				       a2dp_trx->tx_cnt,
10317 				       a2dp_trx->ack_cnt,
10318 				       a2dp_trx->nack_cnt);
10319 		}
10320 		p += scnprintf(p, end - p, "->w%02d",
10321 			       le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
10322 		if (a2dp->exist) {
10323 			a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
10324 			p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10325 				       a2dp_trx->empty_cnt,
10326 				       a2dp_trx->retry_cnt,
10327 				       a2dp_trx->tx_rate ? 3 : 2,
10328 				       a2dp_trx->tx_cnt,
10329 				       a2dp_trx->ack_cnt,
10330 				       a2dp_trx->nack_cnt);
10331 		}
10332 		if (cnt % divide_cnt == 0 || cnt == c_end)
10333 			p += scnprintf(p, end - p, "\n");
10334 	}
10335 
10336 	if (a2dp->exist) {
10337 		p += scnprintf(p, end - p,
10338 			       " %-15s : a2dp_ept:%d, a2dp_late:%d",
10339 			       "[a2dp_t_sta]",
10340 			       le16_to_cpu(pcysta->a2dp_ept.cnt),
10341 			       le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
10342 
10343 		p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10344 			       le16_to_cpu(pcysta->a2dp_ept.tavg),
10345 			       le16_to_cpu(pcysta->a2dp_ept.tmax));
10346 
10347 		p += scnprintf(p, end - p, "\n");
10348 	}
10349 
10350 out:
10351 	return p - buf;
10352 }
10353 
_show_fbtc_cysta_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10354 static int _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10355 {
10356 	struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt;
10357 	struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc;
10358 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
10359 	struct rtw89_btc_fbtc_cysta_v7 *pcysta = NULL;
10360 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
10361 	struct rtw89_btc_rpt_cmn_info *pcinfo;
10362 	char *p = buf, *end = buf + bufsz;
10363 	u16 cycle, c_begin, c_end, s_id;
10364 	u8 i, cnt = 0, divide_cnt;
10365 	u8 slot_pair;
10366 
10367 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10368 	if (!pcinfo->valid)
10369 		return 0;
10370 
10371 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
10372 	p += scnprintf(p, end - p, "\n %-15s : cycle:%d", "[slot_stat]",
10373 		       le16_to_cpu(pcysta->cycles));
10374 
10375 	for (i = 0; i < CXST_MAX; i++) {
10376 		if (!le16_to_cpu(pcysta->slot_cnt[i]))
10377 			continue;
10378 		p += scnprintf(p, end - p, ", %s:%d",
10379 			       id_to_slot(i),
10380 			       le16_to_cpu(pcysta->slot_cnt[i]));
10381 	}
10382 
10383 	if (dm->tdma_now.rxflctrl)
10384 		p += scnprintf(p, end - p, ", leak_rx:%d",
10385 			       le32_to_cpu(pcysta->leak_slot.cnt_rximr));
10386 
10387 	if (pcysta->collision_cnt)
10388 		p += scnprintf(p, end - p, ", collision:%d",
10389 			       pcysta->collision_cnt);
10390 
10391 	if (pcysta->skip_cnt)
10392 		p += scnprintf(p, end - p, ", skip:%d",
10393 			       le16_to_cpu(pcysta->skip_cnt));
10394 
10395 	p += scnprintf(p, end - p,
10396 		       "\n\r %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
10397 		       "[cycle_stat]",
10398 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
10399 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
10400 		       le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
10401 		       le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
10402 	p += scnprintf(p, end - p,
10403 		       ", max_t[wl:%d/bt:%d(>%dms:%d)/lk:%d.%03d]",
10404 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
10405 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
10406 		       dm->bt_slot_flood, dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD],
10407 		       le16_to_cpu(pcysta->leak_slot.tamx) / 1000,
10408 		       le16_to_cpu(pcysta->leak_slot.tamx) % 1000);
10409 	p += scnprintf(p, end - p, ", bcn[all:%d/ok:%d/in_bt:%d/in_bt_ok:%d]",
10410 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
10411 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
10412 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
10413 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
10414 
10415 	if (a2dp->exist) {
10416 		p += scnprintf(p, end - p,
10417 			       "\n\r %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)",
10418 			       "[a2dp_stat]",
10419 			       le16_to_cpu(pcysta->a2dp_ept.cnt),
10420 			       le16_to_cpu(pcysta->a2dp_ept.cnt_timeout),
10421 			       a2dp->no_empty_streak_2s,
10422 			       a2dp->no_empty_streak_max);
10423 
10424 		p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10425 			       le16_to_cpu(pcysta->a2dp_ept.tavg),
10426 			       le16_to_cpu(pcysta->a2dp_ept.tmax));
10427 	}
10428 
10429 	if (le16_to_cpu(pcysta->cycles) <= 1)
10430 		goto out;
10431 
10432 	/* 1 cycle = 1 wl-slot + 1 bt-slot */
10433 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10434 
10435 	if (le16_to_cpu(pcysta->cycles) <= slot_pair)
10436 		c_begin = 1;
10437 	else
10438 		c_begin = le16_to_cpu(pcysta->cycles) - slot_pair + 1;
10439 
10440 	c_end = le16_to_cpu(pcysta->cycles);
10441 
10442 	if (a2dp->exist)
10443 		divide_cnt = 2;
10444 	else
10445 		divide_cnt = 6;
10446 
10447 	if (c_begin > c_end)
10448 		goto out;
10449 
10450 	for (cycle = c_begin; cycle <= c_end; cycle++) {
10451 		cnt++;
10452 		s_id = ((cycle - 1) % slot_pair) * 2;
10453 
10454 		if (cnt % divide_cnt == 1) {
10455 			if (a2dp->exist)
10456 				p += scnprintf(p, end - p, "\n\r %-15s : ",
10457 					       "[slotT_wermtan]");
10458 			else
10459 				p += scnprintf(p, end - p, "\n\r %-15s : ",
10460 					       "[slotT_rxerr]");
10461 		}
10462 
10463 		p += scnprintf(p, end - p, "->b%d",
10464 			       le16_to_cpu(pcysta->slot_step_time[s_id]));
10465 
10466 		if (a2dp->exist)
10467 			p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)",
10468 				       pcysta->wl_rx_err_ratio[s_id],
10469 				       pcysta->a2dp_trx[s_id].empty_cnt,
10470 				       pcysta->a2dp_trx[s_id].retry_cnt,
10471 				       (pcysta->a2dp_trx[s_id].tx_rate ? 3 : 2),
10472 				       pcysta->a2dp_trx[s_id].tx_cnt,
10473 				       pcysta->a2dp_trx[s_id].ack_cnt,
10474 				       pcysta->a2dp_trx[s_id].nack_cnt);
10475 		else
10476 			p += scnprintf(p, end - p, "(%d)",
10477 				       pcysta->wl_rx_err_ratio[s_id]);
10478 
10479 		p += scnprintf(p, end - p, "->w%d",
10480 			       le16_to_cpu(pcysta->slot_step_time[s_id + 1]));
10481 
10482 		if (a2dp->exist)
10483 			p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)",
10484 				       pcysta->wl_rx_err_ratio[s_id + 1],
10485 				       pcysta->a2dp_trx[s_id + 1].empty_cnt,
10486 				       pcysta->a2dp_trx[s_id + 1].retry_cnt,
10487 				       (pcysta->a2dp_trx[s_id + 1].tx_rate ? 3 : 2),
10488 				       pcysta->a2dp_trx[s_id + 1].tx_cnt,
10489 				       pcysta->a2dp_trx[s_id + 1].ack_cnt,
10490 				       pcysta->a2dp_trx[s_id + 1].nack_cnt);
10491 		else
10492 			p += scnprintf(p, end - p, "(%d)",
10493 				       pcysta->wl_rx_err_ratio[s_id + 1]);
10494 	}
10495 
10496 out:
10497 	return p - buf;
10498 }
10499 
_show_fbtc_nullsta(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10500 static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10501 {
10502 	struct rtw89_btc *btc = &rtwdev->btc;
10503 	const struct rtw89_btc_ver *ver = btc->ver;
10504 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10505 	struct rtw89_btc_rpt_cmn_info *pcinfo;
10506 	union rtw89_btc_fbtc_cynullsta_info *ns;
10507 	char *p = buf, *end = buf + bufsz;
10508 	u8 i = 0;
10509 
10510 	if (!btc->dm.tdma_now.rxflctrl)
10511 		return 0;
10512 
10513 	pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
10514 	if (!pcinfo->valid)
10515 		return 0;
10516 
10517 	ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
10518 	if (ver->fcxnullsta == 1) {
10519 		for (i = 0; i < 2; i++) {
10520 			p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]");
10521 			p += scnprintf(p, end - p, "null-%d", i);
10522 			p += scnprintf(p, end - p, "[ok:%d/",
10523 				       le32_to_cpu(ns->v1.result[i][1]));
10524 			p += scnprintf(p, end - p, "fail:%d/",
10525 				       le32_to_cpu(ns->v1.result[i][0]));
10526 			p += scnprintf(p, end - p, "on_time:%d/",
10527 				       le32_to_cpu(ns->v1.result[i][2]));
10528 			p += scnprintf(p, end - p, "retry:%d/",
10529 				       le32_to_cpu(ns->v1.result[i][3]));
10530 			p += scnprintf(p, end - p, "avg_t:%d.%03d/",
10531 				       le32_to_cpu(ns->v1.avg_t[i]) / 1000,
10532 				       le32_to_cpu(ns->v1.avg_t[i]) % 1000);
10533 			p += scnprintf(p, end - p, "max_t:%d.%03d]",
10534 				       le32_to_cpu(ns->v1.max_t[i]) / 1000,
10535 				       le32_to_cpu(ns->v1.max_t[i]) % 1000);
10536 		}
10537 	} else if (ver->fcxnullsta == 7) {
10538 		for (i = 0; i < 2; i++) {
10539 			p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]");
10540 			p += scnprintf(p, end - p, "null-%d", i);
10541 			p += scnprintf(p, end - p, "[Tx:%d/",
10542 				       le32_to_cpu(ns->v7.result[i][4]));
10543 			p += scnprintf(p, end - p, "[ok:%d/",
10544 				       le32_to_cpu(ns->v7.result[i][1]));
10545 			p += scnprintf(p, end - p, "fail:%d/",
10546 				       le32_to_cpu(ns->v7.result[i][0]));
10547 			p += scnprintf(p, end - p, "on_time:%d/",
10548 				       le32_to_cpu(ns->v7.result[i][2]));
10549 			p += scnprintf(p, end - p, "retry:%d/",
10550 				       le32_to_cpu(ns->v7.result[i][3]));
10551 			p += scnprintf(p, end - p, "avg_t:%d.%03d/",
10552 				       le32_to_cpu(ns->v7.tavg[i]) / 1000,
10553 				       le32_to_cpu(ns->v7.tavg[i]) % 1000);
10554 			p += scnprintf(p, end - p, "max_t:%d.%03d]",
10555 				       le32_to_cpu(ns->v7.tmax[i]) / 1000,
10556 				       le32_to_cpu(ns->v7.tmax[i]) % 1000);
10557 		}
10558 	} else {
10559 		for (i = 0; i < 2; i++) {
10560 			p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]");
10561 			p += scnprintf(p, end - p, "null-%d", i);
10562 			p += scnprintf(p, end - p, "[Tx:%d/",
10563 				       le32_to_cpu(ns->v2.result[i][4]));
10564 			p += scnprintf(p, end - p, "[ok:%d/",
10565 				       le32_to_cpu(ns->v2.result[i][1]));
10566 			p += scnprintf(p, end - p, "fail:%d/",
10567 				       le32_to_cpu(ns->v2.result[i][0]));
10568 			p += scnprintf(p, end - p, "on_time:%d/",
10569 				       le32_to_cpu(ns->v2.result[i][2]));
10570 			p += scnprintf(p, end - p, "retry:%d/",
10571 				       le32_to_cpu(ns->v2.result[i][3]));
10572 			p += scnprintf(p, end - p, "avg_t:%d.%03d/",
10573 				       le32_to_cpu(ns->v2.avg_t[i]) / 1000,
10574 				       le32_to_cpu(ns->v2.avg_t[i]) % 1000);
10575 			p += scnprintf(p, end - p, "max_t:%d.%03d]",
10576 				       le32_to_cpu(ns->v2.max_t[i]) / 1000,
10577 				       le32_to_cpu(ns->v2.max_t[i]) % 1000);
10578 		}
10579 	}
10580 
10581 	return p - buf;
10582 }
10583 
_show_fbtc_step_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10584 static int _show_fbtc_step_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10585 {
10586 	struct rtw89_btc *btc = &rtwdev->btc;
10587 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10588 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10589 	struct rtw89_btc_fbtc_steps_v2 *pstep = NULL;
10590 	const struct rtw89_btc_ver *ver = btc->ver;
10591 	char *p = buf, *end = buf + bufsz;
10592 	u8 type, val, cnt = 0, state = 0;
10593 	bool outloop = false;
10594 	u16 i, diff_t, n_start = 0, n_stop = 0;
10595 	u16 pos_old, pos_new, trace_step;
10596 
10597 	pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
10598 	if (!pcinfo->valid)
10599 		return 0;
10600 
10601 	pstep = &pfwinfo->rpt_fbtc_step.finfo.v2;
10602 	pos_old = le16_to_cpu(pstep->pos_old);
10603 	pos_new = le16_to_cpu(pstep->pos_new);
10604 
10605 	if (pcinfo->req_fver != pstep->fver)
10606 		return 0;
10607 
10608 	/* store step info by using ring instead of FIFO*/
10609 	do {
10610 		switch (state) {
10611 		case 0:
10612 			if (ver->fcxctrl == 7 || ver->fcxctrl == 1)
10613 				trace_step = 50;
10614 			else
10615 				trace_step = btc->ctrl.ctrl.trace_step;
10616 
10617 			n_start = pos_old;
10618 			if (pos_new >=  pos_old)
10619 				n_stop = pos_new;
10620 			else
10621 				n_stop = trace_step - 1;
10622 
10623 			state = 1;
10624 			break;
10625 		case 1:
10626 			for (i = n_start; i <= n_stop; i++) {
10627 				type = pstep->step[i].type;
10628 				val = pstep->step[i].val;
10629 				diff_t = le16_to_cpu(pstep->step[i].difft);
10630 
10631 				if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
10632 					continue;
10633 
10634 				if (cnt % 10 == 0)
10635 					p += scnprintf(p, end - p,
10636 						       " %-15s : ", "[steps]");
10637 
10638 				p += scnprintf(p, end - p,
10639 					       "-> %s(%02d)(%02d)",
10640 					       (type == CXSTEP_SLOT ? "SLT" :
10641 						"EVT"), (u32)val, diff_t);
10642 				if (cnt % 10 == 9)
10643 					p += scnprintf(p, end - p, "\n");
10644 				cnt++;
10645 			}
10646 
10647 			state = 2;
10648 			break;
10649 		case 2:
10650 			if (pos_new <  pos_old && n_start != 0) {
10651 				n_start = 0;
10652 				n_stop = pos_new;
10653 				state = 1;
10654 			} else {
10655 				outloop = true;
10656 			}
10657 			break;
10658 		}
10659 	} while (!outloop);
10660 
10661 	return p - buf;
10662 }
10663 
_show_fbtc_step_v3(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10664 static int _show_fbtc_step_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10665 {
10666 	struct rtw89_btc *btc = &rtwdev->btc;
10667 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10668 	struct rtw89_btc_rpt_cmn_info *pcinfo;
10669 	struct rtw89_btc_fbtc_steps_v3 *pstep;
10670 	u32 i, n_begin, n_end, array_idx, cnt = 0;
10671 	char *p = buf, *end = buf + bufsz;
10672 	u8 type, val;
10673 	u16 diff_t;
10674 
10675 	if ((pfwinfo->rpt_en_map &
10676 	     rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0)
10677 		return 0;
10678 
10679 	pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
10680 	if (!pcinfo->valid)
10681 		return 0;
10682 
10683 	pstep = &pfwinfo->rpt_fbtc_step.finfo.v3;
10684 	if (pcinfo->req_fver != pstep->fver)
10685 		return 0;
10686 
10687 	if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP)
10688 		n_begin = 1;
10689 	else
10690 		n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1;
10691 
10692 	n_end = le32_to_cpu(pstep->cnt);
10693 
10694 	if (n_begin > n_end)
10695 		return 0;
10696 
10697 	/* restore step info by using ring instead of FIFO */
10698 	for (i = n_begin; i <= n_end; i++) {
10699 		array_idx = (i - 1) % FCXDEF_STEP;
10700 		type = pstep->step[array_idx].type;
10701 		val = pstep->step[array_idx].val;
10702 		diff_t = le16_to_cpu(pstep->step[array_idx].difft);
10703 
10704 		if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
10705 			continue;
10706 
10707 		if (cnt % 10 == 0)
10708 			p += scnprintf(p, end - p, " %-15s : ", "[steps]");
10709 
10710 		p += scnprintf(p, end - p, "-> %s(%02d)",
10711 			       (type == CXSTEP_SLOT ?
10712 				id_to_slot((u32)val) :
10713 				id_to_evt((u32)val)), diff_t);
10714 
10715 		if (cnt % 10 == 9)
10716 			p += scnprintf(p, end - p, "\n");
10717 
10718 		cnt++;
10719 	}
10720 
10721 	return p - buf;
10722 }
10723 
_show_fw_dm_msg(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10724 static int _show_fw_dm_msg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10725 {
10726 	struct rtw89_btc *btc = &rtwdev->btc;
10727 	const struct rtw89_btc_ver *ver = btc->ver;
10728 	char *p = buf, *end = buf + bufsz;
10729 
10730 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
10731 		goto out;
10732 
10733 	p += _show_error(rtwdev, p, end - p);
10734 	p += _show_fbtc_tdma(rtwdev, p, end - p);
10735 	p += _show_fbtc_slots(rtwdev, p, end - p);
10736 
10737 	if (ver->fcxcysta == 2)
10738 		p += _show_fbtc_cysta_v2(rtwdev, p, end - p);
10739 	else if (ver->fcxcysta == 3)
10740 		p += _show_fbtc_cysta_v3(rtwdev, p, end - p);
10741 	else if (ver->fcxcysta == 4)
10742 		p += _show_fbtc_cysta_v4(rtwdev, p, end - p);
10743 	else if (ver->fcxcysta == 5)
10744 		p += _show_fbtc_cysta_v5(rtwdev, p, end - p);
10745 	else if (ver->fcxcysta == 7)
10746 		p += _show_fbtc_cysta_v7(rtwdev, p, end - p);
10747 
10748 	p += _show_fbtc_nullsta(rtwdev, p, end - p);
10749 
10750 	if (ver->fcxstep == 2)
10751 		p += _show_fbtc_step_v2(rtwdev, p, end - p);
10752 	else if (ver->fcxstep == 3)
10753 		p += _show_fbtc_step_v3(rtwdev, p, end - p);
10754 
10755 out:
10756 	return p - buf;
10757 }
10758 
_get_gnt(struct rtw89_dev * rtwdev,struct rtw89_mac_ax_coex_gnt * gnt_cfg)10759 static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg)
10760 {
10761 	const struct rtw89_chip_info *chip = rtwdev->chip;
10762 	struct rtw89_mac_ax_gnt *gnt;
10763 	u32 val, status;
10764 
10765 	if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B ||
10766 	    chip->chip_id == RTL8851B || chip->chip_id == RTL8852BT) {
10767 		rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
10768 		rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status);
10769 
10770 		gnt = &gnt_cfg->band[0];
10771 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL);
10772 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA);
10773 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL);
10774 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA);
10775 
10776 		gnt = &gnt_cfg->band[1];
10777 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL);
10778 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA);
10779 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL);
10780 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA);
10781 	} else if (chip->chip_id == RTL8852C) {
10782 		val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL);
10783 		status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1);
10784 
10785 		gnt = &gnt_cfg->band[0];
10786 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL);
10787 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0);
10788 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL);
10789 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0);
10790 
10791 		gnt = &gnt_cfg->band[1];
10792 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL);
10793 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1);
10794 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL);
10795 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1);
10796 	} else {
10797 		return;
10798 	}
10799 }
10800 
_show_gpio_dbg(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10801 static int _show_gpio_dbg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10802 {
10803 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
10804 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
10805 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10806 	union rtw89_btc_fbtc_gpio_dbg *gdbg = NULL;
10807 	char *p = buf, *end = buf + bufsz;
10808 	u8 *gpio_map, i;
10809 	u32 en_map;
10810 
10811 	pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
10812 	gdbg = &rtwdev->btc.fwinfo.rpt_fbtc_gpio_dbg.finfo;
10813 	if (!pcinfo->valid) {
10814 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
10815 			    "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n",
10816 			    __func__);
10817 		goto out;
10818 	}
10819 
10820 	if (ver->fcxgpiodbg == 7) {
10821 		en_map = le32_to_cpu(gdbg->v7.en_map);
10822 		gpio_map = gdbg->v7.gpio_map;
10823 	} else {
10824 		en_map = le32_to_cpu(gdbg->v1.en_map);
10825 		gpio_map = gdbg->v1.gpio_map;
10826 	}
10827 
10828 	if (!en_map)
10829 		goto out;
10830 
10831 	p += scnprintf(p, end - p, " %-15s : enable_map:0x%08x",
10832 		       "[gpio_dbg]", en_map);
10833 
10834 	for (i = 0; i < BTC_DBG_MAX1; i++) {
10835 		if (!(en_map & BIT(i)))
10836 			continue;
10837 		p += scnprintf(p, end - p, ", %s->GPIO%d", id_to_gdbg(i),
10838 			       gpio_map[i]);
10839 	}
10840 	p += scnprintf(p, end - p, "\n");
10841 
10842 out:
10843 	return p - buf;
10844 }
10845 
_show_mreg_v1(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10846 static int _show_mreg_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10847 {
10848 	const struct rtw89_chip_info *chip = rtwdev->chip;
10849 	struct rtw89_btc *btc = &rtwdev->btc;
10850 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10851 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10852 	struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL;
10853 	struct rtw89_btc_cx *cx = &btc->cx;
10854 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
10855 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
10856 	struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
10857 	struct rtw89_mac_ax_gnt gnt;
10858 	char *p = buf, *end = buf + bufsz;
10859 	u8 i = 0, type = 0, cnt = 0;
10860 	u32 val, offset;
10861 
10862 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
10863 		return 0;
10864 
10865 	p += scnprintf(p, end - p, "========== [HW Status] ==========\n");
10866 
10867 	p += scnprintf(p, end - p,
10868 		       " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
10869 		       "[scoreboard]", wl->scbd,
10870 		       cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
10871 		       bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
10872 		       cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
10873 
10874 	btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
10875 	_get_gnt(rtwdev, &gnt_cfg);
10876 
10877 	gnt = gnt_cfg.band[0];
10878 	p += scnprintf(p, end - p,
10879 		       " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
10880 		       "[gnt_status]",
10881 		       chip->chip_id == RTL8852C ? "HW" :
10882 		       btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
10883 		       gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
10884 		       gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt);
10885 
10886 	gnt = gnt_cfg.band[1];
10887 	p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
10888 		       gnt.gnt_wl_sw_en ? "SW" : "HW",
10889 		       gnt.gnt_wl,
10890 		       gnt.gnt_bt_sw_en ? "SW" : "HW",
10891 		       gnt.gnt_bt);
10892 
10893 	pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
10894 	if (!pcinfo->valid) {
10895 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
10896 			    "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
10897 			    __func__);
10898 		goto out;
10899 	}
10900 
10901 	pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
10902 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
10903 		    "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
10904 		    __func__, pmreg->reg_num);
10905 
10906 	for (i = 0; i < pmreg->reg_num; i++) {
10907 		type = (u8)le16_to_cpu(chip->mon_reg[i].type);
10908 		offset = le32_to_cpu(chip->mon_reg[i].offset);
10909 		val = le32_to_cpu(pmreg->mreg_val[i]);
10910 
10911 		if (cnt % 6 == 0)
10912 			p += scnprintf(p, end - p,
10913 				       " %-15s : %d_0x%04x=0x%08x",
10914 				       "[reg]", (u32)type, offset, val);
10915 		else
10916 			p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x",
10917 				       (u32)type,
10918 				       offset, val);
10919 		if (cnt % 6 == 5)
10920 			p += scnprintf(p, end - p, "\n");
10921 		cnt++;
10922 
10923 		if (i >= pmreg->reg_num)
10924 			p += scnprintf(p, end - p, "\n");
10925 	}
10926 
10927 out:
10928 	return p - buf;
10929 }
10930 
_show_mreg_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10931 static int _show_mreg_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10932 {
10933 	const struct rtw89_chip_info *chip = rtwdev->chip;
10934 	struct rtw89_btc *btc = &rtwdev->btc;
10935 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10936 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10937 	struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL;
10938 	struct rtw89_btc_cx *cx = &btc->cx;
10939 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
10940 	struct rtw89_btc_bt_info *bt = &btc->cx.bt;
10941 	struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
10942 	struct rtw89_mac_ax_gnt gnt;
10943 	char *p = buf, *end = buf + bufsz;
10944 	u8 i = 0, type = 0, cnt = 0;
10945 	u32 val, offset;
10946 
10947 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
10948 		return 0;
10949 
10950 	p += scnprintf(p, end - p, "========== [HW Status] ==========\n");
10951 
10952 	p += scnprintf(p, end - p,
10953 		       " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
10954 		       "[scoreboard]", wl->scbd,
10955 		       cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
10956 		       bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
10957 		       cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
10958 
10959 	btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
10960 	_get_gnt(rtwdev, &gnt_cfg);
10961 
10962 	gnt = gnt_cfg.band[0];
10963 	p += scnprintf(p, end - p,
10964 		       " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], polut_type:%s",
10965 		       "[gnt_status]",
10966 		       chip->chip_id == RTL8852C ? "HW" :
10967 		       btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
10968 		       gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
10969 		       gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt,
10970 		       id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
10971 
10972 	gnt = gnt_cfg.band[1];
10973 	p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
10974 		       gnt.gnt_wl_sw_en ? "SW" : "HW",
10975 		       gnt.gnt_wl,
10976 		       gnt.gnt_bt_sw_en ? "SW" : "HW",
10977 		       gnt.gnt_bt);
10978 
10979 	pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
10980 	if (!pcinfo->valid) {
10981 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
10982 			    "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
10983 			    __func__);
10984 		goto out;
10985 	}
10986 
10987 	pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
10988 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
10989 		    "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
10990 		    __func__, pmreg->reg_num);
10991 
10992 	for (i = 0; i < pmreg->reg_num; i++) {
10993 		type = (u8)le16_to_cpu(chip->mon_reg[i].type);
10994 		offset = le32_to_cpu(chip->mon_reg[i].offset);
10995 		val = le32_to_cpu(pmreg->mreg_val[i]);
10996 
10997 		if (cnt % 6 == 0)
10998 			p += scnprintf(p, end - p,
10999 				       " %-15s : %d_0x%04x=0x%08x",
11000 				       "[reg]", (u32)type, offset, val);
11001 		else
11002 			p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x",
11003 				       (u32)type,
11004 				       offset, val);
11005 		if (cnt % 6 == 5)
11006 			p += scnprintf(p, end - p, "\n");
11007 		cnt++;
11008 
11009 		if (i >= pmreg->reg_num)
11010 			p += scnprintf(p, end - p, "\n");
11011 	}
11012 
11013 out:
11014 	return p - buf;
11015 }
11016 
_show_mreg_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11017 static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11018 {
11019 	struct rtw89_btc *btc = &rtwdev->btc;
11020 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11021 	struct rtw89_btc_fbtc_mreg_val_v7 *pmreg = NULL;
11022 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11023 	struct rtw89_btc_cx *cx = &btc->cx;
11024 	struct rtw89_btc_wl_info *wl = &cx->wl;
11025 	struct rtw89_btc_bt_info *bt = &cx->bt;
11026 	struct rtw89_mac_ax_gnt *gnt = NULL;
11027 	struct rtw89_btc_dm *dm = &btc->dm;
11028 	char *p = buf, *end = buf + bufsz;
11029 	u8 i, type, cnt = 0;
11030 	u32 val, offset;
11031 
11032 	if (!(dm->coex_info_map & BTC_COEX_INFO_MREG))
11033 		return 0;
11034 
11035 	p += scnprintf(p, end - p, "\n\r========== [HW Status] ==========");
11036 
11037 	p += scnprintf(p, end - p,
11038 		       "\n\r %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)",
11039 		       "[scoreboard]", wl->scbd,
11040 		       cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
11041 		       bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
11042 		       cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
11043 
11044 	/* To avoid I/O if WL LPS or power-off  */
11045 	dm->pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
11046 
11047 	p += scnprintf(p, end - p,
11048 		       "\n\r %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s",
11049 		       "[gnt_status]",
11050 		       rtwdev->chip->para_ver & BTC_FEAT_PTA_ONOFF_CTRL ? "HW" :
11051 		       dm->pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
11052 		       wl->pta_req_mac,
11053 		       id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
11054 
11055 	gnt = &dm->gnt.band[RTW89_PHY_0];
11056 
11057 	p += scnprintf(p, end - p, ", phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]",
11058 		       gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl,
11059 		       gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt);
11060 
11061 	if (rtwdev->dbcc_en) {
11062 		gnt = &dm->gnt.band[RTW89_PHY_1];
11063 		p += scnprintf(p, end - p,
11064 			       ", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]",
11065 			       gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl,
11066 			       gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt);
11067 	}
11068 
11069 	pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
11070 	if (!pcinfo->valid)
11071 		goto out;
11072 
11073 	pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
11074 
11075 	for (i = 0; i < pmreg->reg_num; i++) {
11076 		type = (u8)le16_to_cpu(rtwdev->chip->mon_reg[i].type);
11077 		offset = le32_to_cpu(rtwdev->chip->mon_reg[i].offset);
11078 		val = le32_to_cpu(pmreg->mreg_val[i]);
11079 
11080 		if (cnt % 6 == 0)
11081 			p += scnprintf(p, end - p,
11082 				       "\n\r %-15s : %s_0x%x=0x%x", "[reg]",
11083 				       id_to_regtype(type), offset, val);
11084 		else
11085 			p += scnprintf(p, end - p, ", %s_0x%x=0x%x",
11086 				       id_to_regtype(type), offset, val);
11087 		cnt++;
11088 	}
11089 
11090 out:
11091 	return p - buf;
11092 }
11093 
_show_summary_v1(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11094 static int _show_summary_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11095 {
11096 	struct rtw89_btc *btc = &rtwdev->btc;
11097 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11098 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11099 	struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL;
11100 	struct rtw89_btc_cx *cx = &btc->cx;
11101 	struct rtw89_btc_dm *dm = &btc->dm;
11102 	struct rtw89_btc_wl_info *wl = &cx->wl;
11103 	struct rtw89_btc_bt_info *bt = &cx->bt;
11104 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11105 	char *p = buf, *end = buf + bufsz;
11106 	u8 i;
11107 
11108 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11109 		return 0;
11110 
11111 	p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11112 
11113 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11114 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11115 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v1;
11116 
11117 		p += scnprintf(p, end - p,
11118 			       " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
11119 			       "[summary]", pfwinfo->cnt_h2c,
11120 			       pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt,
11121 			       pfwinfo->cnt_c2h, prptctrl->c2h_cnt);
11122 
11123 		p += scnprintf(p, end - p,
11124 			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
11125 			       pfwinfo->event[BTF_EVNT_RPT],
11126 			       prptctrl->rpt_cnt,
11127 			       prptctrl->rpt_enable, dm->error.val);
11128 
11129 		if (dm->error.map.wl_fw_hang)
11130 			p += scnprintf(p, end - p, " (WL FW Hang!!)");
11131 		p += scnprintf(p, end - p, "\n");
11132 		p += scnprintf(p, end - p,
11133 			       " %-15s : send_ok:%d, send_fail:%d, recv:%d",
11134 			       "[mailbox]", prptctrl->mb_send_ok_cnt,
11135 			       prptctrl->mb_send_fail_cnt,
11136 			       prptctrl->mb_recv_cnt);
11137 
11138 		p += scnprintf(p, end - p,
11139 			       "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n",
11140 			       prptctrl->mb_a2dp_empty_cnt,
11141 			       prptctrl->mb_a2dp_flct_cnt,
11142 			       prptctrl->mb_a2dp_full_cnt);
11143 
11144 		p += scnprintf(p, end - p,
11145 			       " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
11146 			       "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11147 			       cx->cnt_wl[BTC_WCNT_RFK_GO],
11148 			       cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11149 			       cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11150 
11151 		p += scnprintf(p, end - p,
11152 			       ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
11153 			       prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
11154 			       prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
11155 			       prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
11156 			       prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
11157 			       prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
11158 
11159 		if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
11160 			bt->rfk_info.map.timeout = 1;
11161 		else
11162 			bt->rfk_info.map.timeout = 0;
11163 
11164 		dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
11165 	} else {
11166 		p += scnprintf(p, end - p,
11167 			       " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
11168 			       "[summary]", pfwinfo->cnt_h2c,
11169 			       pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
11170 			       pfwinfo->event[BTF_EVNT_RPT],
11171 			       btc->fwinfo.rpt_en_map);
11172 		p += scnprintf(p, end - p, " (WL FW report invalid!!)\n");
11173 	}
11174 
11175 	for (i = 0; i < BTC_NCNT_NUM; i++)
11176 		cnt_sum += dm->cnt_notify[i];
11177 
11178 	p += scnprintf(p, end - p,
11179 		       " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11180 		       "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11181 		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11182 
11183 	p += scnprintf(p, end - p,
11184 		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
11185 		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11186 		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11187 		       cnt[BTC_NCNT_WL_STA]);
11188 
11189 	p += scnprintf(p, end - p,
11190 		       " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11191 		       "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
11192 		       cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
11193 		       cnt[BTC_NCNT_SPECIAL_PACKET]);
11194 
11195 	p += scnprintf(p, end - p,
11196 		       "timer=%d, control=%d, customerize=%d\n",
11197 		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11198 		       cnt[BTC_NCNT_CUSTOMERIZE]);
11199 
11200 	return p - buf;
11201 }
11202 
_show_summary_v4(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11203 static int _show_summary_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11204 {
11205 	struct rtw89_btc *btc = &rtwdev->btc;
11206 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11207 	struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl;
11208 	struct rtw89_btc_rpt_cmn_info *pcinfo;
11209 	struct rtw89_btc_cx *cx = &btc->cx;
11210 	struct rtw89_btc_dm *dm = &btc->dm;
11211 	struct rtw89_btc_wl_info *wl = &cx->wl;
11212 	struct rtw89_btc_bt_info *bt = &cx->bt;
11213 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11214 	char *p = buf, *end = buf + bufsz;
11215 	u8 i;
11216 
11217 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11218 		return 0;
11219 
11220 	p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11221 
11222 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11223 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11224 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v4;
11225 
11226 		p += scnprintf(p, end - p,
11227 			       " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
11228 			       "[summary]", pfwinfo->cnt_h2c,
11229 			       pfwinfo->cnt_h2c_fail,
11230 			       le32_to_cpu(prptctrl->rpt_info.cnt_h2c),
11231 			       pfwinfo->cnt_c2h,
11232 			       le32_to_cpu(prptctrl->rpt_info.cnt_c2h));
11233 
11234 		p += scnprintf(p, end - p,
11235 			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
11236 			       pfwinfo->event[BTF_EVNT_RPT],
11237 			       le32_to_cpu(prptctrl->rpt_info.cnt),
11238 			       le32_to_cpu(prptctrl->rpt_info.en),
11239 			       dm->error.val);
11240 
11241 		if (dm->error.map.wl_fw_hang)
11242 			p += scnprintf(p, end - p, " (WL FW Hang!!)");
11243 		p += scnprintf(p, end - p, "\n");
11244 		p += scnprintf(p, end - p,
11245 			       " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11246 			       "[mailbox]",
11247 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11248 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11249 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11250 
11251 		p += scnprintf(p, end - p,
11252 			       "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
11253 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11254 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11255 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11256 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11257 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11258 
11259 		p += scnprintf(p, end - p,
11260 			       " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
11261 			       "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11262 			       cx->cnt_wl[BTC_WCNT_RFK_GO],
11263 			       cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11264 			       cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11265 
11266 		p += scnprintf(p, end - p,
11267 			       ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
11268 			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]),
11269 			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]),
11270 			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]),
11271 			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]),
11272 			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL]));
11273 
11274 		if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
11275 			bt->rfk_info.map.timeout = 1;
11276 		else
11277 			bt->rfk_info.map.timeout = 0;
11278 
11279 		dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
11280 	} else {
11281 		p += scnprintf(p, end - p,
11282 			       " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
11283 			       "[summary]", pfwinfo->cnt_h2c,
11284 			       pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
11285 			       pfwinfo->event[BTF_EVNT_RPT],
11286 			       btc->fwinfo.rpt_en_map);
11287 		p += scnprintf(p, end - p, " (WL FW report invalid!!)\n");
11288 	}
11289 
11290 	for (i = 0; i < BTC_NCNT_NUM; i++)
11291 		cnt_sum += dm->cnt_notify[i];
11292 
11293 	p += scnprintf(p, end - p,
11294 		       " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11295 		       "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11296 		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11297 
11298 	p += scnprintf(p, end - p,
11299 		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
11300 		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11301 		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11302 		       cnt[BTC_NCNT_WL_STA]);
11303 
11304 	p += scnprintf(p, end - p,
11305 		       " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11306 		       "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
11307 		       cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
11308 		       cnt[BTC_NCNT_SPECIAL_PACKET]);
11309 
11310 	p += scnprintf(p, end - p,
11311 		       "timer=%d, control=%d, customerize=%d\n",
11312 		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11313 		       cnt[BTC_NCNT_CUSTOMERIZE]);
11314 
11315 	return p - buf;
11316 }
11317 
_show_summary_v5(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11318 static int _show_summary_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11319 {
11320 	struct rtw89_btc *btc = &rtwdev->btc;
11321 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11322 	struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl;
11323 	struct rtw89_btc_rpt_cmn_info *pcinfo;
11324 	struct rtw89_btc_cx *cx = &btc->cx;
11325 	struct rtw89_btc_dm *dm = &btc->dm;
11326 	struct rtw89_btc_wl_info *wl = &cx->wl;
11327 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11328 	char *p = buf, *end = buf + bufsz;
11329 	u8 i;
11330 
11331 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11332 		return 0;
11333 
11334 	p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11335 
11336 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11337 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11338 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v5;
11339 
11340 		p += scnprintf(p, end - p,
11341 			       " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
11342 			       "[summary]", pfwinfo->cnt_h2c,
11343 			       pfwinfo->cnt_h2c_fail,
11344 			       le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11345 			       pfwinfo->cnt_c2h,
11346 			       le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11347 			       le16_to_cpu(prptctrl->rpt_info.len_c2h));
11348 
11349 		p += scnprintf(p, end - p,
11350 			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11351 			       pfwinfo->event[BTF_EVNT_RPT],
11352 			       le16_to_cpu(prptctrl->rpt_info.cnt),
11353 			       le32_to_cpu(prptctrl->rpt_info.en));
11354 
11355 		if (dm->error.map.wl_fw_hang)
11356 			p += scnprintf(p, end - p, " (WL FW Hang!!)");
11357 		p += scnprintf(p, end - p, "\n");
11358 		p += scnprintf(p, end - p,
11359 			       " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11360 			       "[mailbox]",
11361 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11362 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11363 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11364 
11365 		p += scnprintf(p, end - p,
11366 			       "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
11367 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11368 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11369 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11370 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11371 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11372 
11373 		p += scnprintf(p, end - p,
11374 			       " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
11375 			       "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11376 			       cx->cnt_wl[BTC_WCNT_RFK_GO],
11377 			       cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11378 			       cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11379 
11380 		p += scnprintf(p, end - p,
11381 			       ", bt_rfk[req:%d]",
11382 			       le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11383 
11384 		p += scnprintf(p, end - p,
11385 			       ", AOAC[RF_on:%d/RF_off:%d]",
11386 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11387 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11388 	} else {
11389 		p += scnprintf(p, end - p,
11390 			       " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
11391 			       "[summary]", pfwinfo->cnt_h2c,
11392 			       pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
11393 	}
11394 
11395 	if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
11396 	    pfwinfo->err[BTFRE_EXCEPTION]) {
11397 		p += scnprintf(p, end - p, "\n");
11398 		p += scnprintf(p, end - p,
11399 			       " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
11400 			       "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
11401 			       "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
11402 			       pfwinfo->fver_mismch,
11403 			       pfwinfo->err[BTFRE_EXCEPTION],
11404 			       wl->status.map.lps, wl->status.map.rf_off);
11405 	}
11406 
11407 	for (i = 0; i < BTC_NCNT_NUM; i++)
11408 		cnt_sum += dm->cnt_notify[i];
11409 
11410 	p += scnprintf(p, end - p, "\n");
11411 	p += scnprintf(p, end - p,
11412 		       " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11413 		       "[notify_cnt]",
11414 		       cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11415 		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11416 
11417 	p += scnprintf(p, end - p,
11418 		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11419 		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11420 		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11421 		       cnt[BTC_NCNT_WL_STA]);
11422 
11423 	p += scnprintf(p, end - p, "\n");
11424 	p += scnprintf(p, end - p,
11425 		       " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11426 		       "[notify_cnt]",
11427 		       cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11428 		       cnt[BTC_NCNT_SWITCH_BAND],
11429 		       cnt[BTC_NCNT_SPECIAL_PACKET]);
11430 
11431 	p += scnprintf(p, end - p,
11432 		       "timer=%d, control=%d, customerize=%d",
11433 		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11434 		       cnt[BTC_NCNT_CUSTOMERIZE]);
11435 
11436 	return p - buf;
11437 }
11438 
_show_summary_v105(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11439 static int _show_summary_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11440 {
11441 	struct rtw89_btc *btc = &rtwdev->btc;
11442 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11443 	struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl;
11444 	struct rtw89_btc_rpt_cmn_info *pcinfo;
11445 	struct rtw89_btc_cx *cx = &btc->cx;
11446 	struct rtw89_btc_dm *dm = &btc->dm;
11447 	struct rtw89_btc_wl_info *wl = &cx->wl;
11448 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11449 	char *p = buf, *end = buf + bufsz;
11450 	u8 i;
11451 
11452 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11453 		return 0;
11454 
11455 	p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11456 
11457 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11458 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11459 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v105;
11460 
11461 		p += scnprintf(p, end - p,
11462 			       " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
11463 			       "[summary]", pfwinfo->cnt_h2c,
11464 			       pfwinfo->cnt_h2c_fail,
11465 			       le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11466 			       pfwinfo->cnt_c2h,
11467 			       le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11468 			       le16_to_cpu(prptctrl->rpt_info.len_c2h));
11469 
11470 		p += scnprintf(p, end - p,
11471 			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11472 			       pfwinfo->event[BTF_EVNT_RPT],
11473 			       le16_to_cpu(prptctrl->rpt_info.cnt),
11474 			       le32_to_cpu(prptctrl->rpt_info.en));
11475 
11476 		if (dm->error.map.wl_fw_hang)
11477 			p += scnprintf(p, end - p, " (WL FW Hang!!)");
11478 		p += scnprintf(p, end - p, "\n");
11479 		p += scnprintf(p, end - p,
11480 			       " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11481 			       "[mailbox]",
11482 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11483 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11484 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11485 
11486 		p += scnprintf(p, end - p,
11487 			       "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
11488 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11489 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11490 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11491 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11492 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11493 
11494 		p += scnprintf(p, end - p,
11495 			       " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
11496 			       "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11497 			       cx->cnt_wl[BTC_WCNT_RFK_GO],
11498 			       cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11499 			       cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11500 
11501 		p += scnprintf(p, end - p,
11502 			       ", bt_rfk[req:%d]",
11503 			       le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11504 
11505 		p += scnprintf(p, end - p,
11506 			       ", AOAC[RF_on:%d/RF_off:%d]",
11507 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11508 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11509 	} else {
11510 		p += scnprintf(p, end - p,
11511 			       " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
11512 			       "[summary]", pfwinfo->cnt_h2c,
11513 			       pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
11514 	}
11515 
11516 	if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
11517 	    pfwinfo->err[BTFRE_EXCEPTION]) {
11518 		p += scnprintf(p, end - p, "\n");
11519 		p += scnprintf(p, end - p,
11520 			       " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
11521 			       "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
11522 			       "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
11523 			       pfwinfo->fver_mismch,
11524 			       pfwinfo->err[BTFRE_EXCEPTION],
11525 			       wl->status.map.lps, wl->status.map.rf_off);
11526 	}
11527 
11528 	for (i = 0; i < BTC_NCNT_NUM; i++)
11529 		cnt_sum += dm->cnt_notify[i];
11530 
11531 	p += scnprintf(p, end - p, "\n");
11532 	p += scnprintf(p, end - p,
11533 		       " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11534 		       "[notify_cnt]",
11535 		       cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11536 		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11537 
11538 	p += scnprintf(p, end - p,
11539 		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11540 		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11541 		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11542 		       cnt[BTC_NCNT_WL_STA]);
11543 
11544 	p += scnprintf(p, end - p, "\n");
11545 	p += scnprintf(p, end - p,
11546 		       " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11547 		       "[notify_cnt]",
11548 		       cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11549 		       cnt[BTC_NCNT_SWITCH_BAND],
11550 		       cnt[BTC_NCNT_SPECIAL_PACKET]);
11551 
11552 	p += scnprintf(p, end - p,
11553 		       "timer=%d, control=%d, customerize=%d",
11554 		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11555 		       cnt[BTC_NCNT_CUSTOMERIZE]);
11556 
11557 	return p - buf;
11558 }
11559 
_show_summary_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11560 static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11561 {
11562 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
11563 	struct rtw89_btc_fbtc_rpt_ctrl_v7 *prptctrl = NULL;
11564 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11565 	struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
11566 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
11567 	struct rtw89_btc_wl_info *wl = &cx->wl;
11568 	u32 *cnt = rtwdev->btc.dm.cnt_notify;
11569 	char *p = buf, *end = buf + bufsz;
11570 	u32 cnt_sum = 0;
11571 	u8 i;
11572 
11573 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11574 		return 0;
11575 
11576 	p += scnprintf(p, end - p, "%s",
11577 		       "\n\r========== [Statistics] ==========");
11578 
11579 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11580 	if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
11581 	    !wl->status.map.rf_off) {
11582 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v7;
11583 
11584 		p += scnprintf(p, end - p,
11585 			       "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d),"
11586 			       "c2h_cnt=%d(fw_send:%d, len:%d, max:%d), ",
11587 			       "[summary]", pfwinfo->cnt_h2c,
11588 			       pfwinfo->cnt_h2c_fail,
11589 			       le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11590 			       pfwinfo->cnt_c2h,
11591 			       le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11592 			       le16_to_cpu(prptctrl->rpt_info.len_c2h),
11593 			       rtwdev->btc.ver->info_buf);
11594 
11595 		p += scnprintf(p, end - p,
11596 			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11597 			       pfwinfo->event[BTF_EVNT_RPT],
11598 			       le16_to_cpu(prptctrl->rpt_info.cnt),
11599 			       le32_to_cpu(prptctrl->rpt_info.en));
11600 
11601 		if (dm->error.map.wl_fw_hang)
11602 			p += scnprintf(p, end - p, " (WL FW Hang!!)");
11603 
11604 		p += scnprintf(p, end - p,
11605 			       "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11606 			       "[mailbox]",
11607 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11608 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11609 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11610 
11611 		p += scnprintf(p, end - p,
11612 			       "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)",
11613 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11614 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11615 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11616 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11617 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11618 
11619 		p += scnprintf(p, end - p,
11620 			       "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
11621 			       "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11622 			       cx->cnt_wl[BTC_WCNT_RFK_GO],
11623 			       cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11624 			       cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT],
11625 			       wl->rfk_info.proc_time);
11626 
11627 		p += scnprintf(p, end - p, ", bt_rfk[req:%d]",
11628 			       le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11629 
11630 		p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]",
11631 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11632 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11633 	} else {
11634 		p += scnprintf(p, end - p,
11635 			       "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)",
11636 			       "[summary]",
11637 			       pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
11638 			       pfwinfo->cnt_c2h,
11639 			       wl->status.map.lps, wl->status.map.rf_off);
11640 	}
11641 
11642 	for (i = 0; i < BTC_NCNT_NUM; i++)
11643 		cnt_sum += dm->cnt_notify[i];
11644 
11645 	p += scnprintf(p, end - p,
11646 		       "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11647 		       "[notify_cnt]",
11648 		       cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11649 		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11650 
11651 	p += scnprintf(p, end - p,
11652 		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11653 		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11654 		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11655 		       cnt[BTC_NCNT_WL_STA]);
11656 
11657 	p += scnprintf(p, end - p,
11658 		       "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
11659 		       "[notify_cnt]",
11660 		       cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11661 		       cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
11662 		       cnt[BTC_NCNT_SPECIAL_PACKET]);
11663 
11664 	p += scnprintf(p, end - p,
11665 		       "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
11666 		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
11667 		       rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
11668 		       cnt[BTC_NCNT_COUNTRYCODE]);
11669 
11670 	return p - buf;
11671 }
11672 
_show_summary_v8(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11673 static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11674 {
11675 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
11676 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11677 	struct rtw89_btc_fbtc_rpt_ctrl_v8 *prptctrl = NULL;
11678 	struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
11679 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
11680 	struct rtw89_btc_wl_info *wl = &cx->wl;
11681 	u32 *cnt = rtwdev->btc.dm.cnt_notify;
11682 	char *p = buf, *end = buf + bufsz;
11683 	u32 cnt_sum = 0;
11684 	u8 i;
11685 
11686 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11687 		return 0;
11688 
11689 	p += scnprintf(p, end - p, "%s",
11690 		       "\n\r========== [Statistics] ==========");
11691 
11692 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11693 	if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
11694 	    !wl->status.map.rf_off) {
11695 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v8;
11696 
11697 		p += scnprintf(p, end - p,
11698 			       "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ",
11699 			       "[summary]", pfwinfo->cnt_h2c,
11700 			       pfwinfo->cnt_h2c_fail,
11701 			       le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11702 			       pfwinfo->cnt_c2h,
11703 			       le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11704 			       le16_to_cpu(prptctrl->rpt_info.len_c2h),
11705 			       (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l,
11706 			       rtwdev->btc.ver->info_buf);
11707 
11708 		p += scnprintf(p, end - p,
11709 			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11710 			       pfwinfo->event[BTF_EVNT_RPT],
11711 			       le16_to_cpu(prptctrl->rpt_info.cnt),
11712 			       le32_to_cpu(prptctrl->rpt_info.en));
11713 
11714 		if (dm->error.map.wl_fw_hang)
11715 			p += scnprintf(p, end - p, " (WL FW Hang!!)");
11716 
11717 		p += scnprintf(p, end - p,
11718 			       "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11719 			       "[mailbox]",
11720 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11721 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11722 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11723 
11724 		p += scnprintf(p, end - p,
11725 			       "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)",
11726 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11727 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11728 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11729 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11730 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11731 
11732 		p += scnprintf(p, end - p,
11733 			       "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
11734 			       "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11735 			       cx->cnt_wl[BTC_WCNT_RFK_GO],
11736 			       cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11737 			       cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT],
11738 			       wl->rfk_info.proc_time);
11739 
11740 		p += scnprintf(p, end - p, ", bt_rfk[req:%d]",
11741 			       le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11742 
11743 		p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]",
11744 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11745 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11746 	} else {
11747 		p += scnprintf(p, end - p,
11748 			       "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)",
11749 			       "[summary]",
11750 			       pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
11751 			       pfwinfo->cnt_c2h,
11752 			       wl->status.map.lps, wl->status.map.rf_off);
11753 	}
11754 
11755 	for (i = 0; i < BTC_NCNT_NUM; i++)
11756 		cnt_sum += dm->cnt_notify[i];
11757 
11758 	p += scnprintf(p, end - p,
11759 		       "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11760 		       "[notify_cnt]",
11761 		       cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11762 		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11763 
11764 	p += scnprintf(p, end - p,
11765 		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11766 		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11767 		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11768 		       cnt[BTC_NCNT_WL_STA]);
11769 
11770 	p += scnprintf(p, end - p,
11771 		       "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
11772 		       "[notify_cnt]",
11773 		       cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11774 		       cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
11775 		       cnt[BTC_NCNT_SPECIAL_PACKET]);
11776 
11777 	p += scnprintf(p, end - p,
11778 		       "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
11779 		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
11780 		       rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
11781 		       cnt[BTC_NCNT_COUNTRYCODE]);
11782 
11783 	return p - buf;
11784 }
11785 
rtw89_btc_dump_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11786 ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11787 {
11788 	struct rtw89_btc *btc = &rtwdev->btc;
11789 	struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver;
11790 	const struct rtw89_btc_ver *ver = btc->ver;
11791 	struct rtw89_btc_dm *dm = &btc->dm;
11792 	char *p = buf, *end = buf + bufsz;
11793 
11794 	dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
11795 
11796 	p += scnprintf(p, end - p,
11797 		       "\n\n\n** Page:%3d/RunCNT:%3d **",
11798 		       dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO],
11799 		       dm->cnt_dm[BTC_DCNT_RUN]);
11800 	p += scnprintf(p, end - p,
11801 		       "\n========== [BTC FEATURE SUB VER] ==========");
11802 	p += scnprintf(p, end - p,
11803 		       "\n %-15s : fcxbtcrpt[%d/%d], fcxtdma[%d/%d], fcxslots[%d/%d], fcxcysta[%d/%d]",
11804 		       "[FW/DRV]", fwsubver->fcxbtcrpt, ver->fcxbtcrpt,
11805 		       fwsubver->fcxtdma, ver->fcxtdma, fwsubver->fcxslots,
11806 		       ver->fcxslots, fwsubver->fcxcysta, ver->fcxcysta);
11807 	p += scnprintf(p, end - p,
11808 		       "\n %-15s : fcxstep[%d/%d], fcxnullsta[%d/%d], fcxmreg[%d/%d], fcxgpiodbg[%d/%d]",
11809 		       "[FW/DRV]", fwsubver->fcxstep, ver->fcxstep,
11810 		       fwsubver->fcxnullsta, ver->fcxnullsta, fwsubver->fcxmreg,
11811 		       ver->fcxmreg, fwsubver->fcxgpiodbg, ver->fcxgpiodbg);
11812 	p += scnprintf(p, end - p,
11813 		       "\n %-15s : fcxbtver[%d/%d], fcxbtscan[%d/%d], fcxbtafh[%d/%d], fcxbtdevinfo[%d/%d]",
11814 		       "[FW/DRV]", fwsubver->fcxbtver, ver->fcxbtver,
11815 		       fwsubver->fcxbtscan, ver->fcxbtscan, fwsubver->fcxbtafh,
11816 		       ver->fcxbtafh, fwsubver->fcxbtdevinfo, ver->fcxbtdevinfo);
11817 	p += scnprintf(p, end - p,
11818 		       "\n %-15s : fcxosi[%d/%d], fcxmlo[%d/%d],",
11819 		       "[FW/DRV]", fwsubver->fcxosi, ver->fcxosi,
11820 		       fwsubver->fcxmlo, ver->fcxmlo);
11821 
11822 	p += _show_cx_info(rtwdev, p, end - p);
11823 	p += _show_wl_info(rtwdev, p, end - p);
11824 	p += _show_bt_info(rtwdev, p, end - p);
11825 	p += _show_dm_info(rtwdev, p, end - p);
11826 	p += _show_fw_dm_msg(rtwdev, p, end - p);
11827 
11828 	if (ver->fcxmreg == 1)
11829 		p += _show_mreg_v1(rtwdev, p, end - p);
11830 	else if (ver->fcxmreg == 2)
11831 		p += _show_mreg_v2(rtwdev, p, end - p);
11832 	else if (ver->fcxmreg == 7)
11833 		p += _show_mreg_v7(rtwdev, p, end - p);
11834 
11835 	p += _show_gpio_dbg(rtwdev, p, end - p);
11836 
11837 	if (ver->fcxbtcrpt == 1)
11838 		p += _show_summary_v1(rtwdev, p, end - p);
11839 	else if (ver->fcxbtcrpt == 4)
11840 		p += _show_summary_v4(rtwdev, p, end - p);
11841 	else if (ver->fcxbtcrpt == 5)
11842 		p += _show_summary_v5(rtwdev, p, end - p);
11843 	else if (ver->fcxbtcrpt == 105)
11844 		p += _show_summary_v105(rtwdev, p, end - p);
11845 	else if (ver->fcxbtcrpt == 7)
11846 		p += _show_summary_v7(rtwdev, p, end - p);
11847 	else if (ver->fcxbtcrpt == 8)
11848 		p += _show_summary_v8(rtwdev, p, end - p);
11849 
11850 	return p - buf;
11851 }
11852 
rtw89_coex_recognize_ver(struct rtw89_dev * rtwdev)11853 void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev)
11854 {
11855 	const struct rtw89_chip_info *chip = rtwdev->chip;
11856 	struct rtw89_btc *btc = &rtwdev->btc;
11857 	const struct rtw89_btc_ver *btc_ver_def;
11858 	const struct rtw89_fw_suit *fw_suit;
11859 	u32 suit_ver_code;
11860 	int i;
11861 
11862 	fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL);
11863 	suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit);
11864 
11865 	for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) {
11866 		btc_ver_def = &rtw89_btc_ver_defs[i];
11867 
11868 		if (chip->chip_id != btc_ver_def->chip_id)
11869 			continue;
11870 
11871 		if (suit_ver_code >= btc_ver_def->fw_ver_code) {
11872 			btc->ver = btc_ver_def;
11873 			goto out;
11874 		}
11875 	}
11876 
11877 	btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX];
11878 
11879 out:
11880 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n",
11881 		    (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code);
11882 }
11883 
rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev * rtwdev,u32 ms)11884 void rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev *rtwdev, u32 ms)
11885 {
11886 	struct rtw89_btc_bt_link_info *bt_linfo = &rtwdev->btc.cx.bt.link_info;
11887 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
11888 
11889 	if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags))
11890 		return;
11891 
11892 	if (!a2dp.exist)
11893 		return;
11894 
11895 	fsleep(ms * 1000);
11896 }
11897 EXPORT_SYMBOL(rtw89_btc_ntfy_preserve_bt_time);
11898 
rtw89_btc_ntfy_conn_rfk(struct rtw89_dev * rtwdev,bool state)11899 void rtw89_btc_ntfy_conn_rfk(struct rtw89_dev *rtwdev, bool state)
11900 {
11901 	rtwdev->btc.cx.wl.rfk_info.con_rfk = state;
11902 }
11903 EXPORT_SYMBOL(rtw89_btc_ntfy_conn_rfk);
11904