xref: /linux/drivers/net/wireless/realtek/rtw89/coex.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
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 0x09180113
15 #define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/
16 #define BTC_E2G_LIMIT_DEF 80
17 
18 enum btc_fbtc_tdma_template {
19 	CXTD_OFF = 0x0,
20 	CXTD_OFF_B2,
21 	CXTD_OFF_EXT,
22 	CXTD_FIX,
23 	CXTD_PFIX,
24 	CXTD_AUTO,
25 	CXTD_PAUTO,
26 	CXTD_AUTO2,
27 	CXTD_PAUTO2,
28 	CXTD_MAX,
29 };
30 
31 enum btc_fbtc_tdma_type {
32 	CXTDMA_OFF = 0x0,
33 	CXTDMA_FIX = 0x1,
34 	CXTDMA_AUTO = 0x2,
35 	CXTDMA_AUTO2 = 0x3,
36 	CXTDMA_MAX
37 };
38 
39 enum btc_fbtc_tdma_rx_flow_ctrl {
40 	CXFLC_OFF = 0x0,
41 	CXFLC_NULLP = 0x1,
42 	CXFLC_QOSNULL = 0x2,
43 	CXFLC_CTS = 0x3,
44 	CXFLC_MAX
45 };
46 
47 enum btc_fbtc_tdma_wlan_tx_pause {
48 	CXTPS_OFF = 0x0,  /* no wl tx pause*/
49 	CXTPS_ON = 0x1,
50 	CXTPS_MAX
51 };
52 
53 enum btc_mlme_state {
54 	MLME_NO_LINK,
55 	MLME_LINKING,
56 	MLME_LINKED,
57 };
58 
59 struct btc_fbtc_1slot {
60 	u8 fver;
61 	u8 sid; /* slot id */
62 	struct rtw89_btc_fbtc_slot slot;
63 } __packed;
64 
65 static const struct rtw89_btc_fbtc_tdma t_def[] = {
66 	[CXTD_OFF]	= { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
67 	[CXTD_OFF_B2]	= { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0},
68 	[CXTD_OFF_EXT]	= { CXTDMA_OFF,    CXFLC_OFF, CXTPS_OFF, 0, 0, 2, 0, 0},
69 	[CXTD_FIX]	= { CXTDMA_FIX,    CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
70 	[CXTD_PFIX]	= { CXTDMA_FIX,  CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0},
71 	[CXTD_AUTO]	= { CXTDMA_AUTO,   CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
72 	[CXTD_PAUTO]	= { CXTDMA_AUTO, CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0},
73 	[CXTD_AUTO2]	= {CXTDMA_AUTO2,   CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
74 	[CXTD_PAUTO2]	= {CXTDMA_AUTO2, CXFLC_NULLP,  CXTPS_ON, 0, 5, 0, 0, 0}
75 };
76 
77 #define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \
78 	{ .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \
79 	  .cxtype = cpu_to_le16(__cxtype),}
80 
81 static const struct rtw89_btc_fbtc_slot s_def[] = {
82 	[CXST_OFF]	= __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
83 	[CXST_B2W]	= __DEF_FBTC_SLOT(5,   0xea5a5a5a, SLOT_ISO),
84 	[CXST_W1]	= __DEF_FBTC_SLOT(70,  0xea5a5a5a, SLOT_ISO),
85 	[CXST_W2]	= __DEF_FBTC_SLOT(15,  0xea5a5a5a, SLOT_ISO),
86 	[CXST_W2B]	= __DEF_FBTC_SLOT(15,  0xea5a5a5a, SLOT_ISO),
87 	[CXST_B1]	= __DEF_FBTC_SLOT(250, 0xe5555555, SLOT_MIX),
88 	[CXST_B2]	= __DEF_FBTC_SLOT(7,   0xea5a5a5a, SLOT_MIX),
89 	[CXST_B3]	= __DEF_FBTC_SLOT(5,   0xe5555555, SLOT_MIX),
90 	[CXST_B4]	= __DEF_FBTC_SLOT(50,  0xe5555555, SLOT_MIX),
91 	[CXST_LK]	= __DEF_FBTC_SLOT(20,  0xea5a5a5a, SLOT_ISO),
92 	[CXST_BLK]	= __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX),
93 	[CXST_E2G]	= __DEF_FBTC_SLOT(5,   0xea5a5a5a, SLOT_MIX),
94 	[CXST_E5G]	= __DEF_FBTC_SLOT(5,   0xffffffff, SLOT_ISO),
95 	[CXST_EBT]	= __DEF_FBTC_SLOT(5,   0xe5555555, SLOT_MIX),
96 	[CXST_ENULL]	= __DEF_FBTC_SLOT(5,   0x55555555, SLOT_MIX),
97 	[CXST_WLK]	= __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX),
98 	[CXST_W1FDD]	= __DEF_FBTC_SLOT(50,  0xffffffff, SLOT_ISO),
99 	[CXST_B1FDD]	= __DEF_FBTC_SLOT(50,  0xffffdfff, SLOT_ISO),
100 };
101 
102 static const u32 cxtbl[] = {
103 	0xffffffff, /* 0 */
104 	0xaaaaaaaa, /* 1 */
105 	0xe5555555, /* 2 */
106 	0xee555555, /* 3 */
107 	0xd5555555, /* 4 */
108 	0x5a5a5a5a, /* 5 */
109 	0xfa5a5a5a, /* 6 */
110 	0xda5a5a5a, /* 7 */
111 	0xea5a5a5a, /* 8 */
112 	0x6a5a5aaa, /* 9 */
113 	0x6a5a6a5a, /* 10 */
114 	0x6a5a6aaa, /* 11 */
115 	0x6afa5afa, /* 12 */
116 	0xaaaa5aaa, /* 13 */
117 	0xaaffffaa, /* 14 */
118 	0xaa5555aa, /* 15 */
119 	0xfafafafa, /* 16 */
120 	0xffffddff, /* 17 */
121 	0xdaffdaff, /* 18 */
122 	0xfafadafa, /* 19 */
123 	0xea6a6a6a, /* 20 */
124 	0xea55556a, /* 21 */
125 	0xaafafafa, /* 22 */
126 	0xfafaaafa, /* 23 */
127 	0xfafffaff, /* 24 */
128 	0xea6a5a5a, /* 25 */
129 	0xfaff5aff, /* 26 */
130 	0xffffdfff, /* 27 */
131 	0xe6555555, /* 28 */
132 };
133 
134 static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
135 	/* firmware version must be in decreasing order for each chip */
136 	{RTL8922D, RTW89_FW_VER_CODE(0, 35, 111, 0),
137 	 .fcxbtcrpt = 11, .fcxtdma = 8,    .fcxslots = 7, .fcxcysta = 8,
138 	 .fcxstep = 7,    .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 8,
139 	 .fcxbtver = 8,   .fcxbtscan = 8,  .fcxbtafh = 8, .fcxbtdevinfo = 8,
140 	 .fwlrole = 10,   .frptmap = 5,    .fcxctrl = 9,  .fcxinit = 11,
141 	 .fwevntrptl = 1, .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800,
142 	 .max_role_num = 6, .fcxosi = 6,   .fcxmlo = 2,   .bt_desired = 8,
143 	 .fcxtrx = 9,
144 	},
145 	{RTL8922D, RTW89_FW_VER_CODE(0, 35, 94, 0),
146 	 .fcxbtcrpt = 11, .fcxtdma = 8,    .fcxslots = 7, .fcxcysta = 8,
147 	 .fcxstep = 7,    .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 8,
148 	 .fcxbtver = 8,   .fcxbtscan = 8,  .fcxbtafh = 8, .fcxbtdevinfo = 8,
149 	 .fwlrole = 10,    .frptmap = 5,    .fcxctrl = 9,  .fcxinit = 10,
150 	 .fwevntrptl = 1,  .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800,
151 	 .max_role_num = 6, .fcxosi = 6,   .fcxmlo = 2,   .bt_desired = 8,
152 	 .fcxtrx = 9,
153 	},
154 	{RTL8852BT, RTW89_FW_VER_CODE(0, 29, 133, 0),
155 	 .fcxbtcrpt = 9, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
156 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 8,
157 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
158 	 .fwlrole = 7,   .frptmap = 5,    .fcxctrl = 7,  .fcxinit = 107,
159 	 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 103, .info_buf = 1800,
160 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 8,
161 	 .fcxtrx = 107,
162 	},
163 	{RTL8852BT, RTW89_FW_VER_CODE(0, 29, 122, 0),
164 	 .fcxbtcrpt = 8, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
165 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 7,
166 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
167 	 .fwlrole = 7,   .frptmap = 3,    .fcxctrl = 7,  .fcxinit = 7,
168 	 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 1, .info_buf = 1800,
169 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 8,
170 	 .fcxtrx = 0,
171 	},
172 	{RTL8852BT, RTW89_FW_VER_CODE(0, 29, 90, 0),
173 	 .fcxbtcrpt = 7, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
174 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 7,
175 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
176 	 .fwlrole = 7,   .frptmap = 3,    .fcxctrl = 7,  .fcxinit = 7,
177 	 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 1, .info_buf = 1800,
178 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 8,
179 	 .fcxtrx = 0,
180 	},
181 	{RTL8922A, RTW89_FW_VER_CODE(0, 35, 111, 0),
182 	 .fcxbtcrpt = 11, .fcxtdma = 8,    .fcxslots = 7, .fcxcysta = 8,
183 	 .fcxstep = 7,    .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 8,
184 	 .fcxbtver = 8,   .fcxbtscan = 8,  .fcxbtafh = 8, .fcxbtdevinfo = 8,
185 	 .fwlrole = 10,   .frptmap = 5,    .fcxctrl = 9,  .fcxinit = 11,
186 	 .fwevntrptl = 1, .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800,
187 	 .max_role_num = 6, .fcxosi = 6,   .fcxmlo = 2,   .bt_desired = 8,
188 	 .fcxtrx = 9,
189 	},
190 	{RTL8922A, RTW89_FW_VER_CODE(0, 35, 71, 0),
191 	 .fcxbtcrpt = 8, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
192 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 7,
193 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
194 	 .fwlrole = 8,   .frptmap = 4,    .fcxctrl = 7,  .fcxinit = 7,
195 	 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_ver = 3, .info_buf = 1800,
196 	 .max_role_num = 6, .fcxosi = 1,  .fcxmlo = 1,   .bt_desired = 9,
197 	 .fcxtrx = 7,
198 	},
199 	{RTL8922A, RTW89_FW_VER_CODE(0, 35, 63, 0),
200 	 .fcxbtcrpt = 8, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
201 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 7,
202 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
203 	 .fwlrole = 8,   .frptmap = 4,    .fcxctrl = 7,  .fcxinit = 7,
204 	 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_ver = 2, .info_buf = 1800,
205 	 .max_role_num = 6, .fcxosi = 1,  .fcxmlo = 1,   .bt_desired = 9,
206 	 .fcxtrx = 0,
207 	},
208 	{RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 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 = 8,   .frptmap = 3,    .fcxctrl = 7,  .fcxinit = 7,
213 	 .fwevntrptl = 1, .fwc2hfunc = 1, .drvinfo_ver = 1, .info_buf = 1800,
214 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
215 	 .fcxtrx = 0,
216 	},
217 	{RTL8851B, RTW89_FW_VER_CODE(0, 29, 133, 0),
218 	 .fcxbtcrpt = 9, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
219 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 8,
220 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
221 	 .fwlrole = 7,   .frptmap = 5,    .fcxctrl = 7,  .fcxinit = 107,
222 	 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 103, .info_buf = 1800,
223 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 8,
224 	 .fcxtrx = 107,
225 	},
226 	{RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0),
227 	 .fcxbtcrpt = 105, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 5,
228 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 2,  .fcxgpiodbg = 1,
229 	 .fcxbtver = 1,  .fcxbtscan = 2,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
230 	 .fwlrole = 2,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
231 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1800,
232 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
233 	 .fcxtrx = 0,
234 	},
235 	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 97, 0),
236 	 .fcxbtcrpt = 4, .fcxtdma = 4,    .fcxslots = 2, .fcxcysta = 105,
237 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 2,  .fcxgpiodbg = 1,
238 	 .fcxbtver = 1,  .fcxbtscan = 2,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
239 	 .fwlrole = 101, .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
240 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280,
241 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
242 	 .fcxtrx = 107,
243 	},
244 	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0),
245 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
246 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
247 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
248 	 .fwlrole = 1,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
249 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280,
250 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
251 	 .fcxtrx = 0,
252 	},
253 	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0),
254 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
255 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
256 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
257 	 .fwlrole = 1,   .frptmap = 2,    .fcxctrl = 1,  .fcxinit = 0,
258 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280,
259 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
260 	 .fcxtrx = 0,
261 	},
262 	{RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0),
263 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
264 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
265 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
266 	 .fwlrole = 1,   .frptmap = 2,    .fcxctrl = 1,  .fcxinit = 0,
267 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280,
268 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
269 	 .fcxtrx = 0,
270 	},
271 	{RTL8852B, RTW89_FW_VER_CODE(0, 29, 133, 0),
272 	 .fcxbtcrpt = 9, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
273 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 8,
274 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
275 	 .fwlrole = 7,   .frptmap = 105,  .fcxctrl = 7,  .fcxinit = 107,
276 	 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 103, .info_buf = 1800,
277 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 8,
278 	 .fcxtrx = 107,
279 	},
280 	{RTL8852B, RTW89_FW_VER_CODE(0, 29, 122, 0),
281 	 .fcxbtcrpt = 8, .fcxtdma = 7,    .fcxslots = 7, .fcxcysta = 7,
282 	 .fcxstep = 7,   .fcxnullsta = 7, .fcxmreg = 7,  .fcxgpiodbg = 7,
283 	 .fcxbtver = 7,  .fcxbtscan = 7,  .fcxbtafh = 7, .fcxbtdevinfo = 7,
284 	 .fwlrole = 7,   .frptmap = 3,    .fcxctrl = 7,  .fcxinit = 7,
285 	 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 1, .info_buf = 1800,
286 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 8,
287 	 .fcxtrx = 0,
288 	},
289 	{RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0),
290 	 .fcxbtcrpt = 105, .fcxtdma = 3,  .fcxslots = 1, .fcxcysta = 5,
291 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 2,  .fcxgpiodbg = 1,
292 	 .fcxbtver = 1,  .fcxbtscan = 2,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
293 	 .fwlrole = 2,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
294 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1800,
295 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
296 	 .fcxtrx = 0,
297 	},
298 	{RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0),
299 	 .fcxbtcrpt = 5, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 4,
300 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
301 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
302 	 .fwlrole = 1,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
303 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1800,
304 	 .max_role_num = 6, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
305 	 .fcxtrx = 0,
306 	},
307 	{RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0),
308 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
309 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
310 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
311 	 .fwlrole = 1,   .frptmap = 1,    .fcxctrl = 1,  .fcxinit = 0,
312 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280,
313 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
314 	 .fcxtrx = 0,
315 	},
316 	{RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0),
317 	 .fcxbtcrpt = 4, .fcxtdma = 3,    .fcxslots = 1, .fcxcysta = 3,
318 	 .fcxstep = 3,   .fcxnullsta = 2, .fcxmreg = 1,  .fcxgpiodbg = 1,
319 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 2, .fcxbtdevinfo = 1,
320 	 .fwlrole = 1,   .frptmap = 3,    .fcxctrl = 1,  .fcxinit = 0,
321 	 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_ver = 0, .info_buf = 1280,
322 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
323 	 .fcxtrx = 0,
324 	},
325 	{RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0),
326 	 .fcxbtcrpt = 1, .fcxtdma = 1,    .fcxslots = 1, .fcxcysta = 2,
327 	 .fcxstep = 2,   .fcxnullsta = 1, .fcxmreg = 1,  .fcxgpiodbg = 1,
328 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
329 	 .fwlrole = 0,   .frptmap = 0,    .fcxctrl = 0,  .fcxinit = 0,
330 	 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_ver = 0, .info_buf = 1024,
331 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
332 	 .fcxtrx = 0,
333 	},
334 
335 	/* keep it to be the last as default entry */
336 	{0, RTW89_FW_VER_CODE(0, 0, 0, 0),
337 	 .fcxbtcrpt = 1, .fcxtdma = 1,    .fcxslots = 1, .fcxcysta = 2,
338 	 .fcxstep = 2,   .fcxnullsta = 1, .fcxmreg = 1,  .fcxgpiodbg = 1,
339 	 .fcxbtver = 1,  .fcxbtscan = 1,  .fcxbtafh = 1, .fcxbtdevinfo = 1,
340 	 .fwlrole = 0,   .frptmap = 0,    .fcxctrl = 0,  .fcxinit = 0,
341 	 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1024,
342 	 .max_role_num = 5, .fcxosi = 0,  .fcxmlo = 0,   .bt_desired = 7,
343 	 .fcxtrx = 0,
344 	},
345 };
346 
347 #define RTW89_DEFAULT_BTC_VER_IDX (ARRAY_SIZE(rtw89_btc_ver_defs) - 1)
348 
349 static const union rtw89_btc_wl_state_map btc_scanning_map = {
350 	.map = {
351 		.scan = 1,
352 		.dhcp = 1,
353 		.roaming = 1,
354 		.transacting = 1,
355 		._4way = 1,
356 		.handshake = 1,
357 	},
358 };
359 
chip_id_to_bt_rom_code_id(u32 id)360 static u32 chip_id_to_bt_rom_code_id(u32 id)
361 {
362 	switch (id) {
363 	case RTL8852A:
364 	case RTL8852B:
365 	case RTL8852C:
366 	case RTL8852BT:
367 		return 0x8852;
368 	case RTL8851B:
369 		return 0x8851;
370 	case RTL8922A:
371 	case RTL8922D:
372 		return 0x8922;
373 	default:
374 		return 0;
375 	}
376 }
377 
378 #define CASE_BTC_MLME_STATE(e) case MLME_##e: return #e
379 
id_to_mlme_state(u32 id)380 static const char *id_to_mlme_state(u32 id)
381 {
382 	switch (id) {
383 	CASE_BTC_MLME_STATE(NO_LINK);
384 	CASE_BTC_MLME_STATE(LINKING);
385 	CASE_BTC_MLME_STATE(LINKED);
386 	default:
387 		return "unknown";
388 	}
389 }
390 
chip_id_str(u32 id)391 static char *chip_id_str(u32 id)
392 {
393 	switch (id) {
394 	case RTL8852A:
395 		return "RTL8852A";
396 	case RTL8852B:
397 		return "RTL8852B";
398 	case RTL8852C:
399 		return "RTL8852C";
400 	case RTL8852BT:
401 		return "RTL8852BT";
402 	case RTL8851B:
403 		return "RTL8851B";
404 	case RTL8922A:
405 		return "RTL8922A";
406 	case RTL8922D:
407 		return "RTL8922D";
408 	default:
409 		return "UNKNOWN";
410 	}
411 }
412 
413 struct rtw89_btc_btf_tlv {
414 	u8 type;
415 	u8 len;
416 	u8 val[];
417 } __packed;
418 
419 struct rtw89_btc_btf_tlv_v7 {
420 	u8 type;
421 	u8 ver;
422 	u8 len;
423 	u8 val[];
424 } __packed;
425 
426 enum btc_btf_set_report_en {
427 	RPT_EN_TDMA,
428 	RPT_EN_CYCLE,
429 	RPT_EN_MREG,
430 	RPT_EN_BT_VER_INFO,
431 	RPT_EN_BT_SCAN_INFO,
432 	RPT_EN_BT_DEVICE_INFO,
433 	RPT_EN_BT_AFH_MAP,
434 	RPT_EN_BT_AFH_MAP_LE,
435 	RPT_EN_BT_TX_PWR_LVL,
436 	RPT_EN_FW_STEP_INFO,
437 	RPT_EN_TEST,
438 	RPT_EN_WL_ALL,
439 	RPT_EN_BT_ALL,
440 	RPT_EN_ALL,
441 	RPT_EN_MONITER,
442 };
443 
444 struct rtw89_btc_btf_set_report_v1 {
445 	u8 fver;
446 	__le32 enable;
447 	__le32 para;
448 } __packed;
449 
450 struct rtw89_btc_btf_set_report_v8 {
451 	u8 type;
452 	u8 fver;
453 	u8 len;
454 	__le32 map;
455 } __packed;
456 
457 union rtw89_fbtc_rtp_ctrl {
458 	struct rtw89_btc_btf_set_report_v1 v1;
459 	struct rtw89_btc_btf_set_report_v8 v8;
460 };
461 
462 #define BTF_SET_SLOT_TABLE_VER 1
463 struct rtw89_btc_btf_set_slot_table {
464 	u8 fver;
465 	u8 tbl_num;
466 	struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num);
467 } __packed;
468 
469 struct rtw89_btc_btf_set_slot_table_v7 {
470 	u8 type;
471 	u8 ver;
472 	u8 len;
473 	struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX];
474 } __packed;
475 
476 struct rtw89_btc_btf_set_mon_reg_v1 {
477 	u8 fver;
478 	u8 reg_num;
479 	struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num);
480 } __packed;
481 
482 struct rtw89_btc_btf_set_mon_reg_v7 {
483 	u8 type;
484 	u8 fver;
485 	u8 len;
486 	struct rtw89_btc_fbtc_mreg regs[] __counted_by(len);
487 } __packed;
488 
489 union rtw89_fbtc_set_mon_reg {
490 	struct rtw89_btc_btf_set_mon_reg_v1 v1;
491 	struct rtw89_btc_btf_set_mon_reg_v7 v7;
492 } __packed;
493 
494 enum btc_btf_set_cx_policy {
495 	CXPOLICY_TDMA = 0x0,
496 	CXPOLICY_SLOT = 0x1,
497 	CXPOLICY_TYPE = 0x2,
498 	CXPOLICY_MAX,
499 };
500 
501 enum btc_b2w_scoreboard {
502 	BTC_BSCB_ACT = BIT(0),
503 	BTC_BSCB_ON = BIT(1),
504 	BTC_BSCB_WHQL = BIT(2),
505 	BTC_BSCB_BT_S1 = BIT(3),
506 	BTC_BSCB_A2DP_ACT = BIT(4),
507 	BTC_BSCB_RFK_RUN = BIT(5),
508 	BTC_BSCB_RFK_REQ = BIT(6),
509 	BTC_BSCB_LPS = BIT(7),
510 	BTC_BSCB_BT_LNAB0 = BIT(8),
511 	BTC_BSCB_BT_LNAB1 = BIT(10),
512 	BTC_BSCB_WLRFK = BIT(11),
513 	BTC_BSCB_BT_HILNA = BIT(13),
514 	BTC_BSCB_BT_HILNA_56G = BIT(14),
515 	BTC_BSCB_CTCODE = BIT(15),
516 	BTC_BSCB_BT_CONNECT = BIT(16),
517 	BTC_BSCB_BT_CONNECT_56G = BIT(17),
518 	BTC_BSCB_BT_LNAB0_56G = BIT(18),
519 	BTC_BSCB_BT_LNAB1_56G = BIT(19),
520 	BTC_BSCB_BT_15DOT4 = BIT(24),
521 	BTC_BSCB_BT_PROTECT = BIT(27),
522 	BTC_BSCB_PAN_ACT = BIT(28),
523 	BTC_BSCB_HFP_ACT = BIT(29),
524 	BTC_BSCB_PATCH_CODE = BIT(30),
525 	BTC_BSCB_ALL = GENMASK(30, 0),
526 };
527 
528 enum btc_phymap {
529 	BTC_PHY_0 = BIT(0),
530 	BTC_PHY_1 = BIT(1),
531 	BTC_PHY_ALL = BIT(0) | BIT(1),
532 };
533 
534 enum btc_cx_state_map {
535 	BTC_WIDLE = 0,
536 	BTC_WBUSY_BNOSCAN,
537 	BTC_WBUSY_BSCAN,
538 	BTC_WSCAN_BNOSCAN,
539 	BTC_WSCAN_BSCAN,
540 	BTC_WLINKING
541 };
542 
543 enum btc_ant_phase {
544 	BTC_ANT_WPOWERON = 0,
545 	BTC_ANT_WINIT,
546 	BTC_ANT_WONLY,
547 	BTC_ANT_WOFF,
548 	BTC_ANT_W2G,
549 	BTC_ANT_FDD,
550 	BTC_ANT_W25G,
551 	BTC_ANT_FREERUN,
552 	BTC_ANT_WRFK,
553 	BTC_ANT_WRFK2,
554 	BTC_ANT_PTA, /* for Multi-PTA, each hw-band has its own PTA */
555 	BTC_ANT_MAX
556 };
557 
558 enum btc_plt {
559 	BTC_PLT_NONE = 0,
560 	BTC_PLT_LTE_RX = BIT(0),
561 	BTC_PLT_GNT_BT_TX = BIT(1),
562 	BTC_PLT_GNT_BT_RX = BIT(2),
563 	BTC_PLT_GNT_WL = BIT(3),
564 	BTC_PLT_BT = BIT(1) | BIT(2),
565 	BTC_PLT_ALL = 0xf
566 };
567 
568 enum btc_cx_poicy_main_type {
569 	BTC_CXP_OFF = 0,
570 	BTC_CXP_OFFB,
571 	BTC_CXP_OFFE,
572 	BTC_CXP_FIX,
573 	BTC_CXP_PFIX,
574 	BTC_CXP_AUTO,
575 	BTC_CXP_PAUTO,
576 	BTC_CXP_AUTO2,
577 	BTC_CXP_PAUTO2,
578 	BTC_CXP_MANUAL,
579 	BTC_CXP_USERDEF0,
580 	BTC_CXP_MAIN_MAX
581 };
582 
583 enum btc_bslot_length {
584 	BTC_BSLOT_A2DP_HID = 60,
585 	BTC_BSLOT_A2DP = 50,
586 	BTC_BSLOT_A2DP_2 = 40,
587 	BTC_BSLOT_INQ = 30,
588 	BTC_BSLOT_IDLE = 20,
589 };
590 
591 enum btc_cx_poicy_type {
592 	/* TDMA off + pri: BT > WL */
593 	BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0,
594 
595 	/* TDMA off + pri: WL > BT */
596 	BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1,
597 
598 	/* TDMA off + pri: BT = WL */
599 	BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2,
600 
601 	/* TDMA off + pri: BT = WL > BT_Lo */
602 	BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3,
603 
604 	/* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */
605 	BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4,
606 
607 	/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
608 	BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5,
609 
610 	/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
611 	BTC_CXP_OFF_EQ4 = (BTC_CXP_OFF << 8) | 6,
612 
613 	/* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
614 	BTC_CXP_OFF_EQ5 = (BTC_CXP_OFF << 8) | 7,
615 
616 	/* TDMA off + pri: BT_Hi > WL > BT_Lo */
617 	BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 8,
618 
619 	/* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
620 	BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 9,
621 
622 	/* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
623 	BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 10,
624 
625 	/* TDMA off + pri: WL_Hi-Tx = BT */
626 	BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 11,
627 
628 	/* TDMA off + pri: WL > BT, Block-BT*/
629 	BTC_CXP_OFF_WL2 = (BTC_CXP_OFF << 8) | 12,
630 
631 	/* TDMA off+Bcn-Protect + pri: BT_Hi > WL > BT_Lo */
632 	BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
633 
634 	/* TDMA off+Bcn-Protect + pri: BT_Hi_Tx = WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
635 	BTC_CXP_OFFB_BWB1 = (BTC_CXP_OFFB << 8) | 1,
636 
637 	/* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
638 	BTC_CXP_OFFB_BWB2 = (BTC_CXP_OFFB << 8) | 2,
639 
640 	/* TDMA off+Bcn-Protect + pri: WL_Hi-Tx = BT*/
641 	BTC_CXP_OFFB_BWB3 = (BTC_CXP_OFFB << 8) | 3,
642 
643 	/* TDMA off+Bcn-Protect + pri: BT > WL*/
644 	BTC_CXP_OFFB_BWB4 = (BTC_CXP_OFFB << 8) | 4,
645 
646 	/* TDMA off + Ext-Ctrl + pri: default */
647 	BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0,
648 
649 	/* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
650 	BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1,
651 
652 	/* TDMA off + Ext-Ctrl + pri: default */
653 	BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2,
654 
655 	/* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
656 	BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3,
657 
658 	/* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */
659 	BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4,
660 
661 	/* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */
662 	BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5,
663 
664 	/* TDMA off + Ext-Ctrl + pri: default */
665 	BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6,
666 
667 	/* TDMA Fix slot-0: W1:B1 = 30:30 */
668 	BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0,
669 
670 	/* TDMA Fix slot-1: W1:B1 = 50:50 */
671 	BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1,
672 
673 	/* TDMA Fix slot-2: W1:B1 = 20:30 */
674 	BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2,
675 
676 	/* TDMA Fix slot-3: W1:B1 = 40:10 */
677 	BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3,
678 
679 	/* TDMA Fix slot-4: W1:B1 = 70:10 */
680 	BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4,
681 
682 	/* TDMA Fix slot-5: W1:B1 = 20:60 */
683 	BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5,
684 
685 	/* TDMA Fix slot-6: W1:B1 = 30:60 */
686 	BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6,
687 
688 	/* TDMA Fix slot-7: W1:B1 = 20:80 */
689 	BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7,
690 
691 	/* TDMA Fix slot-8: W1:B1 = user-define */
692 	BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8,
693 
694 	/* TDMA Fix slot-9: W1:B1 = 40:10 */
695 	BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 9,
696 
697 	/* TDMA Fix slot-10: W1:B1 = 40:10 */
698 	BTC_CXP_FIX_TD4010ISO_DL = (BTC_CXP_FIX << 8) | 10,
699 
700 	/* TDMA Fix slot-11: W1:B1 = 40:10 */
701 	BTC_CXP_FIX_TD4010ISO_UL = (BTC_CXP_FIX << 8) | 11,
702 
703 	/* PS-TDMA Fix slot-0: W1:B1 = 30:30 */
704 	BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0,
705 
706 	/* PS-TDMA Fix slot-1: W1:B1 = 50:50 */
707 	BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1,
708 
709 	/* PS-TDMA Fix slot-2: W1:B1 = 20:30 */
710 	BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2,
711 
712 	/* PS-TDMA Fix slot-3: W1:B1 = 20:60 */
713 	BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3,
714 
715 	/* PS-TDMA Fix slot-4: W1:B1 = 30:70 */
716 	BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4,
717 
718 	/* PS-TDMA Fix slot-5: W1:B1 = 20:80 */
719 	BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5,
720 
721 	/* PS-TDMA Fix slot-6: W1:B1 = user-define */
722 	BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6,
723 
724 	/* TDMA Auto slot-0: W1:B1 = 50:200 */
725 	BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0,
726 
727 	/* TDMA Auto slot-1: W1:B1 = 60:200 */
728 	BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1,
729 
730 	/* TDMA Auto slot-2: W1:B1 = 20:200 */
731 	BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2,
732 
733 	/* TDMA Auto slot-3: W1:B1 = user-define */
734 	BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3,
735 
736 	/* PS-TDMA Auto slot-0: W1:B1 = 50:200 */
737 	BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0,
738 
739 	/* PS-TDMA Auto slot-1: W1:B1 = 60:200 */
740 	BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1,
741 
742 	/* PS-TDMA Auto slot-2: W1:B1 = 20:200 */
743 	BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2,
744 
745 	/* PS-TDMA Auto slot-3: W1:B1 = user-define */
746 	BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3,
747 
748 	/* TDMA Auto slot2-0: W1:B4 = 30:50 */
749 	BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0,
750 
751 	/* TDMA Auto slot2-1: W1:B4 = 30:70 */
752 	BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1,
753 
754 	/* TDMA Auto slot2-2: W1:B4 = 50:50 */
755 	BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2,
756 
757 	/* TDMA Auto slot2-3: W1:B4 = 60:60 */
758 	BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3,
759 
760 	/* TDMA Auto slot2-4: W1:B4 = 20:80 */
761 	BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4,
762 
763 	/* TDMA Auto slot2-5: W1:B4 = user-define */
764 	BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5,
765 
766 	/* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */
767 	BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0,
768 
769 	/* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */
770 	BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1,
771 
772 	/* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */
773 	BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2,
774 
775 	/* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */
776 	BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3,
777 
778 	/* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */
779 	BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4,
780 
781 	/* PS-TDMA Auto slot2-5: W1:B4 = user-define */
782 	BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5,
783 
784 	BTC_CXP_MAX = 0xffff
785 };
786 
787 enum btc_wl_rfk_result {
788 	BTC_WRFK_REJECT = 0,
789 	BTC_WRFK_ALLOW = 1,
790 };
791 
792 enum btc_coex_info_map_en {
793 	BTC_COEX_INFO_CX = BIT(0),
794 	BTC_COEX_INFO_WL = BIT(1),
795 	BTC_COEX_INFO_BT = BIT(2),
796 	BTC_COEX_INFO_DM = BIT(3),
797 	BTC_COEX_INFO_MREG = BIT(4),
798 	BTC_COEX_INFO_SUMMARY = BIT(5),
799 	BTC_COEX_INFO_ALL = GENMASK(7, 0),
800 };
801 
802 #define BTC_CXP_MASK GENMASK(15, 8)
803 
804 enum btc_w2b_scoreboard {
805 	BTC_WSCB_ACTIVE = BIT(0),
806 	BTC_WSCB_ON = BIT(1),
807 	BTC_WSCB_SCAN = BIT(2),
808 	BTC_WSCB_UNDERTEST = BIT(3),
809 	BTC_WSCB_RXGAIN = BIT(4),
810 	BTC_WSCB_5GHICH = BIT(6),
811 	BTC_WSCB_WLBUSY = BIT(7),
812 	BTC_WSCB_EXTFEM = BIT(8),
813 	BTC_WSCB_TDMA = BIT(9),
814 	BTC_WSCB_FIX2M = BIT(10),
815 	BTC_WSCB_WLRFK = BIT(11),
816 	BTC_WSCB_RXSCAN_PRI = BIT(12),
817 	BTC_WSCB_BT_HILNA = BIT(13),
818 	BTC_WSCB_BTLOG = BIT(14),
819 	BTC_WSCB_CTCODE = BIT(15),
820 	BTC_WSCB_RXGAIN_56G = BIT(16),
821 	BTC_WSCB_BT_HILNA_56G = BIT(17),
822 	BTC_WSCB_ALL = GENMASK(23, 0),
823 };
824 
825 enum btc_wl_link_mode_v0 {
826 	BTC_WLINK_V0_NOLINK = 0x0,
827 	BTC_WLINK_V0_2G_STA,
828 	BTC_WLINK_V0_2G_AP,
829 	BTC_WLINK_V0_2G_GO,
830 	BTC_WLINK_V0_2G_GC,
831 	BTC_WLINK_V0_2G_SCC,
832 	BTC_WLINK_V0_2G_MCC,
833 	BTC_WLINK_V0_25G_MCC,
834 	BTC_WLINK_V0_25G_DBCC,
835 	BTC_WLINK_V0_5G,
836 	BTC_WLINK_V0_2G_NAN,
837 	BTC_WLINK_V0_OTHER,
838 	BTC_WLINK_V0_MAX
839 };
840 
841 enum btc_wl_link_mode_v1 {
842 	BTC_WLINK_NOLINK = 0x0,
843 	BTC_WLINK_STA,
844 	BTC_WLINK_AP,
845 	BTC_WLINK_GO,
846 	BTC_WLINK_GC,
847 	BTC_WLINK_SCC,
848 	BTC_WLINK_SB_MCC,
849 	BTC_WLINK_DB_MCC, /* 2+0/0+2 Dual-RF-band MCC */
850 	BTC_WLINK_MAX
851 };
852 
853 #define CASE_BTC_WL_LINK_MODE(e) case BTC_WLINK_## e: return #e
854 
id_to_linkmode(u8 id)855 static const char *id_to_linkmode(u8 id)
856 {
857 	switch (id) {
858 	CASE_BTC_WL_LINK_MODE(NOLINK);
859 	CASE_BTC_WL_LINK_MODE(STA);
860 	CASE_BTC_WL_LINK_MODE(AP);
861 	CASE_BTC_WL_LINK_MODE(GO);
862 	CASE_BTC_WL_LINK_MODE(GC);
863 	CASE_BTC_WL_LINK_MODE(SCC);
864 	CASE_BTC_WL_LINK_MODE(SB_MCC);
865 	CASE_BTC_WL_LINK_MODE(DB_MCC);
866 	default:
867 		return "unknown";
868 	}
869 }
870 
871 enum btc_wl_mrole_type {
872 	BTC_WLMROLE_NONE = 0x0,
873 	BTC_WLMROLE_STA_GC,
874 	BTC_WLMROLE_STA_GC_NOA,
875 	BTC_WLMROLE_STA_GO,
876 	BTC_WLMROLE_STA_GO_NOA,
877 	BTC_WLMROLE_STA_STA,
878 	BTC_WLMROLE_MAX
879 };
880 
881 enum btc_bt_hid_type {
882 	BTC_HID_218 = BIT(0),
883 	BTC_HID_418 = BIT(1),
884 	BTC_HID_BLE = BIT(2),
885 	BTC_HID_RCU = BIT(3),
886 	BTC_HID_RCU_VOICE = BIT(4),
887 	BTC_HID_OTHER_LEGACY = BIT(5)
888 };
889 
890 enum btc_reset_module {
891 	BTC_RESET_CX = BIT(0),
892 	BTC_RESET_DM = BIT(1),
893 	BTC_RESET_CTRL = BIT(2),
894 	BTC_RESET_CXDM = BIT(0) | BIT(1),
895 	BTC_RESET_BTINFO = BIT(3),
896 	BTC_RESET_MDINFO = BIT(4),
897 	BTC_RESET_BT_PSD_DM = BIT(5),
898 	BTC_RESET_BTINFO2 = BIT(6),
899 	BTC_RESET_ALL =  GENMASK(7, 0),
900 };
901 
902 enum btc_gnt_state {
903 	BTC_GNT_HW	= 0,
904 	BTC_GNT_SW_LO,
905 	BTC_GNT_SW_HI,
906 	BTC_GNT_MAX,
907 
908 	BTC_GNT_SET_SKIP = 0xff,
909 };
910 
911 enum btc_ctr_path {
912 	BTC_CTRL_BY_BT = 0,
913 	BTC_CTRL_BY_WL
914 };
915 
916 enum btc_wlact_state {
917 	BTC_WLACT_HW = 0,
918 	BTC_WLACT_SW_LO,
919 	BTC_WLACT_SW_HI,
920 	BTC_WLACT_MAX,
921 };
922 
923 enum btc_wl_max_tx_time {
924 	BTC_MAX_TX_TIME_L1 = 500,
925 	BTC_MAX_TX_TIME_L2 = 1000,
926 	BTC_MAX_TX_TIME_L3 = 2000,
927 	BTC_MAX_TX_TIME_DEF = 5280
928 };
929 
930 enum btc_wl_max_tx_retry {
931 	BTC_MAX_TX_RETRY_L1 = 7,
932 	BTC_MAX_TX_RETRY_L2 = 15,
933 	BTC_MAX_TX_RETRY_DEF = 31,
934 };
935 
936 enum btc_reason_and_action {
937 	BTC_RSN_NONE,
938 	BTC_RSN_NTFY_INIT,
939 	BTC_RSN_NTFY_SWBAND,
940 	BTC_RSN_NTFY_WL_STA,
941 	BTC_RSN_NTFY_RADIO_STATE,
942 	BTC_RSN_UPDATE_BT_SCBD,
943 	BTC_RSN_NTFY_WL_RFK,
944 	BTC_RSN_UPDATE_BT_INFO,
945 	BTC_RSN_NTFY_SCAN_START,
946 	BTC_RSN_NTFY_SCAN_FINISH,
947 	BTC_RSN_NTFY_SPECIFIC_PACKET,
948 	BTC_RSN_NTFY_POWEROFF,
949 	BTC_RSN_NTFY_ROLE_INFO,
950 	BTC_RSN_CMD_SET_COEX,
951 	BTC_RSN_ACT1_WORK,
952 	BTC_RSN_BT_DEVINFO_WORK,
953 	BTC_RSN_RFK_CHK_WORK,
954 	BTC_RSN_UPDATE_BT_LEAUDINFO,
955 	BTC_RSN_NUM,
956 	BTC_ACT_NONE = 100,
957 	BTC_ACT_WL_ONLY,
958 	BTC_ACT_WL_5G,
959 	BTC_ACT_WL_OTHER,
960 	BTC_ACT_WL_IDLE,
961 	BTC_ACT_WL_NC,
962 	BTC_ACT_WL_RFK,
963 	BTC_ACT_WL_INIT,
964 	BTC_ACT_WL_OFF,
965 	BTC_ACT_FREERUN,
966 	BTC_ACT_BT_WHQL,
967 	BTC_ACT_BT_RFK,
968 	BTC_ACT_BT_OFF,
969 	BTC_ACT_BT_IDLE,
970 	BTC_ACT_BT_HFP,
971 	BTC_ACT_BT_HID,
972 	BTC_ACT_BT_A2DP,
973 	BTC_ACT_BT_A2DPSINK,
974 	BTC_ACT_BT_PAN,
975 	BTC_ACT_BT_A2DP_HID,
976 	BTC_ACT_BT_A2DP_PAN,
977 	BTC_ACT_BT_PAN_HID,
978 	BTC_ACT_BT_A2DP_PAN_HID,
979 	BTC_ACT_BT_BIS,
980 	BTC_ACT_BT_CIS,
981 	BTC_ACT_WL_25G_MCC,
982 	BTC_ACT_WL_2G_MCC,
983 	BTC_ACT_WL_2G_SCC,
984 	BTC_ACT_WL_2G_AP,
985 	BTC_ACT_WL_2G_GO,
986 	BTC_ACT_WL_2G_GC,
987 	BTC_ACT_WL_2G_NAN,
988 	BTC_ACT_LAST,
989 	BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE,
990 	BTC_ACT_EXT_BIT = BIT(14),
991 	BTC_POLICY_EXT_BIT = BIT(15),
992 };
993 
994 #define BTC_FREERUN_ANTISO_MIN 30
995 #define BTC_TDMA_BTHID_MAX 2
996 #define BTC_BLINK_NOCONNECT 0
997 #define BTC_B1_MAX 250 /* unit ms */
998 
999 static void _run_coex(struct rtw89_dev *rtwdev,
1000 		      enum btc_reason_and_action reason);
1001 static void _write_scbd(struct rtw89_dev *rtwdev, u8 bid, u32 val, bool state);
1002 static u8 _sned_h2c_w2bscbd(struct rtw89_dev *rtwdev, bool force_exec, u8 bid);
1003 static void _update_bt_scbd(struct rtw89_dev *rtwdev, u8 bid);
1004 static const char *id_to_h2c(u32 id);
1005 
_reset_h2c_macro(struct rtw89_btc * btc)1006 static void _reset_h2c_macro(struct rtw89_btc *btc)
1007 {
1008 	btc->hbuf_len = 0;
1009 	btc->hbuf_cnt = 0;
1010 	memset(btc->hbuf, 0, BTC_H2C_MAXLEN);
1011 }
1012 
_send_fw_cmd(struct rtw89_dev * rtwdev,u8 h2c_class,u8 h2c_func,void * param,u16 len)1013 static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func,
1014 			void *param, u16 len)
1015 {
1016 	struct rtw89_btc *btc = &rtwdev->btc;
1017 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
1018 	struct rtw89_btc_cx *cx = &btc->cx;
1019 	struct rtw89_btc_wl_info *wl = &cx->wl;
1020 	struct rtw89_btc_dm *dm = &btc->dm;
1021 	u8 h2c_func_mask, bid = BTC_BT_1ST;
1022 	u8 *buf = param;
1023 	int ret;
1024 
1025 	if (len > BTC_H2C_MAXLEN || len == 0) {
1026 		btc->fwinfo.cnt_h2c_fail++;
1027 		dm->error.map.h2c_buffer_over = true;
1028 		return -EINVAL;
1029 	} else if (!wl->status.map.init_ok) {
1030 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
1031 			    "[BTC], %s(): return by btc not init!!\n", __func__);
1032 		pfwinfo->cnt_h2c_fail++;
1033 		return -EINVAL;
1034 	} else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF &&
1035 		    wl->status.map.rf_off == BTC_LPS_RF_OFF) ||
1036 		   (wl->status.map.lps_pre == BTC_LPS_RF_OFF &&
1037 		    wl->status.map.lps == BTC_LPS_RF_OFF)) {
1038 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
1039 			    "[BTC], %s(): return by wl off!!\n", __func__);
1040 		pfwinfo->cnt_h2c_fail++;
1041 		return -EINVAL;
1042 	}
1043 
1044 	h2c_func_mask = h2c_func & (~BT_H2C_FUNC_BT2ND);
1045 	if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)
1046 		bid = !!(h2c_func & BT_H2C_FUNC_BT2ND);
1047 
1048 	if (btc->io_oflld_type != BTC_IO_OFLD_BTC_H2C || btc->cli_h2c_cmd ||
1049 	    h2c_func_mask == SET_H2C_MACRO ||
1050 	    (h2c_func_mask == SET_DRV_INFO && buf[0] == CXDRVINFO_TRX) ||
1051 	    (h2c_func_mask == SET_IOFLD_SCBD && dm->scbd_write_instant) ||
1052 	    h2c_func_mask == SET_BT_LNA_CONSTRAIN) {
1053 		h2c_class = BTFC_SET;
1054 
1055 		ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func,
1056 						buf, len, false, true);
1057 
1058 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
1059 			    "[BTC], %s():class=%d, bt%d-func=%s, len=%d\n",
1060 			    __func__, h2c_class, bid,
1061 			    id_to_h2c(h2c_func_mask), len);
1062 
1063 		if (h2c_func_mask == SET_H2C_MACRO) {
1064 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
1065 				    "[BTC], %s():Send H2C-MACRO cnt=%d, len=%d\n",
1066 				    __func__, btc->hbuf_cnt, btc->hbuf_len);
1067 			_reset_h2c_macro(btc); /* clear H2C MACRO buffer */
1068 		}
1069 
1070 		if (ret != 0) { /* Send H2C fail */
1071 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
1072 				    "[BTC], %s():return by rtw_hal_mac_send_h2c\n",
1073 				    __func__);
1074 			btc->fwinfo.cnt_h2c_fail++;
1075 			return 0;
1076 		}
1077 
1078 		btc->fwinfo.cnt_h2c++;
1079 		return 0;
1080 	} else { /* Fill H2C MACRO buffer(TLV format) temporarily */
1081 		if (btc->hbuf_cnt == 0)
1082 			_reset_h2c_macro(btc);
1083 
1084 		/* Type:1 byte, Length:2 Bytes, Data:len bytes */
1085 		if (btc->hbuf_len + len + 3 >= BTC_H2C_MAXLEN) {
1086 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
1087 				    "[BTC], %s():return by MACRO buf full(%d)\n",
1088 				    __func__, btc->hbuf_len + len + 3);
1089 			btc->fwinfo.cnt_h2c_fail++;
1090 			return 0;
1091 		}
1092 
1093 		btc->hbuf[btc->hbuf_len] = h2c_func;
1094 		btc->hbuf[btc->hbuf_len + 1] = len & GENMASK(7, 0);
1095 		btc->hbuf[btc->hbuf_len + 2] = (len & GENMASK(15, 8)) >> 8;
1096 
1097 		memcpy(&btc->hbuf[btc->hbuf_len + 3], buf, len);
1098 		btc->hbuf_len = btc->hbuf_len + len + 3;
1099 		btc->hbuf_cnt++;
1100 
1101 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
1102 			    "[BTC], %s():Buffer H2C-MACRO cnt=%d/bt%d-func=%s/len=%d\n",
1103 			    __func__, btc->hbuf_cnt, bid,
1104 			    id_to_h2c(h2c_func_mask), len);
1105 	}
1106 
1107 	ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, buf, len,
1108 					false, true);
1109 	if (ret)
1110 		pfwinfo->cnt_h2c_fail++;
1111 	else
1112 		pfwinfo->cnt_h2c++;
1113 
1114 	return ret;
1115 }
1116 
1117 #define BTC_DEFAULT_SIR_THRES 51 /* dB, BT Pin - This = TDD/FDD swtch thres */
1118 #define BTC_FDDR_TP_SETUP_TIME 1 /* in second */
1119 #define BTC_FDDR_TP_HOLD_TIME 3 /* in second */
1120 #define BTC_FDDR_RX_LOW_RATE_THRES 4  /* low rate for TDD swotch */
1121 
_reset_btc_var(struct rtw89_dev * rtwdev,u8 type)1122 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
1123 {
1124 	struct rtw89_btc *btc = &rtwdev->btc;
1125 	struct rtw89_btc_cx *cx = &btc->cx;
1126 	const struct rtw89_btc_ver *ver = btc->ver;
1127 	struct rtw89_btc_bt_info *bt0 = &cx->bt0;
1128 	struct rtw89_btc_bt_info *bt1 = &cx->bt1;
1129 	u8 i;
1130 
1131 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
1132 
1133 	if (type & BTC_RESET_CX) {
1134 		memset(cx, 0, sizeof(*cx));
1135 		cx->bt_ext.max_tx_pwr = RTW89_BTC_BT_DEF_LE_TX_PWR;
1136 		cx->bt_ext.ant_iso_to_wl = RTW89_BTC_DEFAULT_ANISO;
1137 	}
1138 
1139 	if (type & BTC_RESET_BTINFO) {/* only for BT enable */
1140 		memset(bt0, 0, sizeof(*bt0));
1141 		bt0->link_info.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR;
1142 		bt0->link_info_56g.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR;
1143 		bt0->link_info.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR;
1144 		bt0->link_info_56g.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR;
1145 		bt0->ant_iso_to_wl = RTW89_BTC_DEFAULT_ANISO;
1146 	} else if (type & BTC_RESET_BTINFO2) {
1147 		memset(bt1, 0, sizeof(*bt1));
1148 		bt1->link_info.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR;
1149 		bt1->link_info_56g.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR;
1150 		bt1->link_info.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR;
1151 		bt1->link_info_56g.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR;
1152 		bt1->ant_iso_to_wl = RTW89_BTC_DEFAULT_ANISO;
1153 	}
1154 
1155 	if (type & BTC_RESET_CTRL) {
1156 		memset(&btc->ctrl, 0, sizeof(btc->ctrl));
1157 		btc->ctrl.trace_step = FCXDEF_STEP;
1158 	}
1159 
1160 	/* Init Coex variables that are not zero */
1161 	if (type & BTC_RESET_DM) {
1162 		memset(&btc->dm, 0, sizeof(btc->dm));
1163 
1164 		/* set the slot_now table to original */
1165 		btc->dm.tdma_now = t_def[CXTD_OFF];
1166 		btc->dm.tdma = t_def[CXTD_OFF];
1167 		if (ver->fcxslots >= 2) {
1168 			for (i = 0; i < ARRAY_SIZE(s_def); i++) {
1169 				btc->dm.slot.v7[i].dur = s_def[i].dur;
1170 				btc->dm.slot.v7[i].cxtype = s_def[i].cxtype;
1171 				btc->dm.slot.v7[i].cxtbl = s_def[i].cxtbl;
1172 			}
1173 			memcpy(&btc->dm.slot_now.v7, &btc->dm.slot.v7,
1174 			       sizeof(btc->dm.slot_now.v7));
1175 		} else {
1176 			memcpy(&btc->dm.slot_now.v1, s_def,
1177 			       sizeof(btc->dm.slot_now.v1));
1178 			memcpy(&btc->dm.slot.v1, s_def,
1179 			       sizeof(btc->dm.slot.v1));
1180 		}
1181 
1182 		btc->policy_len = 0;
1183 		btc->bt_req_len[RTW89_PHY_0] = 0;
1184 		btc->bt_req_len[RTW89_PHY_1] = 0;
1185 		btc->hubmsg_cnt = 0;
1186 
1187 		btc->dm.coex_info_map = BTC_COEX_INFO_ALL;
1188 		btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF;
1189 		btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF;
1190 		btc->dm.bt_slot_flood = BTC_B1_MAX;
1191 		btc->dm.sir_thres = BTC_DEFAULT_SIR_THRES;
1192 		btc->dm.fddr_info.tp_setup_time = BTC_FDDR_TP_SETUP_TIME;
1193 		btc->dm.fddr_info.tp_hold_time = BTC_FDDR_TP_HOLD_TIME;
1194 		btc->dm.fddr_info.wl_rx_rate_thres = BTC_FDDR_RX_LOW_RATE_THRES;
1195 		btc->dm.fddt_info.type = BTC_FDDT_TYPE_AUTO;
1196 
1197 		btc->dm.wl_pre_agc_rb = BTC_PREAGC_NOTFOUND;
1198 		btc->dm.wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_NOTFOUND;
1199 	}
1200 
1201 	if (type & BTC_RESET_MDINFO) {
1202 		memset(&btc->mdinfo, 0, sizeof(btc->mdinfo));
1203 		btc->mdinfo.ant.isolation = RTW89_BTC_DEFAULT_ANISO;
1204 	}
1205 }
1206 
_search_reg_index(struct rtw89_dev * rtwdev,u8 mreg_num,u16 reg_type,u32 target)1207 static u8 _search_reg_index(struct rtw89_dev *rtwdev, u8 mreg_num, u16 reg_type, u32 target)
1208 {
1209 	const struct rtw89_chip_info *chip = rtwdev->chip;
1210 	u8 i;
1211 
1212 	for (i = 0; i < mreg_num; i++)
1213 		if (le16_to_cpu(chip->mon_reg[i].type) == reg_type &&
1214 		    le32_to_cpu(chip->mon_reg[i].offset) == target) {
1215 			return i;
1216 	}
1217 	return BTC_REG_NOTFOUND;
1218 }
1219 
_get_reg_status(struct rtw89_dev * rtwdev,u8 type,u8 * val)1220 static void _get_reg_status(struct rtw89_dev *rtwdev, u8 type, u8 *val)
1221 {
1222 	struct rtw89_btc *btc = &rtwdev->btc;
1223 	const struct rtw89_btc_ver *ver = btc->ver;
1224 	struct rtw89_btc_module *md = &btc->mdinfo;
1225 	union rtw89_btc_fbtc_mreg_val *pmreg;
1226 	u32 pre_agc_addr = R_BTC_BB_PRE_AGC_S1;
1227 	u32 reg_val;
1228 	u8 idx;
1229 
1230 	if (btc->btg_pos == RF_PATH_A)
1231 		pre_agc_addr = R_BTC_BB_PRE_AGC_S0;
1232 
1233 	switch (type) {
1234 	case BTC_CSTATUS_TXDIV_POS:
1235 		if (md->bt0_sw_type == BTC_SWITCH_INTERNAL)
1236 			*val = BTC_ANT_DIV_MAIN;
1237 		break;
1238 	case BTC_CSTATUS_RXDIV_POS:
1239 		if (md->bt0_sw_type == BTC_SWITCH_INTERNAL)
1240 			*val = BTC_ANT_DIV_MAIN;
1241 		break;
1242 	case BTC_CSTATUS_BB_GNT_MUX:
1243 		reg_val = rtw89_phy_read32(rtwdev, R_BTC_BB_BTG_RX);
1244 		*val = !(reg_val & B_BTC_BB_GNT_MUX);
1245 		break;
1246 	case BTC_CSTATUS_BB_GNT_MUX_MON:
1247 		if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
1248 			return;
1249 
1250 		pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
1251 		if (ver->fcxmreg == 1) {
1252 			idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
1253 						REG_BB, R_BTC_BB_BTG_RX);
1254 			if (idx == BTC_REG_NOTFOUND) {
1255 				*val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
1256 			} else {
1257 				reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]);
1258 				*val = !(reg_val & B_BTC_BB_GNT_MUX);
1259 			}
1260 		} else if (ver->fcxmreg == 2) {
1261 			idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
1262 						REG_BB, R_BTC_BB_BTG_RX);
1263 			if (idx == BTC_REG_NOTFOUND) {
1264 				*val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
1265 			} else {
1266 				reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]);
1267 				*val = !(reg_val & B_BTC_BB_GNT_MUX);
1268 			}
1269 		}
1270 		break;
1271 	case BTC_CSTATUS_BB_PRE_AGC:
1272 		reg_val = rtw89_phy_read32(rtwdev, pre_agc_addr);
1273 		reg_val &= B_BTC_BB_PRE_AGC_MASK;
1274 		*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1275 		break;
1276 	case BTC_CSTATUS_BB_PRE_AGC_MON:
1277 		if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
1278 			return;
1279 
1280 		pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
1281 		if (ver->fcxmreg == 1) {
1282 			idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
1283 						REG_BB, pre_agc_addr);
1284 			if (idx == BTC_REG_NOTFOUND) {
1285 				*val = BTC_PREAGC_NOTFOUND;
1286 			} else {
1287 				reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]) &
1288 					  B_BTC_BB_PRE_AGC_MASK;
1289 				*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1290 			}
1291 		} else if (ver->fcxmreg == 2) {
1292 			idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
1293 						REG_BB, pre_agc_addr);
1294 			if (idx == BTC_REG_NOTFOUND) {
1295 				*val = BTC_PREAGC_NOTFOUND;
1296 			} else {
1297 				reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]) &
1298 					  B_BTC_BB_PRE_AGC_MASK;
1299 				*val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1300 			}
1301 		}
1302 		break;
1303 	default:
1304 		break;
1305 	}
1306 }
1307 
1308 #define BTC_RPT_HDR_SIZE 3
1309 #define BTC_CHK_WLSLOT_DRIFT_MAX 15
1310 #define BTC_CHK_BTSLOT_DRIFT_MAX 15
1311 #define BTC_CHK_HANG_MAX 3
1312 
_chk_btc_err(struct rtw89_dev * rtwdev,u8 type,u32 cnt)1313 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt)
1314 {
1315 	struct rtw89_btc *btc = &rtwdev->btc;
1316 	struct rtw89_btc_cx *cx = &btc->cx;
1317 	struct rtw89_btc_bt_info *bt = &cx->bt0;
1318 	struct rtw89_btc_wl_info *wl = &cx->wl;
1319 	struct rtw89_btc_dm *dm = &btc->dm;
1320 
1321 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
1322 		    "[BTC], %s(): type:%d cnt:%d\n",
1323 		    __func__, type, cnt);
1324 
1325 	switch (type) {
1326 	case BTC_DCNT_WL_FW_VER_MATCH:
1327 		if ((wl->ver_info.fw_coex & 0xffff0000) !=
1328 		     rtwdev->chip->wlcx_desired) {
1329 			wl->fw_ver_mismatch = true;
1330 			dm->error.map.wl_ver_mismatch = true;
1331 		} else {
1332 			wl->fw_ver_mismatch = false;
1333 			dm->error.map.wl_ver_mismatch = false;
1334 		}
1335 		break;
1336 	case BTC_DCNT_RPT_HANG:
1337 		if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map)
1338 			dm->cnt_dm[BTC_DCNT_RPT_HANG]++;
1339 		else
1340 			dm->cnt_dm[BTC_DCNT_RPT_HANG] = 0;
1341 
1342 		if (dm->cnt_dm[BTC_DCNT_RPT_HANG] >= BTC_CHK_HANG_MAX)
1343 			dm->error.map.wl_fw_hang = true;
1344 		else
1345 			dm->error.map.wl_fw_hang = false;
1346 
1347 		dm->cnt_dm[BTC_DCNT_RPT] = cnt;
1348 		break;
1349 	case BTC_DCNT_CYCLE_HANG:
1350 		if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt &&
1351 		    (dm->tdma_now.type != CXTDMA_OFF ||
1352 		     dm->tdma_now.ext_ctrl == CXECTL_EXT))
1353 			dm->cnt_dm[BTC_DCNT_CYCLE_HANG]++;
1354 		else
1355 			dm->cnt_dm[BTC_DCNT_CYCLE_HANG] = 0;
1356 
1357 		if (dm->cnt_dm[BTC_DCNT_CYCLE_HANG] >= BTC_CHK_HANG_MAX)
1358 			dm->error.map.cycle_hang = true;
1359 		else
1360 			dm->error.map.cycle_hang = false;
1361 
1362 		dm->cnt_dm[BTC_DCNT_CYCLE] = cnt;
1363 		break;
1364 	case BTC_DCNT_W1_HANG:
1365 		if (dm->cnt_dm[BTC_DCNT_W1] == cnt &&
1366 		    dm->tdma_now.type != CXTDMA_OFF)
1367 			dm->cnt_dm[BTC_DCNT_W1_HANG]++;
1368 		else
1369 			dm->cnt_dm[BTC_DCNT_W1_HANG] = 0;
1370 
1371 		if (dm->cnt_dm[BTC_DCNT_W1_HANG] >= BTC_CHK_HANG_MAX)
1372 			dm->error.map.w1_hang = true;
1373 		else
1374 			dm->error.map.w1_hang = false;
1375 
1376 		dm->cnt_dm[BTC_DCNT_W1] = cnt;
1377 		break;
1378 	case BTC_DCNT_B1_HANG:
1379 		if (dm->cnt_dm[BTC_DCNT_B1] == cnt &&
1380 		    dm->tdma_now.type != CXTDMA_OFF)
1381 			dm->cnt_dm[BTC_DCNT_B1_HANG]++;
1382 		else
1383 			dm->cnt_dm[BTC_DCNT_B1_HANG] = 0;
1384 
1385 		if (dm->cnt_dm[BTC_DCNT_B1_HANG] >= BTC_CHK_HANG_MAX)
1386 			dm->error.map.b1_hang = true;
1387 		else
1388 			dm->error.map.b1_hang = false;
1389 
1390 		dm->cnt_dm[BTC_DCNT_B1] = cnt;
1391 		break;
1392 	case BTC_DCNT_E2G_HANG:
1393 		if (dm->cnt_dm[BTC_DCNT_E2G] == cnt &&
1394 		    dm->tdma_now.ext_ctrl == CXECTL_EXT)
1395 			dm->cnt_dm[BTC_DCNT_E2G_HANG]++;
1396 		else
1397 			dm->cnt_dm[BTC_DCNT_E2G_HANG] = 0;
1398 
1399 		if (dm->cnt_dm[BTC_DCNT_E2G_HANG] >= BTC_CHK_HANG_MAX)
1400 			dm->error.map.wl_e2g_hang = true;
1401 		else
1402 			dm->error.map.wl_e2g_hang = false;
1403 
1404 		dm->cnt_dm[BTC_DCNT_E2G] = cnt;
1405 		break;
1406 	case BTC_DCNT_TDMA_NONSYNC:
1407 		if (cnt != 0) /* if tdma not sync between drv/fw  */
1408 			dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++;
1409 		else
1410 			dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0;
1411 
1412 		if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX)
1413 			dm->error.map.tdma_no_sync = true;
1414 		else
1415 			dm->error.map.tdma_no_sync = false;
1416 		break;
1417 	case BTC_DCNT_SLOT_NONSYNC:
1418 		if (cnt != 0) /* if slot not sync between drv/fw  */
1419 			dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++;
1420 		else
1421 			dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0;
1422 
1423 		if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX)
1424 			dm->error.map.slot_no_sync = true;
1425 		else
1426 			dm->error.map.slot_no_sync = false;
1427 		break;
1428 	case BTC_DCNT_BTTX_HANG:
1429 		cnt = bt->bcnt[BTC_BCNT_LOPRI_TX];
1430 
1431 		if (cnt == 0 && bt->link_info.slave_role)
1432 			dm->cnt_dm[BTC_DCNT_BTTX_HANG]++;
1433 		else
1434 			dm->cnt_dm[BTC_DCNT_BTTX_HANG] = 0;
1435 
1436 		if (dm->cnt_dm[BTC_DCNT_BTTX_HANG] >= BTC_CHK_HANG_MAX)
1437 			dm->error.map.bt_tx_hang = true;
1438 		else
1439 			dm->error.map.bt_tx_hang = false;
1440 		break;
1441 	case BTC_DCNT_BTCNT_HANG:
1442 		cnt = bt->bcnt[BTC_BCNT_HIPRI_RX] +
1443 		      bt->bcnt[BTC_BCNT_HIPRI_TX] +
1444 		      bt->bcnt[BTC_BCNT_LOPRI_RX] +
1445 		      bt->bcnt[BTC_BCNT_LOPRI_TX];
1446 
1447 		if (cnt == 0)
1448 			dm->cnt_dm[BTC_DCNT_BTCNT_HANG]++;
1449 		else
1450 			dm->cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
1451 		break;
1452 	case BTC_DCNT_WL_SLOT_DRIFT:
1453 		if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX)
1454 			dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++;
1455 		else
1456 			dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0;
1457 
1458 		if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1459 			dm->error.map.wl_slot_drift = true;
1460 		else
1461 			dm->error.map.wl_slot_drift = false;
1462 		break;
1463 	case BTC_DCNT_BT_SLOT_DRIFT:
1464 		if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX)
1465 			dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++;
1466 		else
1467 			dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0;
1468 
1469 		if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1470 			dm->error.map.bt_slot_drift = true;
1471 		else
1472 			dm->error.map.bt_slot_drift = false;
1473 
1474 		break;
1475 	case BTC_DCNT_WL_STA_NTFY:
1476 		cnt = dm->cnt_notify[BTC_NCNT_WL_STA] -
1477 		      dm->cnt_notify[BTC_NCNT_WL_STA_LAST];
1478 
1479 		dm->cnt_notify[BTC_NCNT_WL_STA_LAST] =
1480 			dm->cnt_notify[BTC_NCNT_WL_STA];
1481 
1482 		if (cnt == 0 &&
1483 		    (dm->tdd_bind.wl_link_mode != BTC_WLINK_NOLINK ||
1484 		     dm->fdd_bind.wl_link_mode != BTC_WLINK_NOLINK))
1485 			dm->cnt_dm[BTC_DCNT_WL_STA_NTFY]++;
1486 		else
1487 			dm->cnt_dm[BTC_DCNT_WL_STA_NTFY] = 0;
1488 
1489 		if (dm->cnt_dm[BTC_DCNT_WL_STA_NTFY] >= BTC_CHK_HANG_MAX)
1490 			dm->error.map.wl_no_sta_ntfy = true;
1491 		else
1492 			dm->error.map.wl_no_sta_ntfy = false;
1493 		break;
1494 	case BTC_DCNT_W2B_SCBD_NOSYNC:
1495 		if (!(rtwdev->chip->para_ver & BTC_FEAT_MULTI_PTA))
1496 			return; /* return if no-support W2B scbd readback */
1497 
1498 		if (wl->scbd_rb[BTC_BT_1ST] != wl->scbd[BTC_BT_1ST] ||
1499 		    wl->scbd_rb[BTC_BT_2ND] != wl->scbd[BTC_BT_2ND])
1500 			dm->cnt_dm[BTC_DCNT_W2B_SCBD_NOSYNC]++;
1501 		else
1502 			dm->cnt_dm[BTC_DCNT_W2B_SCBD_NOSYNC] = 0;
1503 
1504 		if (dm->cnt_dm[BTC_DCNT_W2B_SCBD_NOSYNC] >= BTC_CHK_HANG_MAX)
1505 			dm->error.map.w2b_scbd_no_sync = true;
1506 		else
1507 			dm->error.map.w2b_scbd_no_sync = false;
1508 		break;
1509 	}
1510 }
1511 
_update_bt_report(struct rtw89_dev * rtwdev,u8 rpt_type,u8 * pfinfo)1512 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo)
1513 {
1514 	struct rtw89_btc *btc = &rtwdev->btc;
1515 	const struct rtw89_btc_ver *ver = btc->ver;
1516 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
1517 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
1518 	struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc;
1519 	union  rtw89_btc_fbtc_btver *pver = &btc->fwinfo.rpt_fbtc_btver.finfo;
1520 	struct rtw89_btc_fbtc_btafh_v2 *pafh_v2 = NULL;
1521 	struct rtw89_btc_fbtc_btafh_v7 *pafh_v7 = NULL;
1522 	struct rtw89_btc_fbtc_btdevinfo *pdev = NULL;
1523 	struct rtw89_btc_fbtc_btafh *pafh_v1 = NULL;
1524 	struct rtw89_btc_fbtc_btscan_v1 *pscan_v1;
1525 	struct rtw89_btc_fbtc_btscan_v2 *pscan_v2;
1526 	struct rtw89_btc_fbtc_btscan_v7 *pscan_v7;
1527 	bool scan_update = true;
1528 	int i;
1529 
1530 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
1531 		    "[BTC], %s(): rpt_type:%d\n",
1532 		    __func__, rpt_type);
1533 
1534 	switch (rpt_type) {
1535 	case BTC_RPT_TYPE_BT_VER:
1536 		if (ver->fcxbtver == 8) {
1537 			pver->v8 = *(struct rtw89_btc_fbtc_btver_v8 *)pfinfo;
1538 			bt = pver->v8.bt_id ? &btc->cx.bt1 : &btc->cx.bt0;
1539 			bt->ver_info.fw = le32_to_cpu(pver->v8.fw_ver);
1540 			bt->ver_info.fw_coex = le32_get_bits(pver->v8.coex_ver,
1541 							     GENMASK(7, 0));
1542 			bt->feature = le32_to_cpu(pver->v8.feature);
1543 		} else if (ver->fcxbtver == 7) {
1544 			pver->v7 = *(struct rtw89_btc_fbtc_btver_v7 *)pfinfo;
1545 			bt->ver_info.fw = le32_to_cpu(pver->v7.fw_ver);
1546 			bt->ver_info.fw_coex = le32_get_bits(pver->v7.coex_ver,
1547 							     GENMASK(7, 0));
1548 			bt->feature = le32_to_cpu(pver->v7.feature);
1549 		} else {
1550 			pver->v1 = *(struct rtw89_btc_fbtc_btver_v1 *)pfinfo;
1551 			bt->ver_info.fw = le32_to_cpu(pver->v1.fw_ver);
1552 			bt->ver_info.fw_coex = le32_get_bits(pver->v1.coex_ver,
1553 							     GENMASK(7, 0));
1554 			bt->feature = le32_to_cpu(pver->v1.feature);
1555 		}
1556 		break;
1557 	case BTC_RPT_TYPE_BT_SCAN:
1558 		if (ver->fcxbtscan == 1) {
1559 			pscan_v1 = (struct rtw89_btc_fbtc_btscan_v1 *)pfinfo;
1560 			for (i = 0; i < BTC_SCAN_MAX1; i++) {
1561 				bt->scan_info_v1[i] = pscan_v1->scan[i];
1562 				if (bt->scan_info_v1[i].win == 0 &&
1563 				    bt->scan_info_v1[i].intvl == 0)
1564 					scan_update = false;
1565 			}
1566 		} else if (ver->fcxbtscan == 2) {
1567 			pscan_v2 = (struct rtw89_btc_fbtc_btscan_v2 *)pfinfo;
1568 			for (i = 0; i < CXSCAN_MAX; i++) {
1569 				bt->scan_info_v2[i] = pscan_v2->para[i];
1570 				if ((pscan_v2->type & BIT(i)) &&
1571 				    pscan_v2->para[i].win == 0 &&
1572 				    pscan_v2->para[i].intvl == 0)
1573 					scan_update = false;
1574 			}
1575 		} else if (ver->fcxbtscan == 7) {
1576 			pscan_v7 = (struct rtw89_btc_fbtc_btscan_v7 *)pfinfo;
1577 			for (i = 0; i < CXSCAN_MAX; i++) {
1578 				bt->scan_info_v2[i] = pscan_v7->para[i];
1579 				if ((pscan_v7->type & BIT(i)) &&
1580 				    pscan_v7->para[i].win == 0 &&
1581 				    pscan_v7->para[i].intvl == 0)
1582 					scan_update = false;
1583 			}
1584 		} else if (ver->fcxbtscan == 8) {
1585 			struct rtw89_btc_fbtc_btscan_v8 *pscan_v8 =
1586 				(struct rtw89_btc_fbtc_btscan_v8 *)pfinfo;
1587 			struct rtw89_btc_bt_info *tbt =
1588 				pscan_v8->bt_id ? &btc->cx.bt1 : &btc->cx.bt0;
1589 
1590 			for (i = 0; i < CXSCAN_MAX; i++) {
1591 				tbt->scan_info_v2[i] = pscan_v8->para[i];
1592 				if ((pscan_v8->type & BIT(i)) &&
1593 				    pscan_v8->para[i].win == 0 &&
1594 				    pscan_v8->para[i].intvl == 0)
1595 					scan_update = false;
1596 			}
1597 		}
1598 		if (scan_update)
1599 			bt->scan_info_update = 1;
1600 		break;
1601 	case BTC_RPT_TYPE_BT_AFH:
1602 		if (ver->fcxbtafh == 2) {
1603 			pafh_v2 = (struct rtw89_btc_fbtc_btafh_v2 *)pfinfo;
1604 			if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1605 				memcpy(&bt_linfo->afh_map[0], pafh_v2->afh_l, 4);
1606 				memcpy(&bt_linfo->afh_map[4], pafh_v2->afh_m, 4);
1607 				memcpy(&bt_linfo->afh_map[8], pafh_v2->afh_h, 2);
1608 			}
1609 			if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LE) {
1610 				memcpy(&bt_linfo->afh_map_le[0], pafh_v2->afh_le_a, 4);
1611 				memcpy(&bt_linfo->afh_map_le[4], pafh_v2->afh_le_b, 1);
1612 			}
1613 		} else if (ver->fcxbtafh == 7) {
1614 			pafh_v7 = (struct rtw89_btc_fbtc_btafh_v7 *)pfinfo;
1615 			if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1616 				memcpy(&bt_linfo->afh_map[0], pafh_v7->afh_l, 4);
1617 				memcpy(&bt_linfo->afh_map[4], pafh_v7->afh_m, 4);
1618 				memcpy(&bt_linfo->afh_map[8], pafh_v7->afh_h, 2);
1619 			}
1620 			if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LE) {
1621 				memcpy(&bt_linfo->afh_map_le[0], pafh_v7->afh_le_a, 4);
1622 				memcpy(&bt_linfo->afh_map_le[4], pafh_v7->afh_le_b, 1);
1623 			}
1624 		} else if (ver->fcxbtafh == 8) {
1625 			struct rtw89_btc_fbtc_btafh_v8 *pafh_v8 =
1626 				(struct rtw89_btc_fbtc_btafh_v8 *)pfinfo;
1627 			struct rtw89_btc_bt_info *tbt =
1628 				pafh_v8->bt_id ? &btc->cx.bt1 : &btc->cx.bt0;
1629 			struct rtw89_btc_bt_link_info *tbt_linfo = &tbt->link_info;
1630 
1631 			if (pafh_v8->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1632 				memcpy(&tbt_linfo->afh_map[0], pafh_v8->afh_l, 4);
1633 				memcpy(&tbt_linfo->afh_map[4], pafh_v8->afh_m, 4);
1634 				memcpy(&tbt_linfo->afh_map[8], pafh_v8->afh_h, 2);
1635 			}
1636 			if (pafh_v8->map_type & RPT_BT_AFH_SEQ_LE) {
1637 				memcpy(&tbt_linfo->afh_map_le[0], pafh_v8->afh_le_a, 4);
1638 				memcpy(&tbt_linfo->afh_map_le[4], pafh_v8->afh_le_b, 1);
1639 			}
1640 		} else if (ver->fcxbtafh == 1) {
1641 			pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo;
1642 			memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4);
1643 			memcpy(&bt_linfo->afh_map[4], pafh_v1->afh_m, 4);
1644 			memcpy(&bt_linfo->afh_map[8], pafh_v1->afh_h, 2);
1645 		}
1646 		break;
1647 	case BTC_RPT_TYPE_BT_DEVICE:
1648 		pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo;
1649 		a2dp->device_name = le32_to_cpu(pdev->dev_name);
1650 		a2dp->vendor_id = le16_to_cpu(pdev->vendor_id);
1651 		a2dp->flush_time = le32_to_cpu(pdev->flush_time);
1652 		break;
1653 	default:
1654 		break;
1655 	}
1656 }
1657 
rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev * rtwdev,u8 * index)1658 static void rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev *rtwdev, u8 *index)
1659 {
1660 	struct rtw89_btc *btc = &rtwdev->btc;
1661 	const struct rtw89_btc_ver *ver = btc->ver;
1662 
1663 	if (ver->fwevntrptl == 1)
1664 		return;
1665 
1666 	if (*index <= __BTC_RPT_TYPE_V0_SAME)
1667 		return;
1668 	else if (*index <= __BTC_RPT_TYPE_V0_MAX)
1669 		(*index)++;
1670 	else
1671 		*index = BTC_RPT_TYPE_MAX;
1672 }
1673 
1674 #define BTC_LEAK_AP_TH 10
1675 #define BTC_CYSTA_CHK_PERIOD 100
1676 
1677 struct rtw89_btc_prpt {
1678 	u8 type;
1679 	__le16 len;
1680 	u8 content[];
1681 } __packed;
1682 
_chk_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * prptbuf,u32 index)1683 static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
1684 			   struct rtw89_btc_btf_fwinfo *pfwinfo,
1685 			   u8 *prptbuf, u32 index)
1686 {
1687 	struct rtw89_btc *btc = &rtwdev->btc;
1688 	struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver;
1689 	const struct rtw89_btc_ver *ver = btc->ver;
1690 	struct rtw89_btc_dm *dm = &btc->dm;
1691 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
1692 	struct rtw89_btc_cx *cx = &btc->cx;
1693 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1694 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
1695 	union rtw89_btc_fbtc_rpt_ctrl_ver_info *prpt = NULL;
1696 	union rtw89_btc_fbtc_cysta_info *pcysta = NULL;
1697 	struct rtw89_btc_prpt *btc_prpt = NULL;
1698 	void *rpt_content = NULL, *pfinfo = NULL;
1699 	u8 rpt_type = 0;
1700 	u16 wl_slot_set = 0, wl_slot_real = 0, val16;
1701 	u32 trace_step = 0, rpt_len = 0, diff_t = 0;
1702 	u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr;
1703 	u8 i, j, val = 0, val1, val2;
1704 	u32 *bt_cnt, start_idx;
1705 
1706 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
1707 		    "[BTC], %s(): index:%d\n",
1708 		    __func__, index);
1709 
1710 	if (!prptbuf) {
1711 		pfwinfo->err[BTFRE_INVALID_INPUT]++;
1712 		return 0;
1713 	}
1714 
1715 	btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index];
1716 	rpt_type = btc_prpt->type;
1717 	rpt_len = le16_to_cpu(btc_prpt->len);
1718 	rpt_content = btc_prpt->content;
1719 
1720 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
1721 		    "[BTC], %s(): rpt_type:%d\n",
1722 		    __func__, rpt_type);
1723 
1724 	rtw89_btc_fw_rpt_evnt_ver(rtwdev, &rpt_type);
1725 
1726 	switch (rpt_type) {
1727 	case BTC_RPT_TYPE_CTRL:
1728 		pcinfo = &pfwinfo->rpt_ctrl.cinfo;
1729 		prpt = &pfwinfo->rpt_ctrl.finfo;
1730 		if (ver->fcxbtcrpt == 1) {
1731 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v1;
1732 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v1);
1733 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v1.fver;
1734 		} else if (ver->fcxbtcrpt == 4) {
1735 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v4;
1736 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v4);
1737 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v4.fver;
1738 		} else if (ver->fcxbtcrpt == 5) {
1739 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v5;
1740 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v5);
1741 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v5.fver;
1742 		} else if (ver->fcxbtcrpt == 105) {
1743 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v105;
1744 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v105);
1745 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v105.fver;
1746 			pcinfo->req_fver = 5;
1747 			break;
1748 		} else if (ver->fcxbtcrpt == 8) {
1749 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v8;
1750 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8);
1751 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v8.fver;
1752 		} else if (ver->fcxbtcrpt == 7) {
1753 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v7;
1754 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v7);
1755 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v7.fver;
1756 		} else if (ver->fcxbtcrpt == 9) {
1757 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v9;
1758 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v9);
1759 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v9.fver;
1760 		} else if (ver->fcxbtcrpt == 11) {
1761 			pfinfo = &pfwinfo->rpt_ctrl.finfo.v11;
1762 			pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v11);
1763 			fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v11.fver;
1764 		} else {
1765 			goto err;
1766 		}
1767 		pcinfo->req_fver = ver->fcxbtcrpt;
1768 		break;
1769 	case BTC_RPT_TYPE_TDMA:
1770 		pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
1771 		if (ver->fcxtdma == 1) {
1772 			pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
1773 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1);
1774 			fwsubver->fcxtdma = 0;
1775 		} else if (ver->fcxtdma == 3 || ver->fcxtdma == 4 ||
1776 			   ver->fcxtdma == 7 || ver->fcxtdma == 8) {
1777 			pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3;
1778 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3);
1779 			fwsubver->fcxtdma = pfwinfo->rpt_fbtc_tdma.finfo.v3.fver;
1780 		} else {
1781 			goto err;
1782 		}
1783 		pcinfo->req_fver = ver->fcxtdma;
1784 		break;
1785 	case BTC_RPT_TYPE_SLOT:
1786 		pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
1787 		if (ver->fcxslots == 1) {
1788 			pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1;
1789 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v1);
1790 			fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v1.fver;
1791 		} else if (ver->fcxslots == 2) {
1792 			pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v2;
1793 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v2);
1794 			fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v2.fver;
1795 		} else if (ver->fcxslots == 7) {
1796 			pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7;
1797 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v7);
1798 			fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v7.fver;
1799 		} else {
1800 			goto err;
1801 		}
1802 		pcinfo->req_fver = ver->fcxslots;
1803 		break;
1804 	case BTC_RPT_TYPE_CYSTA:
1805 		pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
1806 		pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
1807 		if (ver->fcxcysta == 2) {
1808 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
1809 			pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
1810 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v2);
1811 			fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v2.fver;
1812 		} else if (ver->fcxcysta == 3) {
1813 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
1814 			pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
1815 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v3);
1816 			fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v3.fver;
1817 		} else if (ver->fcxcysta == 4) {
1818 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
1819 			pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
1820 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v4);
1821 			fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v4.fver;
1822 		} else if (ver->fcxcysta == 5) {
1823 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
1824 			pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
1825 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v5);
1826 			fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v5.fver;
1827 		} else if (ver->fcxcysta == 105) {
1828 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v105;
1829 			pcysta->v105 = pfwinfo->rpt_fbtc_cysta.finfo.v105;
1830 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v105);
1831 			fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v105.fver;
1832 		} else if (ver->fcxcysta == 7) {
1833 			pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
1834 			pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
1835 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v7);
1836 			fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v7.fver;
1837 		} else {
1838 			goto err;
1839 		}
1840 		pcinfo->req_fver = ver->fcxcysta;
1841 		break;
1842 	case BTC_RPT_TYPE_STEP:
1843 		pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
1844 		if (ver->fcxctrl != 7)
1845 			trace_step = btc->ctrl.trace_step;
1846 
1847 		if (ver->fcxstep == 2) {
1848 			pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v2;
1849 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) *
1850 					  trace_step +
1851 					  offsetof(struct rtw89_btc_fbtc_steps_v2, step);
1852 			fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v2.fver;
1853 		} else if (ver->fcxstep == 3) {
1854 			pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3;
1855 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) *
1856 					  trace_step +
1857 					  offsetof(struct rtw89_btc_fbtc_steps_v3, step);
1858 			fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v3.fver;
1859 		} else {
1860 			goto err;
1861 		}
1862 		pcinfo->req_fver = ver->fcxstep;
1863 		break;
1864 	case BTC_RPT_TYPE_NULLSTA:
1865 		pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
1866 		if (ver->fcxnullsta == 1) {
1867 			pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1;
1868 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v1);
1869 			fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v1.fver;
1870 		} else if (ver->fcxnullsta == 2) {
1871 			pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2;
1872 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v2);
1873 			fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v2.fver;
1874 		} else if (ver->fcxnullsta == 7) {
1875 			pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v7;
1876 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v7);
1877 			fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v7.fver;
1878 		} else {
1879 			goto err;
1880 		}
1881 		pcinfo->req_fver = ver->fcxnullsta;
1882 		break;
1883 	case BTC_RPT_TYPE_MREG:
1884 		pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
1885 		if (ver->fcxmreg == 1) {
1886 			pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
1887 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v1);
1888 			fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v1.fver;
1889 		} else if (ver->fcxmreg == 2) {
1890 			pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
1891 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v2);
1892 			fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v2.fver;
1893 		} else if (ver->fcxmreg == 7) {
1894 			pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
1895 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v7);
1896 			fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v7.fver;
1897 		} else {
1898 			goto err;
1899 		}
1900 		pcinfo->req_fver = ver->fcxmreg;
1901 		break;
1902 	case BTC_RPT_TYPE_GPIO_DBG:
1903 		pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
1904 		if (ver->fcxgpiodbg == 7) {
1905 			pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7;
1906 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7);
1907 			fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7.fver;
1908 		} else {
1909 			pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1;
1910 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1);
1911 			fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1.fver;
1912 		}
1913 		pcinfo->req_fver = ver->fcxgpiodbg;
1914 		break;
1915 	case BTC_RPT_TYPE_BT_VER:
1916 		pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
1917 		if (ver->fcxbtver == 1) {
1918 			pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v1;
1919 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v1);
1920 			fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v1.fver;
1921 		} else if (ver->fcxbtver == 7) {
1922 			pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v7;
1923 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v7);
1924 			fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v7.fver;
1925 		} else if (ver->fcxbtver == 8) {
1926 			pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v8;
1927 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v8);
1928 			fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v8.fver;
1929 		} else {
1930 			goto err;
1931 		}
1932 		pcinfo->req_fver = ver->fcxbtver;
1933 		break;
1934 	case BTC_RPT_TYPE_BT_SCAN:
1935 		pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
1936 		if (ver->fcxbtscan == 1) {
1937 			pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1;
1938 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v1);
1939 			fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v1.fver;
1940 		} else if (ver->fcxbtscan == 2) {
1941 			pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2;
1942 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v2);
1943 			fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v2.fver;
1944 		} else if (ver->fcxbtscan == 7) {
1945 			pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v7;
1946 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v7);
1947 			fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v7.fver;
1948 		} else if (ver->fcxbtscan == 8) {
1949 			pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v8;
1950 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v8);
1951 			fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v8.fver;
1952 		} else {
1953 			goto err;
1954 		}
1955 		pcinfo->req_fver = ver->fcxbtscan;
1956 		break;
1957 	case BTC_RPT_TYPE_BT_AFH:
1958 		pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
1959 		if (ver->fcxbtafh == 1) {
1960 			pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1;
1961 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v1);
1962 			fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v1.fver;
1963 		} else if (ver->fcxbtafh == 2) {
1964 			pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2;
1965 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2);
1966 			fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v2.fver;
1967 		} else if (ver->fcxbtafh == 7) {
1968 			pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v7;
1969 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v7);
1970 			fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v7.fver;
1971 		} else if (ver->fcxbtafh == 8) {
1972 			pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v8;
1973 			pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v8);
1974 			fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v8.fver;
1975 		} else {
1976 			goto err;
1977 		}
1978 		pcinfo->req_fver = ver->fcxbtafh;
1979 		break;
1980 	case BTC_RPT_TYPE_BT_DEVICE:
1981 		pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
1982 		pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo;
1983 		pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo);
1984 		fwsubver->fcxbtdevinfo = pfwinfo->rpt_fbtc_btdev.finfo.fver;
1985 		pcinfo->req_fver = ver->fcxbtdevinfo;
1986 		break;
1987 	default:
1988 		pfwinfo->err[BTFRE_UNDEF_TYPE]++;
1989 		return 0;
1990 	}
1991 
1992 	pcinfo->rx_len = rpt_len;
1993 	pcinfo->rx_cnt++;
1994 
1995 	if (rpt_len != pcinfo->req_len) {
1996 		if (rpt_type < BTC_RPT_TYPE_MAX)
1997 			pfwinfo->len_mismch |= (0x1 << rpt_type);
1998 		else
1999 			pfwinfo->len_mismch |= BIT(31);
2000 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2001 			    "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n",
2002 			    __func__, rpt_type, rpt_len, pcinfo->req_len);
2003 
2004 		pcinfo->valid = 0;
2005 		return 0;
2006 	} else if (!pfinfo || !rpt_content || !pcinfo->req_len) {
2007 		pfwinfo->err[BTFRE_EXCEPTION]++;
2008 		pcinfo->valid = 0;
2009 		return 0;
2010 	}
2011 
2012 	memcpy(pfinfo, rpt_content, pcinfo->req_len);
2013 	pcinfo->valid = 1;
2014 
2015 	switch (rpt_type) {
2016 	case BTC_RPT_TYPE_CTRL:
2017 		if (ver->fcxbtcrpt == 1) {
2018 			prpt->v1 = pfwinfo->rpt_ctrl.finfo.v1;
2019 			btc->fwinfo.rpt_en_map = prpt->v1.rpt_enable;
2020 			wl->ver_info.fw_coex = prpt->v1.wl_fw_coex_ver;
2021 			wl->ver_info.fw = prpt->v1.wl_fw_ver;
2022 			dm->wl_fw_cx_offload = !!prpt->v1.wl_fw_cx_offload;
2023 
2024 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
2025 				     pfwinfo->event[BTF_EVNT_RPT]);
2026 
2027 			/* To avoid I/O if WL LPS or power-off */
2028 			if (wl->status.map.lps != BTC_LPS_RF_OFF &&
2029 			    !wl->status.map.rf_off) {
2030 				rtwdev->chip->ops->btc_update_bt_cnt(rtwdev);
2031 				_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2032 
2033 				bt->bcnt[BTC_BCNT_POLLUTED] =
2034 					rtw89_mac_get_plt_cnt(rtwdev,
2035 							      RTW89_MAC_0);
2036 			}
2037 		} else if (ver->fcxbtcrpt == 4) {
2038 			prpt->v4 = pfwinfo->rpt_ctrl.finfo.v4;
2039 			btc->fwinfo.rpt_en_map = le32_to_cpu(prpt->v4.rpt_info.en);
2040 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v4.wl_fw_info.cx_ver);
2041 			wl->ver_info.fw = le32_to_cpu(prpt->v4.wl_fw_info.fw_ver);
2042 			dm->wl_fw_cx_offload = !!le32_to_cpu(prpt->v4.wl_fw_info.cx_offload);
2043 
2044 			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
2045 				memcpy(&dm->gnt_val[i], &prpt->v4.gnt_val[i],
2046 				       sizeof(dm->gnt_val[i]));
2047 
2048 			bt->bcnt[BTC_BCNT_HIPRI_TX] =
2049 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_TX]);
2050 			bt->bcnt[BTC_BCNT_HIPRI_RX] =
2051 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_RX]);
2052 			bt->bcnt[BTC_BCNT_LOPRI_TX] =
2053 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_TX]);
2054 			bt->bcnt[BTC_BCNT_LOPRI_RX] =
2055 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_RX]);
2056 			bt->bcnt[BTC_BCNT_POLLUTED] =
2057 				le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_POLLUTED]);
2058 
2059 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2060 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
2061 				     pfwinfo->event[BTF_EVNT_RPT]);
2062 
2063 			if (le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
2064 				bt->rfk_info.map.timeout = 1;
2065 			else
2066 				bt->rfk_info.map.timeout = 0;
2067 
2068 			dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
2069 		} else if (ver->fcxbtcrpt == 5) {
2070 			prpt->v5 = pfwinfo->rpt_ctrl.finfo.v5;
2071 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v5.rpt_info.en);
2072 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v5.rpt_info.cx_ver);
2073 			wl->ver_info.fw = le32_to_cpu(prpt->v5.rpt_info.fw_ver);
2074 			dm->wl_fw_cx_offload = 0;
2075 
2076 			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
2077 				memcpy(&dm->gnt_val[i], &prpt->v5.gnt_val[i],
2078 				       sizeof(dm->gnt_val[i]));
2079 
2080 			bt->bcnt[BTC_BCNT_HIPRI_TX] =
2081 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_TX]);
2082 			bt->bcnt[BTC_BCNT_HIPRI_RX] =
2083 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_RX]);
2084 			bt->bcnt[BTC_BCNT_LOPRI_TX] =
2085 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_TX]);
2086 			bt->bcnt[BTC_BCNT_LOPRI_RX] =
2087 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_RX]);
2088 			bt->bcnt[BTC_BCNT_POLLUTED] =
2089 				le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_POLLUTED]);
2090 
2091 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2092 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
2093 				     pfwinfo->event[BTF_EVNT_RPT]);
2094 
2095 			dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
2096 		} else if (ver->fcxbtcrpt == 105) {
2097 			prpt->v105 = pfwinfo->rpt_ctrl.finfo.v105;
2098 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v105.rpt_info.en);
2099 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v105.rpt_info.cx_ver);
2100 			wl->ver_info.fw = le32_to_cpu(prpt->v105.rpt_info.fw_ver);
2101 			dm->wl_fw_cx_offload = 0;
2102 
2103 			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
2104 				memcpy(&dm->gnt_val[i], &prpt->v105.gnt_val[i],
2105 				       sizeof(dm->gnt_val[i]));
2106 
2107 			bt->bcnt[BTC_BCNT_HIPRI_TX] =
2108 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_TX_V105]);
2109 			bt->bcnt[BTC_BCNT_HIPRI_RX] =
2110 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_RX_V105]);
2111 			bt->bcnt[BTC_BCNT_LOPRI_TX] =
2112 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_TX_V105]);
2113 			bt->bcnt[BTC_BCNT_LOPRI_RX] =
2114 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_RX_V105]);
2115 			bt->bcnt[BTC_BCNT_POLLUTED] =
2116 				le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_POLLUTED_V105]);
2117 
2118 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2119 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
2120 				     pfwinfo->event[BTF_EVNT_RPT]);
2121 
2122 			dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
2123 		} else if (ver->fcxbtcrpt == 7) {
2124 			prpt->v7 = pfwinfo->rpt_ctrl.finfo.v7;
2125 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v7.rpt_info.en);
2126 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v7.rpt_info.cx_ver);
2127 			wl->ver_info.fw = le32_to_cpu(prpt->v7.rpt_info.fw_ver);
2128 
2129 			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
2130 				memcpy(&dm->gnt_val[i], &prpt->v7.gnt_val[i],
2131 				       sizeof(dm->gnt_val[i]));
2132 
2133 			bt->bcnt[BTC_BCNT_HIPRI_TX] =
2134 				le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_TX_V105]);
2135 			bt->bcnt[BTC_BCNT_HIPRI_RX] =
2136 				le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_RX_V105]);
2137 			bt->bcnt[BTC_BCNT_LOPRI_TX] =
2138 				le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_TX_V105]);
2139 			bt->bcnt[BTC_BCNT_LOPRI_RX] =
2140 				le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_RX_V105]);
2141 
2142 			val1 = le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]);
2143 			if (val1 > bt->bcnt[BTC_BCNT_POLUT_NOW])
2144 				val1 -= bt->bcnt[BTC_BCNT_POLUT_NOW]; /* diff */
2145 
2146 			bt->bcnt[BTC_BCNT_POLUT_DIFF] = val1;
2147 			bt->bcnt[BTC_BCNT_POLUT_NOW] =
2148 				le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]);
2149 
2150 			val1 = pfwinfo->event[BTF_EVNT_RPT];
2151 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2152 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
2153 			_chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
2154 			_chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
2155 		} else if (ver->fcxbtcrpt == 8) {
2156 			prpt->v8 = pfwinfo->rpt_ctrl.finfo.v8;
2157 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v8.rpt_info.en);
2158 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v8.rpt_info.cx_ver);
2159 			wl->ver_info.fw = le32_to_cpu(prpt->v8.rpt_info.fw_ver);
2160 
2161 			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
2162 				memcpy(&dm->gnt_val[i], &prpt->v8.gnt_val[i],
2163 				       sizeof(dm->gnt_val[i]));
2164 
2165 			bt->bcnt[BTC_BCNT_HIPRI_TX] =
2166 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_TX_V105]);
2167 			bt->bcnt[BTC_BCNT_HIPRI_RX] =
2168 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_RX_V105]);
2169 			bt->bcnt[BTC_BCNT_LOPRI_TX] =
2170 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_TX_V105]);
2171 			bt->bcnt[BTC_BCNT_LOPRI_RX] =
2172 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_RX_V105]);
2173 
2174 			val1 = le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
2175 			if (val1 > bt->bcnt[BTC_BCNT_POLUT_NOW])
2176 				val1 -= bt->bcnt[BTC_BCNT_POLUT_NOW]; /* diff */
2177 
2178 			bt->bcnt[BTC_BCNT_POLUT_DIFF] = val1;
2179 			bt->bcnt[BTC_BCNT_POLUT_NOW] =
2180 				le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
2181 
2182 			val1 = pfwinfo->event[BTF_EVNT_RPT];
2183 			if (((prpt->v8.rpt_len_max_h << 8) +
2184 			      prpt->v8.rpt_len_max_l) != ver->info_buf)
2185 				dm->error.map.h2c_c2h_buffer_mismatch = true;
2186 			else
2187 				dm->error.map.h2c_c2h_buffer_mismatch = false;
2188 
2189 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2190 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
2191 			_chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
2192 			_chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
2193 		}  else if (ver->fcxbtcrpt == 9) {
2194 			prpt->v9 = pfwinfo->rpt_ctrl.finfo.v9;
2195 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v9.rpt_info.en);
2196 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v9.rpt_info.cx_ver);
2197 			wl->ver_info.fw = le32_to_cpu(prpt->v9.rpt_info.fw_ver);
2198 
2199 			memcpy(wl->ver_info.build_time,
2200 			       prpt->v9.build_time,
2201 			       sizeof(wl->ver_info.build_time));
2202 			memcpy(wl->ver_info.build_date,
2203 			       prpt->v9.build_date,
2204 			       sizeof(wl->ver_info.build_date));
2205 
2206 			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
2207 				memcpy(&dm->gnt_val[i], &prpt->v9.gnt_val[i],
2208 				       sizeof(dm->gnt_val[i]));
2209 
2210 			bt->bcnt[BTC_BCNT_HIPRI_TX] =
2211 				le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_HI_TX_V105]);
2212 			bt->bcnt[BTC_BCNT_HIPRI_RX] =
2213 				le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_HI_RX_V105]);
2214 			bt->bcnt[BTC_BCNT_LOPRI_TX] =
2215 				le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_LO_TX_V105]);
2216 			bt->bcnt[BTC_BCNT_LOPRI_RX] =
2217 				le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_LO_RX_V105]);
2218 
2219 			val1 = le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_POLLUTED_V105]);
2220 			if (val1 > bt->bcnt[BTC_BCNT_POLUT_NOW])
2221 				val1 -= bt->bcnt[BTC_BCNT_POLUT_NOW]; /* diff */
2222 
2223 			bt->bcnt[BTC_BCNT_POLUT_DIFF] = val1;
2224 			bt->bcnt[BTC_BCNT_POLUT_NOW] =
2225 				le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_POLLUTED_V105]);
2226 
2227 			dm->pta_owner = prpt->v9.pta_owner;
2228 
2229 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2230 			_chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
2231 			_chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
2232 			_chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
2233 		} else if (ver->fcxbtcrpt == 11) {
2234 			prpt->v11 = pfwinfo->rpt_ctrl.finfo.v11;
2235 			pfwinfo->rpt_en_map = le32_to_cpu(prpt->v11.rpt_info.en);
2236 			wl->ver_info.fw_coex = le32_to_cpu(prpt->v11.rpt_info.cx_ver);
2237 			wl->ver_info.fw = le32_to_cpu(prpt->v11.rpt_info.fw_ver);
2238 
2239 			memcpy(wl->ver_info.build_time,
2240 			       prpt->v11.build_time,
2241 			       sizeof(wl->ver_info.build_time));
2242 			memcpy(wl->ver_info.build_date,
2243 			       prpt->v11.build_date,
2244 			       sizeof(wl->ver_info.build_date));
2245 
2246 			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
2247 				memcpy(&dm->gnt_val[i], &prpt->v11.gnt_val[i][0],
2248 				       sizeof(dm->gnt_val[i]));
2249 
2250 			for (i = BTC_BT_1ST; i <= BTC_BT_EXT; i++) {
2251 				if (i == BTC_BT_EXT) {
2252 					if (cx->bt_ext.func_type == BTC_BTF_NONE)
2253 						continue;
2254 					bt_cnt = cx->bt_ext.bcnt;
2255 				} else if (i == BTC_BT_2ND) {
2256 					if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))
2257 						continue;
2258 					bt_cnt = cx->bt1.bcnt;
2259 					wl->scbd_rb[i] = le32_to_cpu(prpt->v11.scbd_w2b[i]);
2260 					cx->bt1.scbd_rb = le32_to_cpu(prpt->v11.scbd_b2w[i]);
2261 				} else {
2262 					bt_cnt = cx->bt0.bcnt;
2263 					wl->scbd_rb[i] = le32_to_cpu(prpt->v11.scbd_w2b[i]);
2264 					cx->bt0.scbd_rb = le32_to_cpu(prpt->v11.scbd_b2w[i]);
2265 				}
2266 
2267 				start_idx = BTC_BCNT_HIPRI_TX;
2268 				for (j = BTC_BCNT_HI_TX_V105; j <= BTC_BCNT_LO_RX_V105 ; j++)
2269 					bt_cnt[start_idx++] = le16_to_cpu(prpt->v11.bt_cnt[i][j]);
2270 
2271 				/* check if polut counter increase */
2272 				val1 = le16_to_cpu(prpt->v11.bt_cnt[i][BTC_BCNT_POLLUTED_V105]);
2273 				if (val1 > bt_cnt[BTC_BCNT_POLUT_NOW]) /* cnt increase*/
2274 					val2 = val1 - bt_cnt[BTC_BCNT_POLUT_NOW];
2275 				else
2276 					val2 = val1; /* overflow */
2277 
2278 				bt_cnt[BTC_BCNT_POLUT_DIFF] = val2;
2279 				bt_cnt[BTC_BCNT_POLUT_NOW] = val1;
2280 
2281 				if (i <= BTC_BT_2ND)
2282 					bt_cnt[BTC_BCNT_SCBDREAD]++;
2283 			}
2284 			dm->scbd_w2b_update = true;
2285 			dm->scbd_b2w_update = true;
2286 
2287 			_chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2288 			_chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
2289 			_chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
2290 			_chk_btc_err(rtwdev, BTC_DCNT_WL_STA_NTFY, 0);
2291 			_chk_btc_err(rtwdev, BTC_DCNT_W2B_SCBD_NOSYNC, 0);
2292 		} else {
2293 			goto err;
2294 		}
2295 		break;
2296 	case BTC_RPT_TYPE_TDMA:
2297 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2298 			    "[BTC], %s(): check %d %zu\n", __func__,
2299 			    BTC_DCNT_TDMA_NONSYNC,
2300 			    sizeof(dm->tdma_now));
2301 		if (ver->fcxtdma == 1)
2302 			_chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
2303 				     memcmp(&dm->tdma_now,
2304 					    &pfwinfo->rpt_fbtc_tdma.finfo.v1,
2305 					    sizeof(dm->tdma_now)));
2306 		else if (ver->fcxtdma == 3 || ver->fcxtdma == 4 ||
2307 			 ver->fcxtdma == 7 || ver->fcxtdma == 8)
2308 			_chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
2309 				     memcmp(&dm->tdma_now,
2310 					    &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma,
2311 					    sizeof(dm->tdma_now)));
2312 		else
2313 			goto err;
2314 		break;
2315 	case BTC_RPT_TYPE_SLOT:
2316 		if (ver->fcxslots == 7) {
2317 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
2318 				    "[BTC], %s(): check %d %zu\n",
2319 				    __func__, BTC_DCNT_SLOT_NONSYNC,
2320 				    sizeof(dm->slot_now.v7));
2321 			_chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
2322 				     memcmp(dm->slot_now.v7,
2323 					    pfwinfo->rpt_fbtc_slots.finfo.v7.slot,
2324 					    sizeof(dm->slot_now.v7)));
2325 		} else if (ver->fcxslots == 2) {
2326 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
2327 				    "[BTC], %s(): check %d %zu\n",
2328 				    __func__, BTC_DCNT_SLOT_NONSYNC,
2329 				    sizeof(dm->slot_now.v7));
2330 			_chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
2331 				     memcmp(dm->slot_now.v7,
2332 					    pfwinfo->rpt_fbtc_slots.finfo.v2.slot,
2333 					    sizeof(dm->slot_now.v7)));
2334 		} else if (ver->fcxslots == 1) {
2335 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
2336 				    "[BTC], %s(): check %d %zu\n",
2337 				    __func__, BTC_DCNT_SLOT_NONSYNC,
2338 				    sizeof(dm->slot_now.v1));
2339 			_chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
2340 				     memcmp(dm->slot_now.v1,
2341 					    pfwinfo->rpt_fbtc_slots.finfo.v1.slot,
2342 					    sizeof(dm->slot_now.v1)));
2343 		}
2344 		break;
2345 	case BTC_RPT_TYPE_CYSTA:
2346 		if (ver->fcxcysta == 2) {
2347 			if (le16_to_cpu(pcysta->v2.cycles) < BTC_CYSTA_CHK_PERIOD)
2348 				break;
2349 			/* Check Leak-AP */
2350 			if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) != 0 &&
2351 			    le32_to_cpu(pcysta->v2.leakrx_cnt) != 0 && dm->tdma_now.rxflctrl) {
2352 				if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) <
2353 				    BTC_LEAK_AP_TH * le32_to_cpu(pcysta->v2.leakrx_cnt))
2354 					dm->leak_ap = 1;
2355 			}
2356 
2357 			/* Check diff time between WL slot and W1/E2G slot */
2358 			if (dm->tdma_now.type == CXTDMA_OFF &&
2359 			    dm->tdma_now.ext_ctrl == CXECTL_EXT) {
2360 				if (ver->fcxslots == 1)
2361 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_E2G].dur);
2362 				else if (ver->fcxslots == 7)
2363 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_E2G].dur);
2364 			} else {
2365 				if (ver->fcxslots == 1)
2366 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2367 				else if (ver->fcxslots == 7)
2368 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2369 			}
2370 
2371 			if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) {
2372 				diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set;
2373 				_chk_btc_err(rtwdev,
2374 					     BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2375 			}
2376 
2377 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2378 				     le32_to_cpu(pcysta->v2.slot_cnt[CXST_W1]));
2379 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2380 				     le32_to_cpu(pcysta->v2.slot_cnt[CXST_B1]));
2381 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2382 				     le16_to_cpu(pcysta->v2.cycles));
2383 		} else if (ver->fcxcysta == 3) {
2384 			if (le16_to_cpu(pcysta->v3.cycles) < BTC_CYSTA_CHK_PERIOD)
2385 				break;
2386 
2387 			cnt_leak_slot = le32_to_cpu(pcysta->v3.slot_cnt[CXST_LK]);
2388 			cnt_rx_imr = le32_to_cpu(pcysta->v3.leak_slot.cnt_rximr);
2389 
2390 			/* Check Leak-AP */
2391 			if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
2392 			    dm->tdma_now.rxflctrl) {
2393 				if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
2394 					dm->leak_ap = 1;
2395 			}
2396 
2397 			/* Check diff time between real WL slot and W1 slot */
2398 			if (dm->tdma_now.type == CXTDMA_OFF) {
2399 				if (ver->fcxslots == 1)
2400 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2401 				else if (ver->fcxslots == 7)
2402 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2403 				wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]);
2404 				if (wl_slot_real > wl_slot_set) {
2405 					diff_t = wl_slot_real - wl_slot_set;
2406 					_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2407 				}
2408 			}
2409 
2410 			/* Check diff time between real BT slot and EBT/E5G slot */
2411 			if (dm->tdma_now.type == CXTDMA_OFF &&
2412 			    dm->tdma_now.ext_ctrl == CXECTL_EXT &&
2413 			    btc->bt_req_len[RTW89_PHY_0] != 0) {
2414 				bt_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_BT]);
2415 				if (btc->bt_req_len[RTW89_PHY_0] > bt_slot_real) {
2416 					diff_t = btc->bt_req_len[RTW89_PHY_0] - bt_slot_real;
2417 					_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2418 				}
2419 			}
2420 
2421 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2422 				     le32_to_cpu(pcysta->v3.slot_cnt[CXST_W1]));
2423 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2424 				     le32_to_cpu(pcysta->v3.slot_cnt[CXST_B1]));
2425 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2426 				     le16_to_cpu(pcysta->v3.cycles));
2427 		} else if (ver->fcxcysta == 4) {
2428 			if (le16_to_cpu(pcysta->v4.cycles) < BTC_CYSTA_CHK_PERIOD)
2429 				break;
2430 
2431 			cnt_leak_slot = le16_to_cpu(pcysta->v4.slot_cnt[CXST_LK]);
2432 			cnt_rx_imr = le32_to_cpu(pcysta->v4.leak_slot.cnt_rximr);
2433 
2434 			/* Check Leak-AP */
2435 			if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
2436 			    dm->tdma_now.rxflctrl) {
2437 				if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
2438 					dm->leak_ap = 1;
2439 			}
2440 
2441 			/* Check diff time between real WL slot and W1 slot */
2442 			if (dm->tdma_now.type == CXTDMA_OFF) {
2443 				if (ver->fcxslots == 1)
2444 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2445 				else if (ver->fcxslots == 7)
2446 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2447 				wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]);
2448 				if (wl_slot_real > wl_slot_set) {
2449 					diff_t = wl_slot_real - wl_slot_set;
2450 					_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2451 				}
2452 			}
2453 
2454 			/* Check diff time between real BT slot and EBT/E5G slot */
2455 			if (dm->tdma_now.type == CXTDMA_OFF &&
2456 			    dm->tdma_now.ext_ctrl == CXECTL_EXT &&
2457 			    btc->bt_req_len[RTW89_PHY_0] != 0) {
2458 				bt_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_BT]);
2459 
2460 				if (btc->bt_req_len[RTW89_PHY_0] > bt_slot_real) {
2461 					diff_t = btc->bt_req_len[RTW89_PHY_0] - bt_slot_real;
2462 					_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2463 				}
2464 			}
2465 
2466 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2467 				     le16_to_cpu(pcysta->v4.slot_cnt[CXST_W1]));
2468 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2469 				     le16_to_cpu(pcysta->v4.slot_cnt[CXST_B1]));
2470 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2471 				     le16_to_cpu(pcysta->v4.cycles));
2472 		} else if (ver->fcxcysta == 5) {
2473 			if (dm->fddt_train == BTC_FDDT_ENABLE)
2474 				break;
2475 			cnt_leak_slot = le16_to_cpu(pcysta->v5.slot_cnt[CXST_LK]);
2476 			cnt_rx_imr = le32_to_cpu(pcysta->v5.leak_slot.cnt_rximr);
2477 
2478 			/* Check Leak-AP */
2479 			if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
2480 			    dm->tdma_now.rxflctrl) {
2481 				if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD &&
2482 				    cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
2483 					dm->leak_ap = 1;
2484 			}
2485 
2486 			/* Check diff time between real WL slot and W1 slot */
2487 			if (dm->tdma_now.type == CXTDMA_OFF) {
2488 				if (ver->fcxslots == 1)
2489 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2490 				else if (ver->fcxslots == 7)
2491 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2492 				wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]);
2493 
2494 				if (wl_slot_real > wl_slot_set)
2495 					diff_t = wl_slot_real - wl_slot_set;
2496 				else
2497 					diff_t = wl_slot_set - wl_slot_real;
2498 			}
2499 			_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2500 
2501 			/* Check diff time between real BT slot and EBT/E5G slot */
2502 			bt_slot_set = btc->bt_req_len[RTW89_PHY_0];
2503 			bt_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_BT]);
2504 			diff_t = 0;
2505 			if (dm->tdma_now.type == CXTDMA_OFF &&
2506 			    dm->tdma_now.ext_ctrl == CXECTL_EXT &&
2507 			    bt_slot_set != 0) {
2508 				if (bt_slot_set > bt_slot_real)
2509 					diff_t = bt_slot_set - bt_slot_real;
2510 				else
2511 					diff_t = bt_slot_real - bt_slot_set;
2512 			}
2513 
2514 			_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2515 			_chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
2516 				     le16_to_cpu(pcysta->v5.slot_cnt[CXST_E2G]));
2517 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2518 				     le16_to_cpu(pcysta->v5.slot_cnt[CXST_W1]));
2519 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2520 				     le16_to_cpu(pcysta->v5.slot_cnt[CXST_B1]));
2521 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2522 				     le16_to_cpu(pcysta->v5.cycles));
2523 		} else if (ver->fcxcysta == 105) {
2524 			if (dm->fddt_train == BTC_FDDT_ENABLE)
2525 				break;
2526 
2527 			cnt_leak_slot = le16_to_cpu(pcysta->v105.slot_cnt[CXST_LK]);
2528 			cnt_rx_imr = le32_to_cpu(pcysta->v105.leak_slot.cnt_rximr);
2529 
2530 			/* Check Leak-AP */
2531 			if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
2532 			    dm->tdma_now.rxflctrl) {
2533 				if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD &&
2534 				    cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
2535 					dm->leak_ap = 1;
2536 			}
2537 
2538 			/* Check diff time between real WL slot and W1 slot */
2539 			if (dm->tdma_now.type == CXTDMA_OFF) {
2540 				if (ver->fcxslots == 1)
2541 					wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2542 				else if (ver->fcxslots == 7)
2543 					wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2544 				wl_slot_real = le16_to_cpu(pcysta->v105.cycle_time.tavg[CXT_WL]);
2545 
2546 				if (wl_slot_real > wl_slot_set)
2547 					diff_t = wl_slot_real - wl_slot_set;
2548 				else
2549 					diff_t = wl_slot_set - wl_slot_real;
2550 			}
2551 			_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2552 
2553 			/* Check diff time between real BT slot and EBT/E5G slot */
2554 			bt_slot_set = btc->bt_req_len[RTW89_PHY_0];
2555 			bt_slot_real = le16_to_cpu(pcysta->v105.cycle_time.tavg[CXT_BT]);
2556 			diff_t = 0;
2557 			if (dm->tdma_now.type == CXTDMA_OFF &&
2558 			    dm->tdma_now.ext_ctrl == CXECTL_EXT &&
2559 			    bt_slot_set != 0) {
2560 				if (bt_slot_set > bt_slot_real)
2561 					diff_t = bt_slot_set - bt_slot_real;
2562 				else
2563 					diff_t = bt_slot_real - bt_slot_set;
2564 			}
2565 
2566 			_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2567 			_chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
2568 				     le16_to_cpu(pcysta->v105.slot_cnt[CXST_E2G]));
2569 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2570 				     le16_to_cpu(pcysta->v105.slot_cnt[CXST_W1]));
2571 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2572 				     le16_to_cpu(pcysta->v105.slot_cnt[CXST_B1]));
2573 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2574 				     le16_to_cpu(pcysta->v105.cycles));
2575 		} else if (ver->fcxcysta == 7) {
2576 			if (dm->fddt_train == BTC_FDDT_ENABLE)
2577 				break;
2578 
2579 			pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
2580 
2581 			if (dm->tdma_now.type != CXTDMA_OFF) {
2582 				/* Check diff time between real WL slot and W1 slot */
2583 				val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_WL]);
2584 				_chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, val16);
2585 
2586 				/* Check Leak-AP */
2587 				val1 = le32_to_cpu(pcysta->v7.leak_slot.cnt_rximr) *
2588 				       BTC_LEAK_AP_TH;
2589 				val2 = le16_to_cpu(pcysta->v7.slot_cnt[CXST_LK]);
2590 
2591 				val16 = le16_to_cpu(pcysta->v7.cycles);
2592 				if (dm->tdma_now.rxflctrl &&
2593 				    val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
2594 					dm->leak_ap = 1;
2595 			} else if (dm->tdma_now.ext_ctrl == CXECTL_EXT) {
2596 				val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_BT]);
2597 				/* Check diff between real BT slot and EBT/E5G slot */
2598 				_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, val16);
2599 
2600 				/* Check bt slot length for P2P mode*/
2601 				val1 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt_timeout) *
2602 				       BTC_SLOT_REQ_TH;
2603 				val2 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt);
2604 
2605 				val16 = le16_to_cpu(pcysta->v7.cycles);
2606 				if (val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
2607 					dm->slot_req_more = 1;
2608 				else if (bt->link_info.status.map.connect == 0)
2609 					dm->slot_req_more = 0;
2610 			}
2611 
2612 			_chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
2613 				     le16_to_cpu(pcysta->v7.slot_cnt[CXST_E2G]));
2614 			_chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2615 				     le16_to_cpu(pcysta->v7.slot_cnt[CXST_W1]));
2616 			_chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2617 				     le16_to_cpu(pcysta->v7.slot_cnt[CXST_B1]));
2618 
2619 			/* "BT_SLOT_FLOOD" error-check MUST before "CYCLE_HANG" */
2620 			_chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_FLOOD,
2621 				     le16_to_cpu(pcysta->v7.cycles));
2622 			_chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2623 				     le16_to_cpu(pcysta->v7.cycles));
2624 		} else {
2625 			goto err;
2626 		}
2627 		break;
2628 	case BTC_RPT_TYPE_MREG:
2629 		if (ver->fcxmreg == 7)
2630 			break;
2631 		_get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX_MON, &val);
2632 		if (dm->wl_btg_rx == BTC_BTGCTRL_BB_GNT_FWCTRL)
2633 			dm->wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_FWCTRL;
2634 		else
2635 			dm->wl_btg_rx_rb = val;
2636 
2637 		_get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC_MON, &val);
2638 		if (dm->wl_pre_agc == BTC_PREAGC_BB_FWCTRL)
2639 			dm->wl_pre_agc_rb = BTC_PREAGC_BB_FWCTRL;
2640 		else
2641 			dm->wl_pre_agc_rb = val;
2642 		break;
2643 	case BTC_RPT_TYPE_BT_VER:
2644 	case BTC_RPT_TYPE_BT_SCAN:
2645 	case BTC_RPT_TYPE_BT_AFH:
2646 	case BTC_RPT_TYPE_BT_DEVICE:
2647 		_update_bt_report(rtwdev, rpt_type, pfinfo);
2648 		break;
2649 	}
2650 	return (rpt_len + BTC_RPT_HDR_SIZE);
2651 
2652 err:
2653 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2654 		    "[BTC], %s(): Undefined version for type=%d\n", __func__, rpt_type);
2655 	return 0;
2656 }
2657 
_parse_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * pbuf,u32 buf_len)2658 static void _parse_btc_report(struct rtw89_dev *rtwdev,
2659 			      struct rtw89_btc_btf_fwinfo *pfwinfo,
2660 			      u8 *pbuf, u32 buf_len)
2661 {
2662 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
2663 	struct rtw89_btc_prpt *btc_prpt = NULL;
2664 	u32 index = 0, rpt_len = 0;
2665 
2666 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2667 		    "[BTC], %s(): buf_len:%d\n",
2668 		    __func__, buf_len);
2669 
2670 	while (pbuf) {
2671 		btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index];
2672 		if (index + 2 >= ver->info_buf)
2673 			break;
2674 		/* At least 3 bytes: type(1) & len(2) */
2675 		rpt_len = le16_to_cpu(btc_prpt->len);
2676 		if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len)
2677 			break;
2678 
2679 		rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index);
2680 		if (!rpt_len)
2681 			break;
2682 		index += rpt_len;
2683 	}
2684 }
2685 
2686 #define BTC_TLV_HDR_LEN 2
2687 #define BTC_TLV_HDR_LEN_V7 3
2688 
_append_tdma(struct rtw89_dev * rtwdev)2689 static void _append_tdma(struct rtw89_dev *rtwdev)
2690 {
2691 	struct rtw89_btc *btc = &rtwdev->btc;
2692 	const struct rtw89_btc_ver *ver = btc->ver;
2693 	struct rtw89_btc_dm *dm = &btc->dm;
2694 	struct rtw89_btc_btf_tlv *tlv;
2695 	struct rtw89_btc_btf_tlv_v7 *tlv_v7;
2696 	struct rtw89_btc_fbtc_tdma *v;
2697 	struct rtw89_btc_fbtc_tdma_v3 *v3;
2698 	u16 len = btc->policy_len;
2699 
2700 	if (!btc->update_policy_force &&
2701 	    !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) {
2702 		rtw89_debug(rtwdev,
2703 			    RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n",
2704 			    __func__);
2705 		return;
2706 	}
2707 
2708 	tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
2709 	tlv->type = CXPOLICY_TDMA;
2710 	if (ver->fcxtdma == 1) {
2711 		v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0];
2712 		tlv->len = sizeof(*v);
2713 		*v = dm->tdma;
2714 		btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
2715 	} else if (ver->fcxtdma == 7 || ver->fcxtdma == 4) {
2716 		tlv_v7 = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2717 		tlv_v7->len = sizeof(dm->tdma);
2718 		tlv_v7->ver = ver->fcxtdma;
2719 		tlv_v7->type = CXPOLICY_TDMA;
2720 		memcpy(tlv_v7->val, &dm->tdma, tlv_v7->len);
2721 		btc->policy_len += BTC_TLV_HDR_LEN_V7 + tlv_v7->len;
2722 	} else {
2723 		tlv->len = sizeof(*v3);
2724 		v3 = (struct rtw89_btc_fbtc_tdma_v3 *)&tlv->val[0];
2725 		v3->fver = ver->fcxtdma;
2726 		v3->tdma = dm->tdma;
2727 		btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v3);
2728 	}
2729 
2730 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2731 		    "[BTC], %s(): type:%d, rxflctrl=%d, txflctrl=%d, bind=%d, leak_n=%d, ext_ctrl=%d\n",
2732 		    __func__, dm->tdma.type, dm->tdma.rxflctrl,
2733 		    dm->tdma.txflctrl, dm->tdma.bind, dm->tdma.leak_n,
2734 		    dm->tdma.ext_ctrl);
2735 }
2736 
_append_slot_v1(struct rtw89_dev * rtwdev)2737 static void _append_slot_v1(struct rtw89_dev *rtwdev)
2738 {
2739 	struct rtw89_btc *btc = &rtwdev->btc;
2740 	struct rtw89_btc_dm *dm = &btc->dm;
2741 	struct rtw89_btc_btf_tlv *tlv = NULL;
2742 	struct btc_fbtc_1slot *v = NULL;
2743 	u16 len = 0;
2744 	u8 i, cnt = 0;
2745 
2746 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
2747 		    "[BTC], %s(): A:btc->policy_len = %d\n",
2748 		    __func__, btc->policy_len);
2749 
2750 	for (i = 0; i < CXST_MAX; i++) {
2751 		if (!btc->update_policy_force &&
2752 		    !memcmp(&dm->slot.v1[i], &dm->slot_now.v1[i],
2753 			    sizeof(dm->slot.v1[i])))
2754 			continue;
2755 
2756 		len = btc->policy_len;
2757 
2758 		tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
2759 		v = (struct btc_fbtc_1slot *)&tlv->val[0];
2760 		tlv->type = CXPOLICY_SLOT;
2761 		tlv->len = sizeof(*v);
2762 
2763 		v->fver = btc->ver->fcxslots;
2764 		v->sid = i;
2765 		v->slot = dm->slot.v1[i];
2766 
2767 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2768 			    "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n",
2769 			    __func__, i, dm->slot.v1[i].dur, dm->slot.v1[i].cxtbl,
2770 			    dm->slot.v1[i].cxtype);
2771 		cnt++;
2772 
2773 		btc->policy_len += BTC_TLV_HDR_LEN  + sizeof(*v);
2774 	}
2775 
2776 	if (cnt > 0)
2777 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2778 			    "[BTC], %s(): slot update (cnt=%d)!!\n",
2779 			    __func__, cnt);
2780 }
2781 
_append_slot_v7(struct rtw89_dev * rtwdev)2782 static void _append_slot_v7(struct rtw89_dev *rtwdev)
2783 {
2784 	struct rtw89_btc_btf_tlv_v7 *tlv = NULL;
2785 	struct rtw89_btc *btc = &rtwdev->btc;
2786 	struct rtw89_btc_dm *dm = &btc->dm;
2787 	u8 i, cnt = 0;
2788 	u16 len;
2789 
2790 	for (i = 0; i < CXST_MAX; i++) {
2791 		if (!btc->update_policy_force &&
2792 		    !memcmp(&dm->slot.v7[i], &dm->slot_now.v7[i],
2793 			    sizeof(dm->slot.v7[i])))
2794 			continue;
2795 
2796 		len = btc->policy_len;
2797 
2798 		if (!tlv) {
2799 			if ((len + BTC_TLV_HDR_LEN_V7) > RTW89_BTC_POLICY_MAXLEN) {
2800 				rtw89_debug(rtwdev, RTW89_DBG_BTC,
2801 					    "[BTC], %s(): buff overflow!\n", __func__);
2802 				break;
2803 			}
2804 
2805 			tlv = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2806 			tlv->type = CXPOLICY_SLOT;
2807 			tlv->ver = btc->ver->fcxslots;
2808 			tlv->len = sizeof(dm->slot.v7[0]) + BTC_TLV_SLOT_ID_LEN_V7;
2809 			len += BTC_TLV_HDR_LEN_V7;
2810 		}
2811 
2812 		if ((len + (u16)tlv->len) > RTW89_BTC_POLICY_MAXLEN) {
2813 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
2814 				    "[BTC], %s(): buff overflow!\n", __func__);
2815 			break;
2816 		}
2817 
2818 		btc->policy[len] = i; /* slot-id */
2819 		memcpy(&btc->policy[len + 1], &dm->slot.v7[i],
2820 		       sizeof(dm->slot.v7[0]));
2821 		len += tlv->len;
2822 
2823 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2824 			    "[BTC], %s: policy_len=%d, slot-%d: dur=%d, type=%d, table=0x%08x\n",
2825 			    __func__, btc->policy_len, i, dm->slot.v7[i].dur,
2826 			    dm->slot.v7[i].cxtype, dm->slot.v7[i].cxtbl);
2827 		cnt++;
2828 		btc->policy_len = len; /* update total length */
2829 	}
2830 
2831 	if (cnt > 0)
2832 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
2833 			    "[BTC], %s: slot update (cnt=%d, len=%d)!!\n",
2834 			    __func__, cnt, btc->policy_len);
2835 }
2836 
_append_slot(struct rtw89_dev * rtwdev)2837 static void _append_slot(struct rtw89_dev *rtwdev)
2838 {
2839 	struct rtw89_btc *btc = &rtwdev->btc;
2840 
2841 	if (btc->ver->fcxslots == 2 || btc->ver->fcxslots == 7)
2842 		_append_slot_v7(rtwdev);
2843 	else
2844 		_append_slot_v1(rtwdev);
2845 }
2846 
rtw89_btc_fw_rpt_ver(struct rtw89_dev * rtwdev,u32 rpt_map)2847 static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map)
2848 {
2849 	struct rtw89_btc *btc = &rtwdev->btc;
2850 	const struct rtw89_btc_ver *ver = btc->ver;
2851 	u32 bit_map = 0;
2852 
2853 	switch (rpt_map) {
2854 	case RPT_EN_TDMA:
2855 		bit_map = BIT(0);
2856 		break;
2857 	case RPT_EN_CYCLE:
2858 		bit_map = BIT(1);
2859 		break;
2860 	case RPT_EN_MREG:
2861 		bit_map = BIT(2);
2862 		break;
2863 	case RPT_EN_BT_VER_INFO:
2864 		bit_map = BIT(3);
2865 		break;
2866 	case RPT_EN_BT_SCAN_INFO:
2867 		bit_map = BIT(4);
2868 		break;
2869 	case RPT_EN_BT_DEVICE_INFO:
2870 		switch (ver->frptmap) {
2871 		case 0:
2872 		case 1:
2873 		case 2:
2874 			bit_map = BIT(6);
2875 			break;
2876 		case 3:
2877 		case 4:
2878 		case 5:
2879 		case 105:
2880 			bit_map = BIT(5);
2881 			break;
2882 		default:
2883 			break;
2884 		}
2885 		break;
2886 	case RPT_EN_BT_AFH_MAP:
2887 		switch (ver->frptmap) {
2888 		case 0:
2889 		case 1:
2890 		case 2:
2891 			bit_map = BIT(5);
2892 			break;
2893 		case 3:
2894 		case 4:
2895 		case 5:
2896 		case 105:
2897 			bit_map = BIT(6);
2898 			break;
2899 		default:
2900 			break;
2901 		}
2902 		break;
2903 	case RPT_EN_BT_AFH_MAP_LE:
2904 		switch (ver->frptmap) {
2905 		case 2:
2906 			bit_map = BIT(8);
2907 			break;
2908 		case 3:
2909 		case 4:
2910 		case 5:
2911 		case 105:
2912 			bit_map = BIT(7);
2913 			break;
2914 		default:
2915 			break;
2916 		}
2917 		break;
2918 	case RPT_EN_BT_TX_PWR_LVL:
2919 		switch (ver->frptmap) {
2920 		case 0:
2921 		case 1:
2922 		case 2:
2923 		case 3:
2924 		case 105:
2925 			break;
2926 		case 4:
2927 		case 5:
2928 			bit_map = BIT(8);
2929 			break;
2930 		default:
2931 			break;
2932 		}
2933 		break;
2934 	case RPT_EN_FW_STEP_INFO:
2935 		switch (ver->frptmap) {
2936 		case 1:
2937 		case 2:
2938 			bit_map = BIT(7);
2939 			break;
2940 		case 3:
2941 		case 105:
2942 			bit_map = BIT(8);
2943 			break;
2944 		case 4:
2945 		case 5:
2946 			bit_map = BIT(9);
2947 			break;
2948 		default:
2949 			break;
2950 		}
2951 		break;
2952 	case RPT_EN_TEST:
2953 		if (ver->frptmap == 5)
2954 			bit_map = BIT(10);
2955 		else if (ver->frptmap == 105)
2956 			bit_map = BIT(9);
2957 		else
2958 			bit_map = BIT(31);
2959 		break;
2960 	case RPT_EN_WL_ALL:
2961 		switch (ver->frptmap) {
2962 		case 0:
2963 		case 1:
2964 		case 2:
2965 			bit_map = GENMASK(2, 0);
2966 			break;
2967 		case 3:
2968 		case 105:
2969 			bit_map = GENMASK(2, 0) | BIT(8);
2970 			break;
2971 		case 4:
2972 		case 5:
2973 			bit_map = GENMASK(2, 0) | BIT(9);
2974 			break;
2975 		default:
2976 			break;
2977 		}
2978 		break;
2979 	case RPT_EN_BT_ALL:
2980 		switch (ver->frptmap) {
2981 		case 0:
2982 		case 1:
2983 			bit_map = GENMASK(6, 3);
2984 			break;
2985 		case 2:
2986 			bit_map = GENMASK(6, 3) | BIT(8);
2987 			break;
2988 		case 3:
2989 		case 105:
2990 			bit_map = GENMASK(7, 3);
2991 			break;
2992 		case 4:
2993 		case 5:
2994 			bit_map = GENMASK(8, 3);
2995 			break;
2996 		default:
2997 			break;
2998 		}
2999 		break;
3000 	case RPT_EN_ALL:
3001 		switch (ver->frptmap) {
3002 		case 0:
3003 			bit_map = GENMASK(6, 0);
3004 			break;
3005 		case 1:
3006 			bit_map = GENMASK(7, 0);
3007 			break;
3008 		case 2:
3009 		case 3:
3010 			bit_map = GENMASK(8, 0);
3011 			break;
3012 		case 4:
3013 		case 5:
3014 		case 105:
3015 			bit_map = GENMASK(9, 0);
3016 			break;
3017 		default:
3018 			break;
3019 		}
3020 		break;
3021 	case RPT_EN_MONITER:
3022 		switch (ver->frptmap) {
3023 		case 0:
3024 		case 1:
3025 			bit_map = GENMASK(6, 2);
3026 			break;
3027 		case 2:
3028 			bit_map = GENMASK(6, 2) | BIT(8);
3029 			break;
3030 		case 3:
3031 		case 105:
3032 			bit_map = GENMASK(8, 2);
3033 			break;
3034 		case 4:
3035 		case 5:
3036 			bit_map = GENMASK(9, 2);
3037 			break;
3038 		default:
3039 			break;
3040 		}
3041 		break;
3042 	}
3043 
3044 	return bit_map;
3045 }
3046 
rtw89_btc_fw_set_slots(struct rtw89_dev * rtwdev)3047 static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev)
3048 {
3049 	struct rtw89_btc *btc = &rtwdev->btc;
3050 	const struct rtw89_btc_ver *ver = btc->ver;
3051 	struct rtw89_btc_btf_tlv_v7 *tlv_v7 = NULL;
3052 	struct rtw89_btc_btf_set_slot_table *tbl;
3053 	struct rtw89_btc_dm *dm = &btc->dm;
3054 	u16 n, len;
3055 
3056 	if (ver->fcxslots == 2 || ver->fcxslots == 7) {
3057 		len = sizeof(*tlv_v7) + sizeof(dm->slot.v7);
3058 		tlv_v7 = kmalloc(len, GFP_KERNEL);
3059 		if (!tlv_v7)
3060 			return;
3061 
3062 		tlv_v7->type = SET_SLOT_TABLE;
3063 		tlv_v7->ver = ver->fcxslots;
3064 		tlv_v7->len = ARRAY_SIZE(dm->slot.v7);
3065 		memcpy(tlv_v7->val, dm->slot.v7, sizeof(dm->slot.v7));
3066 
3067 		_send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, (u8 *)tlv_v7, len);
3068 
3069 		kfree(tlv_v7);
3070 	} else {
3071 		n = struct_size(tbl, tbls, CXST_MAX);
3072 		tbl = kmalloc(n, GFP_KERNEL);
3073 		if (!tbl)
3074 			return;
3075 
3076 		tbl->fver = BTF_SET_SLOT_TABLE_VER;
3077 		tbl->tbl_num = CXST_MAX;
3078 		memcpy(tbl->tbls, dm->slot.v1, flex_array_size(tbl, tbls, CXST_MAX));
3079 
3080 		_send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
3081 
3082 		kfree(tbl);
3083 	}
3084 }
3085 
rtw89_btc_fw_en_rpt(struct rtw89_dev * rtwdev,bool force_exec,u32 rpt_map)3086 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
3087 				bool force_exec, u32 rpt_map)
3088 {
3089 	struct rtw89_btc *btc = &rtwdev->btc;
3090 	struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo;
3091 	union rtw89_fbtc_rtp_ctrl r;
3092 	int ret;
3093 	u32 i;
3094 
3095 	if (!force_exec && rpt_map == fwinfo->rpt_en_map)
3096 		return;
3097 
3098 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rpt_map=%x\n",
3099 		    __func__, fwinfo->rpt_en_map);
3100 
3101 	if (btc->ver->fcxbtcrpt == 7 ||
3102 	    btc->ver->fcxbtcrpt == 8 ||
3103 	    btc->ver->fcxbtcrpt == 9 ||
3104 	    btc->ver->fcxbtcrpt == 11) {
3105 		r.v8.type = SET_REPORT_EN;
3106 		r.v8.fver = btc->ver->fcxbtcrpt;
3107 		r.v8.len = sizeof(r.v8.map);
3108 		r.v8.map = cpu_to_le32(rpt_map);
3109 		ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v8,
3110 				   sizeof(r.v8));
3111 	} else {
3112 		if (btc->ver->fcxbtcrpt == 105)
3113 			r.v1.fver = 5;
3114 		else
3115 			r.v1.fver = btc->ver->fcxbtcrpt;
3116 
3117 		for (i = 0; i < RPT_EN_MONITER; i++) {
3118 			r.v1.enable = cpu_to_le32(i);
3119 			if (rpt_map & BIT(i))
3120 				r.v1.para = cpu_to_le32(1);
3121 			else
3122 				r.v1.para = 0;
3123 
3124 			ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN,
3125 					   &r.v1, sizeof(r.v1));
3126 		}
3127 	}
3128 
3129 	if (!ret)
3130 		fwinfo->rpt_en_map = rpt_map;
3131 }
3132 
btc_fw_set_monreg(struct rtw89_dev * rtwdev)3133 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
3134 {
3135 	const struct rtw89_chip_info *chip = rtwdev->chip;
3136 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
3137 	struct rtw89_btc_btf_set_mon_reg_v1 *v1 = NULL;
3138 	struct rtw89_btc_btf_set_mon_reg_v7 *v7 = NULL;
3139 	u8 i, n, ulen, cxmreg_max;
3140 	u16 sz = 0;
3141 
3142 	n = chip->mon_reg_num;
3143 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
3144 		    "[BTC], %s(): mon_reg_num=%d\n", __func__, n);
3145 
3146 	if (ver->fcxmreg == 1)
3147 		cxmreg_max = CXMREG_MAX;
3148 	else
3149 		cxmreg_max = CXMREG_MAX_V2;
3150 
3151 	if (n > cxmreg_max) {
3152 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
3153 			    "[BTC], %s(): mon reg count %d > %d\n",
3154 			    __func__, n, cxmreg_max);
3155 		return;
3156 	}
3157 
3158 	ulen = sizeof(struct rtw89_btc_fbtc_mreg);
3159 
3160 	if (ver->fcxmreg == 7) {
3161 		sz = struct_size(v7, regs, n);
3162 		v7 = kmalloc(sz, GFP_KERNEL);
3163 		if (!v7)
3164 			return;
3165 		v7->type = RPT_EN_MREG;
3166 		v7->fver = ver->fcxmreg;
3167 		v7->len = n;
3168 		for (i = 0; i < n; i++) {
3169 			v7->regs[i].type = chip->mon_reg[i].type;
3170 			v7->regs[i].bytes = chip->mon_reg[i].bytes;
3171 			v7->regs[i].offset = chip->mon_reg[i].offset;
3172 		}
3173 
3174 		_send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v7, sz);
3175 		kfree(v7);
3176 	} else {
3177 		sz = struct_size(v1, regs, n);
3178 		v1 = kmalloc(sz, GFP_KERNEL);
3179 		if (!v1)
3180 			return;
3181 		v1->fver = ver->fcxmreg;
3182 		v1->reg_num = n;
3183 		memcpy(v1->regs, chip->mon_reg, flex_array_size(v1, regs, n));
3184 
3185 		_send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v1, sz);
3186 		kfree(v1);
3187 	}
3188 
3189 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
3190 		    "[BTC], %s(): sz=%d ulen=%d n=%d\n",
3191 		    __func__, sz, ulen, n);
3192 }
3193 
_update_dm_step(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason_or_action)3194 static void _update_dm_step(struct rtw89_dev *rtwdev,
3195 			    enum btc_reason_and_action reason_or_action)
3196 {
3197 	struct rtw89_btc *btc = &rtwdev->btc;
3198 	struct rtw89_btc_dm *dm = &btc->dm;
3199 
3200 	/* use ring-structure to store dm step */
3201 	dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action;
3202 	dm->dm_step.step_pos++;
3203 
3204 	if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) {
3205 		dm->dm_step.step_pos = 0;
3206 		dm->dm_step.step_ov = true;
3207 	}
3208 }
3209 
_fw_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)3210 static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
3211 			   enum btc_reason_and_action action)
3212 {
3213 	struct rtw89_btc *btc = &rtwdev->btc;
3214 	struct rtw89_btc_dm *dm = &btc->dm;
3215 	int ret;
3216 
3217 	dm->run_action = action;
3218 
3219 	_update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT);
3220 	_update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT);
3221 
3222 	btc->policy_len = 0;
3223 	btc->policy_type = policy_type;
3224 
3225 	_append_tdma(rtwdev);
3226 	_append_slot(rtwdev);
3227 
3228 	if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN)
3229 		return;
3230 
3231 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
3232 		    "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n",
3233 		    __func__, action, policy_type, btc->policy_len);
3234 
3235 	if (dm->tdma.rxflctrl == CXFLC_NULLP ||
3236 	    dm->tdma.rxflctrl == CXFLC_QOSNULL)
3237 		btc->btc_ctrl_lps = 1;
3238 	else
3239 		btc->btc_ctrl_lps = dm->lps_ctrl_scbd;
3240 
3241 	if (btc->btc_ctrl_lps == 1)
3242 		rtw89_set_coex_ctrl_lps(rtwdev, btc->btc_ctrl_lps);
3243 
3244 	ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY,
3245 			   btc->policy, btc->policy_len);
3246 	if (!ret) {
3247 		memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now));
3248 		if (btc->ver->fcxslots == 2 || btc->ver->fcxslots == 7)
3249 			memcpy(&dm->slot_now.v7, &dm->slot.v7, sizeof(dm->slot_now.v7));
3250 		else
3251 			memcpy(&dm->slot_now.v1, &dm->slot.v1, sizeof(dm->slot_now.v1));
3252 	}
3253 
3254 	if (btc->update_policy_force)
3255 		btc->update_policy_force = false;
3256 
3257 	if (btc->btc_ctrl_lps == 0)
3258 		rtw89_set_coex_ctrl_lps(rtwdev, btc->btc_ctrl_lps);
3259 }
3260 
_get_gpiosig_for_ver(struct rtw89_dev * rtwdev,u8 sig_v8)3261 static u8 _get_gpiosig_for_ver(struct rtw89_dev *rtwdev, u8 sig_v8)
3262 {
3263 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
3264 
3265 	/* v8: gpio_ver >= 8, directly use v8 signal ID */
3266 	if (ver->fcxgpiodbg >= 8)
3267 		return sig_v8;
3268 
3269 	/* v7: gpio_ver < 8, convert v8 signal ID to v7 signal ID */
3270 	if (sig_v8 <= BTC_DBG_GNT_WL) {
3271 		return sig_v8;
3272 	} else if (sig_v8 <= BTC_DBG_GNT_WL1) {
3273 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
3274 			    "[BTC], %s(): sig %d not supported in v7\n",
3275 			    __func__, sig_v8);
3276 		return BTC_DBG_NUM;
3277 	} else if (sig_v8 >= BTC_DBG_NUM) {
3278 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
3279 			    "[BTC], %s(): sig %d not available\n",
3280 			    __func__, sig_v8);
3281 		return BTC_DBG_NUM;
3282 	} else {
3283 		return sig_v8 - 2;
3284 	}
3285 }
3286 
_convert_gpio_enmap_to_ver(struct rtw89_dev * rtwdev,u32 en_map_v8)3287 static u32 _convert_gpio_enmap_to_ver(struct rtw89_dev *rtwdev, u32 en_map_v8)
3288 {
3289 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
3290 	u32 en_map_v7 = 0;
3291 	u32 bit;
3292 
3293 	/* v8: gpio_ver >= 8, directly use v8 en_map */
3294 	if (ver->fcxgpiodbg >= 8)
3295 		return en_map_v8;
3296 
3297 	/* v7: gpio_ver < 8, convert v8 en_map bitmap to v7 en_map bitmap */
3298 	/* bit 0-1: GNT_BT, GNT_WL - same position in both versions */
3299 	en_map_v7 |= en_map_v8 & GENMASK(1, 0);
3300 
3301 	/* bit 2-3: GNT_BT1, GNT_WL1 - not supported in v7, skip these bits */
3302 
3303 	/* bit 4-31: shift right by 2 positions (become bit 2-29 in v7) */
3304 	for (bit = BTC_DBG_BCN_EARLY; bit < BTC_DBG_NUM; bit++) {
3305 		if (en_map_v8 & BIT(bit))
3306 			en_map_v7 |= BIT(bit - 2);
3307 	}
3308 
3309 	return en_map_v7;
3310 }
3311 
_convert_gpio_enmap_from_ver(struct rtw89_dev * rtwdev,u32 en_map)3312 static u32 _convert_gpio_enmap_from_ver(struct rtw89_dev *rtwdev, u32 en_map)
3313 {
3314 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
3315 	u32 en_map_v8 = 0;
3316 	u32 bit;
3317 
3318 	if (ver->fcxgpiodbg >= 8)
3319 		return en_map;
3320 
3321 	/* bit 0-1: GNT_BT, GNT_WL - same position in both versions */
3322 	en_map_v8 |= en_map & GENMASK(1, 0);
3323 
3324 	/* bit 2-29: shift left by 2 positions (become bit 4-31 in v8) */
3325 	for (bit = BTC_DBG_GNT_BT1; bit < BTC_DBG_NUM - 2; bit++) {
3326 		if (en_map & BIT(bit))
3327 			en_map_v8 |= BIT(bit + 2);
3328 	}
3329 
3330 	return en_map_v8;
3331 }
3332 
_fw_set_gpio(struct rtw89_dev * rtwdev,u8 type,u32 val)3333 static void _fw_set_gpio(struct rtw89_dev *rtwdev, u8 type, u32 val)
3334 {
3335 	struct rtw89_btc *btc = &rtwdev->btc;
3336 	struct rtw89_fbtc_h2c_set_gpio *gpio = &btc->gpio;
3337 	const struct rtw89_btc_ver *ver = btc->ver;
3338 	struct rtw89_fbtc_h2c_set_gpio_2b l2_h2c;
3339 	struct rtw89_fbtc_h2c_set_gpio_4b l4_h2c;
3340 	u8 gpio_ver = ver->fcxgpiodbg;
3341 	u8 buf[sizeof(l4_h2c)];
3342 	u8 len;
3343 
3344 	if (gpio_ver < 8 && type > CXDGPIO_MUX_MAP)
3345 		return;
3346 
3347 	if (type >= CXDGPIO_MAX)
3348 		return;
3349 
3350 	switch (type) {
3351 	case CXDGPIO_EN_MAP: /* GPIO debug signal en-map 0~31 */
3352 		val = _convert_gpio_enmap_to_ver(rtwdev, val);
3353 		gpio->en_map.data.type = CXDGPIO_EN_MAP;
3354 		gpio->en_map.data.fver = gpio_ver;
3355 		gpio->en_map.data.dlen = CXDGPIO_SET_L4;
3356 		gpio->en_map.data.en_map = val;
3357 		l4_h2c = gpio->en_map.fmt;
3358 		put_unaligned_le32(val, (u32 *)l4_h2c.data);
3359 		memcpy(buf, &l4_h2c, sizeof(l4_h2c));
3360 		len = sizeof(l4_h2c);
3361 		break;
3362 	case CXDGPIO_MUX_MAP: /* GPIO dbg: Signal to GPIO Mux */
3363 		gpio->mux.data.type = CXDGPIO_MUX_MAP;
3364 		gpio->mux.data.fver = gpio_ver;
3365 		gpio->mux.data.dlen = CXDGPIO_SET_L2;
3366 		gpio->mux.data.sig = _get_gpiosig_for_ver(rtwdev,
3367 							  FIELD_GET(GENMASK(7, 0), val));
3368 		if (gpio->mux.data.sig == 0xff)
3369 			return;
3370 		gpio->mux.data.gpio = FIELD_GET(GENMASK(15, 8), val);
3371 		l2_h2c = gpio->mux.fmt;
3372 		memcpy(buf, &l2_h2c, sizeof(l2_h2c));
3373 		len = sizeof(l2_h2c);
3374 		break;
3375 	case CXDGPIO_EXT_HPTA: /* GPIO config for Ext HW-PTA */
3376 		gpio->ext_pta.data.type = CXDGPIO_EXT_HPTA;
3377 		gpio->ext_pta.data.fver = gpio_ver;
3378 		gpio->ext_pta.data.dlen = CXDGPIO_SET_L2;
3379 		gpio->ext_pta.data.map_low = FIELD_GET(GENMASK(7, 0), val);
3380 		gpio->ext_pta.data.map_high = FIELD_GET(GENMASK(15, 8), val);
3381 		l2_h2c = gpio->ext_pta.fmt;
3382 		memcpy(buf, &l2_h2c, sizeof(l2_h2c));
3383 		len = sizeof(l2_h2c);
3384 		break;
3385 	case CXDGPIO_EXT_HMBX: /* GPIO config for Ext HW-mailbox */
3386 		gpio->ext_mb.data.type = CXDGPIO_EXT_HMBX;
3387 		gpio->ext_mb.data.fver = gpio_ver;
3388 		gpio->ext_mb.data.dlen = CXDGPIO_SET_L2;
3389 		gpio->ext_mb.data.map_low = FIELD_GET(GENMASK(7, 0), val);
3390 		gpio->ext_mb.data.map_high = FIELD_GET(GENMASK(15, 8), val);
3391 		l2_h2c = gpio->ext_mb.fmt;
3392 		memcpy(buf, &l2_h2c, sizeof(l2_h2c));
3393 		len = sizeof(l2_h2c);
3394 		break;
3395 	case CXDGPIO_EXT_SWOUT: /* GPIO config for Ext SW output (wlan_act) */
3396 		gpio->ext_swout.data.type = CXDGPIO_EXT_SWOUT;
3397 		gpio->ext_swout.data.fver = gpio_ver;
3398 		gpio->ext_swout.data.dlen = CXDGPIO_SET_L2;
3399 		gpio->ext_swout.data.map_low = FIELD_GET(GENMASK(7, 0), val);
3400 		gpio->ext_swout.data.map_high = FIELD_GET(GENMASK(15, 8), val);
3401 		l2_h2c = gpio->ext_swout.fmt;
3402 		memcpy(buf, &l2_h2c, sizeof(l2_h2c));
3403 		len = sizeof(l2_h2c);
3404 		break;
3405 	case CXDGPIO_EXT_SWIN: /* GPIO config for Ext SW input control */
3406 		gpio->ext_swin.data.type = CXDGPIO_EXT_SWIN;
3407 		gpio->ext_swin.data.fver = gpio_ver;
3408 		gpio->ext_swin.data.dlen = CXDGPIO_SET_L4;
3409 		gpio->ext_swin.data.in_map_low = FIELD_GET(GENMASK(7, 0), val);
3410 		gpio->ext_swin.data.in_map_high = FIELD_GET(GENMASK(15, 8), val);
3411 		gpio->ext_swin.data.int_map_low = FIELD_GET(GENMASK(23, 16), val);
3412 		gpio->ext_swin.data.int_map_high = FIELD_GET(GENMASK(31, 24), val);
3413 		l4_h2c = gpio->ext_swin.fmt;
3414 		put_unaligned_le32(val, (u32 *)l4_h2c.data);
3415 		memcpy(buf, &l4_h2c, sizeof(l4_h2c));
3416 		len = sizeof(l4_h2c);
3417 		break;
3418 	default:
3419 		return;
3420 	}
3421 
3422 	_send_fw_cmd(rtwdev, BTFC_SET, SET_GPIO_DBG, buf, len);
3423 }
3424 
_set_ext_interface(struct rtw89_dev * rtwdev)3425 static void _set_ext_interface(struct rtw89_dev *rtwdev)
3426 {
3427 	struct rtw89_btc *btc = &rtwdev->btc;
3428 	struct rtw89_btc_cx *cx = &btc->cx;
3429 	u8 bt1_sw_type = BTC_SWITCH_INTERNAL;
3430 	u32 val;
3431 
3432 	if (btc->ver->fcxgpiodbg < 7)
3433 		return;
3434 
3435 	/* if BT1+WL-S0, route DBG_GNT_BT1 to control SPDT */
3436 	if ((rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) &&
3437 	    btc->ver->fcxinit >= 10) {
3438 		if (btc->ver->fcxinit >= 10)
3439 			bt1_sw_type = btc->mdinfo.bt1_sw_type;
3440 		else
3441 			return;
3442 
3443 		if (bt1_sw_type > BTC_SWITCH_INTERNAL) {
3444 			_fw_set_gpio(rtwdev, CXDGPIO_EN_MAP,
3445 				     BIT(BTC_DBG_GNT_BT1));
3446 
3447 			val = (bt1_sw_type << 8) + BTC_DBG_GNT_BT1;
3448 			_fw_set_gpio(rtwdev, CXDGPIO_MUX_MAP, val);
3449 		}
3450 	}
3451 
3452 	/* set GPIO as Ext-PTA interface wire */
3453 	if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_PTA)
3454 		_fw_set_gpio(rtwdev, CXDGPIO_EXT_HPTA, cx->bt_ext.hpta_cfg);
3455 
3456 	/* set GPIO as Ext-mailbox interface wire */
3457 	if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_MBX)
3458 		_fw_set_gpio(rtwdev, CXDGPIO_EXT_HMBX, cx->bt_ext.hmbx_cfg);
3459 
3460 	/* set GPIO as Ext-SWIO interface wire */
3461 	if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_SWIO) {
3462 		_fw_set_gpio(rtwdev, CXDGPIO_EXT_SWOUT, cx->bt_ext.swout_cfg);
3463 		_fw_set_gpio(rtwdev, CXDGPIO_EXT_SWIN, cx->bt_ext.swin_cfg);
3464 	}
3465 }
3466 
_fw_set_drv_info(struct rtw89_dev * rtwdev,u8 index)3467 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 index)
3468 {
3469 	struct rtw89_btc *btc = &rtwdev->btc;
3470 	const struct rtw89_btc_ver *ver = btc->ver;
3471 
3472 	switch (index) {
3473 	case CXDRVINFO_INIT:
3474 		if (ver->fcxinit == 7 || ver->fcxinit == 107)
3475 			rtw89_fw_h2c_cxdrv_init_v7(rtwdev, index);
3476 		else if (ver->fcxinit == 10)
3477 			rtw89_fw_h2c_cxdrv_init_v10(rtwdev, index);
3478 		else if (ver->fcxinit == 11)
3479 			rtw89_fw_h2c_cxdrv_init_v11(rtwdev, index);
3480 		else
3481 			rtw89_fw_h2c_cxdrv_init(rtwdev, index);
3482 		break;
3483 	case CXDRVINFO_ROLE:
3484 		if (ver->fwlrole == 0)
3485 			rtw89_fw_h2c_cxdrv_role(rtwdev, index);
3486 		else if (ver->fwlrole == 1)
3487 			rtw89_fw_h2c_cxdrv_role_v1(rtwdev, index);
3488 		else if (ver->fwlrole == 101)
3489 			rtw89_fw_h2c_cxdrv_role_v101(rtwdev, index);
3490 		else if (ver->fwlrole == 2)
3491 			rtw89_fw_h2c_cxdrv_role_v2(rtwdev, index);
3492 		else if (ver->fwlrole == 7)
3493 			rtw89_fw_h2c_cxdrv_role_v7(rtwdev, index);
3494 		else if (ver->fwlrole == 8)
3495 			rtw89_fw_h2c_cxdrv_role_v8(rtwdev, index);
3496 		else if (ver->fwlrole == 10)
3497 			rtw89_fw_h2c_cxdrv_role_v10(rtwdev, index);
3498 		break;
3499 	case CXDRVINFO_CTRL:
3500 		if (ver->drvinfo_ver != 0)
3501 			index = 2;
3502 
3503 		if (ver->fcxctrl == 7)
3504 			rtw89_fw_h2c_cxdrv_ctrl_v7(rtwdev, index);
3505 		else if (ver->fcxctrl == 9)
3506 			rtw89_fw_h2c_cxdrv_ctrl_v9(rtwdev, index);
3507 		else
3508 			rtw89_fw_h2c_cxdrv_ctrl(rtwdev, index);
3509 		break;
3510 	case CXDRVINFO_TRX:
3511 		if (ver->drvinfo_ver > 1)
3512 			index = 3;
3513 
3514 		if (ver->fcxtrx == 0)
3515 			return;
3516 
3517 		if (ver->fcxtrx == 7)
3518 			rtw89_fw_h2c_cxdrv_trx_v7(rtwdev, index);
3519 		else if (ver->fcxtrx == 9)
3520 			rtw89_fw_h2c_cxdrv_trx_v9(rtwdev, index);
3521 		else if (ver->fcxtrx == 107)
3522 			rtw89_fw_h2c_cxdrv_trx_v107(rtwdev, index);
3523 		break;
3524 	case CXDRVINFO_RFK:
3525 		if (ver->drvinfo_ver != 0)
3526 			return;
3527 
3528 		rtw89_fw_h2c_cxdrv_rfk(rtwdev, index);
3529 		break;
3530 	case CXDRVINFO_TXPWR:
3531 		if (ver->drvinfo_ver == 3 || ver->drvinfo_ver == 103)
3532 			index = 4;
3533 
3534 		if (ver->fcxtrx == 7 || ver->fcxtrx == 107)
3535 			rtw89_fw_h2c_cxtxpwr_v7(rtwdev, index);
3536 		else if (ver->fcxtrx == 9)
3537 			rtw89_fw_h2c_cxtxpwr_v9(rtwdev, index);
3538 		break;
3539 	case CXDRVINFO_FDDT:
3540 		if (ver->drvinfo_ver == 3 || ver->drvinfo_ver == 103)
3541 			index = 5;
3542 		else
3543 			return;
3544 
3545 		break;
3546 	case CXDRVINFO_MLO:
3547 		if (!ver->fcxmlo || ver->drvinfo_ver == 103)
3548 			return;
3549 
3550 		if (ver->drvinfo_ver == 3)
3551 			index = 6;
3552 		else
3553 			return;
3554 
3555 		if (ver->fcxmlo == 2)
3556 			rtw89_fw_h2c_cxdrv_mlo_v2(rtwdev, index);
3557 
3558 		break;
3559 	case CXDRVINFO_OSI:
3560 		if (!ver->fcxosi || ver->drvinfo_ver == 103)
3561 			return;
3562 
3563 		if (ver->drvinfo_ver == 3)
3564 			index = 7;
3565 		else
3566 			return;
3567 
3568 		if (ver->fcxosi == 1)
3569 			rtw89_fw_h2c_cxdrv_osi_info(rtwdev, index);
3570 		else if (ver->fcxosi == 6)
3571 			rtw89_fw_h2c_cxdrv_osi_info_v6(rtwdev, index);
3572 		else
3573 			return;
3574 		break;
3575 	default:
3576 		break;
3577 	}
3578 }
3579 
3580 static
btc_fw_event(struct rtw89_dev * rtwdev,u8 evt_id,void * data,u32 len)3581 void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len)
3582 {
3583 	struct rtw89_btc *btc = &rtwdev->btc;
3584 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
3585 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
3586 	u8 i;
3587 
3588 	_parse_btc_report(rtwdev, pfwinfo, data, len);
3589 
3590 	if (!rtwdev->chip->scbd)
3591 		return;
3592 
3593 	if (!btc->dm.scbd_b2w_update)
3594 		return; /* skip if init or no-update */
3595 
3596 	for (i = BTC_BT_1ST; i <= BTC_BT_2ND; i++) {
3597 		bt = (i == BTC_BT_1ST) ? &btc->cx.bt0 : &btc->cx.bt1;
3598 
3599 		if (bt->scbd_c2h != bt->scbd_rb) {
3600 			/* if btx b2w scbd non-sync */
3601 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
3602 				    "[BTC], %s() bt%d:c2h->0x%08x, rb->0x%08x\n",
3603 				    __func__, i, bt->scbd_c2h, bt->scbd_rb);
3604 			bt->scbd_c2h = bt->scbd_rb;
3605 			_update_bt_scbd(rtwdev, i);
3606 			btc->dm.scbd_b2w_update = false;
3607 		}
3608 	}
3609 
3610 	if (!btc->dm.scbd_b2w_update)
3611 		_run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
3612 	else
3613 		btc->dm.scbd_b2w_update = 0;
3614 }
3615 
_set_gnt(struct rtw89_dev * rtwdev,u8 phy_map,u8 wl_state,u8 bt_state,u8 wlact_state)3616 static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map,
3617 		     u8 wl_state, u8 bt_state, u8 wlact_state)
3618 {
3619 	struct rtw89_btc *btc = &rtwdev->btc;
3620 	struct rtw89_btc_dm *dm = &btc->dm;
3621 	struct rtw89_btc_fbtc_outsrc_set_info *o = &dm->ost_info;
3622 	struct rtw89_mac_ax_wl_act *wlact_set;
3623 	struct rtw89_mac_ax_coex_gnt mg;
3624 	u8 i;
3625 
3626 	if (phy_map > BTC_PHY_ALL)
3627 		return;
3628 
3629 	for (i = 0; i < RTW89_PHY_NUM; i++) {
3630 		if (!(phy_map & BIT(i)))
3631 			continue;
3632 
3633 		switch (wl_state) {
3634 		case BTC_GNT_HW:
3635 			dm->gnt_set[i].gnt_wl_sw_en = 0;
3636 			dm->gnt_set[i].gnt_wl = 0;
3637 			break;
3638 		case BTC_GNT_SW_LO:
3639 			dm->gnt_set[i].gnt_wl_sw_en = 1;
3640 			dm->gnt_set[i].gnt_wl = 0;
3641 			break;
3642 		case BTC_GNT_SW_HI:
3643 			dm->gnt_set[i].gnt_wl_sw_en = 1;
3644 			dm->gnt_set[i].gnt_wl = 1;
3645 			break;
3646 		case BTC_GNT_SET_SKIP:
3647 		default:
3648 			break;
3649 		}
3650 
3651 		switch (bt_state) {
3652 		case BTC_GNT_HW:
3653 			dm->gnt_set[i].gnt_bt0_sw_en = 0;
3654 			dm->gnt_set[i].gnt_bt0 = 0;
3655 			dm->gnt_set[i].gnt_bt1_sw_en = 0;
3656 			dm->gnt_set[i].gnt_bt1 = 0;
3657 			dm->gnt_set[i].gnt_zb_sw_en = 0;
3658 			dm->gnt_set[i].gnt_zb = 0;
3659 			break;
3660 		case BTC_GNT_SW_LO:
3661 			dm->gnt_set[i].gnt_bt0_sw_en = 1;
3662 			dm->gnt_set[i].gnt_bt0 = 0;
3663 			dm->gnt_set[i].gnt_bt1_sw_en = 1;
3664 			dm->gnt_set[i].gnt_bt1 = 0;
3665 			dm->gnt_set[i].gnt_zb_sw_en = 1;
3666 			dm->gnt_set[i].gnt_zb = 0;
3667 			break;
3668 		case BTC_GNT_SW_HI:
3669 			dm->gnt_set[i].gnt_bt0_sw_en = 1;
3670 			dm->gnt_set[i].gnt_bt0 = 1;
3671 			dm->gnt_set[i].gnt_bt1_sw_en = 1;
3672 			dm->gnt_set[i].gnt_bt1 = 1;
3673 			dm->gnt_set[i].gnt_zb_sw_en = 1;
3674 			dm->gnt_set[i].gnt_zb = 1;
3675 			break;
3676 		case BTC_GNT_SET_SKIP:
3677 		default:
3678 			break;
3679 		}
3680 	}
3681 
3682 	for (i = 0; i < BTC_ALL_BT_EZL; i++) {
3683 		if (!(rtwdev->chip->para_ver & BTC_FEAT_WLAN_ACT_MUX))
3684 			break;
3685 
3686 		switch (wlact_state) {
3687 		case BTC_WLACT_HW:
3688 			dm->wlact_set[i].wlan_act_en = 0;
3689 			dm->wlact_set[i].wlan_act = 0;
3690 			break;
3691 		case BTC_WLACT_SW_LO:
3692 			dm->wlact_set[i].wlan_act_en = 1;
3693 			dm->wlact_set[i].wlan_act = 0;
3694 			break;
3695 		case BTC_WLACT_SW_HI:
3696 			dm->wlact_set[i].wlan_act_en = 1;
3697 			dm->wlact_set[i].wlan_act = 1;
3698 			break;
3699 		default:
3700 			break;
3701 		}
3702 
3703 		if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))
3704 			break;
3705 	}
3706 
3707 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
3708 		    "[BTC], %s(): phy_map=0x%x, gnt_wl:%d, gnt_bt:%d, wl_act:%d\n",
3709 		    __func__, phy_map, wl_state, bt_state, wlact_state);
3710 
3711 	if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO) {
3712 		if (o->rf_band[BTC_RF_S0] == 1 && o->rf_band[BTC_RF_S1] == 0)
3713 			o->rf_gbt_source = BTC_RF_S1;
3714 		else
3715 			o->rf_gbt_source = BTC_RF_S0;
3716 
3717 		memcpy(o->wlact_set, dm->wlact_set, sizeof(o->wlact_set));
3718 
3719 		if (btc->ver->fcxosi == 6) {
3720 			memcpy(o->gnt_set_be, dm->gnt_set, sizeof(o->gnt_set_be));
3721 			return;
3722 		} else if (btc->ver->fcxosi == 1) {
3723 			for (i = 0; i < RTW89_PHY_NUM; i++) { /* gnt[MAC0/MAC1] */
3724 				mg.band[i].gnt_bt_sw_en = dm->gnt_set[i].gnt_bt0_sw_en;
3725 				mg.band[i].gnt_bt = dm->gnt_set[i].gnt_bt0;
3726 				mg.band[i].gnt_wl_sw_en = dm->gnt_set[i].gnt_wl_sw_en;
3727 				mg.band[i].gnt_wl = dm->gnt_set[i].gnt_wl;
3728 				memcpy(o->gnt_set, mg.band, sizeof(o->gnt_set));
3729 			}
3730 			return;
3731 		}
3732 	}
3733 
3734 	for (i = 0; i < RTW89_PHY_NUM; i++) { /* gnt[MAC0/MAC1] */
3735 		mg.band[i].gnt_bt_sw_en = dm->gnt_set[i].gnt_bt0_sw_en;
3736 		mg.band[i].gnt_bt = dm->gnt_set[i].gnt_bt0;
3737 		mg.band[i].gnt_wl_sw_en = dm->gnt_set[i].gnt_wl_sw_en;
3738 		mg.band[i].gnt_wl = dm->gnt_set[i].gnt_wl;
3739 	}
3740 	for (i = 0; i < BTC_ALL_BT; i++) { /* wlact[BT0/BT1] */
3741 		wlact_set = &dm->wlact_set[i];
3742 		mg.bt[i].wlan_act_en = wlact_set->wlan_act_en;
3743 		mg.bt[i].wlan_act = wlact_set->wlan_act;
3744 	}
3745 
3746 	rtw89_chip_mac_cfg_gnt(rtwdev, &mg);
3747 }
3748 
3749 #define BTC_TDMA_WLROLE_MAX 3
3750 
_set_bt_ignore_wlan_act(struct rtw89_dev * rtwdev,u8 enable)3751 static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable)
3752 {
3753 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
3754 		    "[BTC], %s(): set bt %s wlan_act\n", __func__,
3755 		    enable ? "ignore" : "do not ignore");
3756 
3757 	_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1);
3758 }
3759 
3760 #define WL_TX_POWER_NO_BTC_CTRL	GENMASK(31, 0)
3761 #define WL_TX_POWER_ALL_TIME GENMASK(15, 0)
3762 #define WL_TX_POWER_WITH_BT GENMASK(31, 16)
3763 #define WL_TX_POWER_INT_PART GENMASK(8, 2)
3764 #define WL_TX_POWER_FRA_PART GENMASK(1, 0)
3765 #define B_BTC_WL_TX_POWER_SIGN BIT(7)
3766 #define B_TSSI_WL_TX_POWER_SIGN BIT(8)
3767 #define SET_RF_PARA_AX_LEN 1
3768 
_set_wl_tx_power(struct rtw89_dev * rtwdev,u32 level,u8 phy_map)3769 static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level, u8 phy_map)
3770 {
3771 	const struct rtw89_chip_info *chip = rtwdev->chip;
3772 	struct rtw89_btc *btc = &rtwdev->btc;
3773 	const struct rtw89_btc_ver *ver = btc->ver;
3774 	struct rtw89_btc_dm *dm = &btc->dm;
3775 	bool level_chg = false;
3776 	u32 pwr_val;
3777 
3778 	if (phy_map & BIT(RTW89_PHY_0))
3779 		level_chg = !(dm->rf_trx_para.wl_tx_power[RTW89_PHY_0] == level);
3780 
3781 	if (phy_map & BIT(RTW89_PHY_1))
3782 		level_chg |= !(dm->rf_trx_para.wl_tx_power[RTW89_PHY_1] == level);
3783 
3784 	if (!level_chg && !btc->cli_h2c_cmd)
3785 		return;
3786 
3787 	if (phy_map & BIT(RTW89_PHY_0))
3788 		dm->rf_trx_para.wl_tx_power[RTW89_PHY_0] = level;
3789 
3790 	if (phy_map & BIT(RTW89_PHY_1))
3791 		dm->rf_trx_para.wl_tx_power[RTW89_PHY_1] = level;
3792 
3793 	dm->wl_tx_pwr_phy_map = phy_map;
3794 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
3795 		    "[BTC], %s(): phy_map=0x%x, wl_tx_pwr-> phy0=%d, phy1=%d\n",
3796 		    __func__, phy_map,
3797 		    dm->rf_trx_para.wl_tx_power[RTW89_PHY_0],
3798 		    dm->rf_trx_para.wl_tx_power[RTW89_PHY_1]);
3799 
3800 	if ((ver->fcxtrx == 7 && chip->chip_id == RTL8922A) ||
3801 	    ver->fcxtrx == 107) {
3802 		_fw_set_drv_info(rtwdev, CXDRVINFO_TXPWR);
3803 	} else if (ver->fcxtrx == 9) {
3804 		_fw_set_drv_info(rtwdev, CXDRVINFO_TXPWR);
3805 	} else {
3806 		if (level == RTW89_BTC_WL_DEF_TX_PWR) {
3807 			pwr_val = WL_TX_POWER_NO_BTC_CTRL;
3808 		} else { /* only apply "force tx power" */
3809 			pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level);
3810 			if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR)
3811 				pwr_val = RTW89_BTC_WL_DEF_TX_PWR;
3812 
3813 			if (level & B_BTC_WL_TX_POWER_SIGN)
3814 				pwr_val |= B_TSSI_WL_TX_POWER_SIGN;
3815 			pwr_val |= WL_TX_POWER_WITH_BT;
3816 		}
3817 		chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val);
3818 	}
3819 }
3820 
_set_wl_rx_gain(struct rtw89_dev * rtwdev,u32 level,u8 phy_map)3821 static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level, u8 phy_map)
3822 {
3823 	const struct rtw89_chip_info *chip = rtwdev->chip;
3824 	struct rtw89_btc *btc = &rtwdev->btc;
3825 	struct rtw89_btc_dm *dm = &btc->dm;
3826 	bool level_chg = false;
3827 
3828 	if (phy_map & BIT(RTW89_PHY_0))
3829 		level_chg = !(dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0] == level);
3830 
3831 	if (phy_map & BIT(RTW89_PHY_1))
3832 		level_chg |= !(dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1] == level);
3833 
3834 	if (!level_chg && !btc->cli_h2c_cmd)
3835 		return;
3836 
3837 	if (phy_map & BIT(RTW89_PHY_0))
3838 		dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0] = level;
3839 
3840 	if (phy_map & BIT(RTW89_PHY_1))
3841 		dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1] = level;
3842 
3843 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
3844 		    "[BTC], %s(): phy_map=0x%x, wl_rx_gain-> phy0=%d, phy1=%d\n",
3845 		    __func__, phy_map,
3846 		    dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0],
3847 		    dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1]);
3848 
3849 	chip->ops->btc_set_wl_rx_gain(rtwdev, level);
3850 }
3851 
_set_bt_tx_power(struct rtw89_dev * rtwdev,bool force_exec,u8 bid,u8 rf_band,u8 level)3852 static void _set_bt_tx_power(struct rtw89_dev *rtwdev, bool force_exec, u8 bid,
3853 			     u8 rf_band, u8 level)
3854 {
3855 	struct rtw89_btc *btc = &rtwdev->btc;
3856 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
3857 	u8 h2c_func = SET_BT_TX_PWR;
3858 	u8 i, id_start, id_stop;
3859 	u8 buf[2] = {};
3860 	u8 len = sizeof(*buf);
3861 
3862 	if (bt->bcnt[BTC_BCNT_INFOUPDATE] == 0 || !rf_band)
3863 		return;
3864 
3865 	if (bt->rf_para.tx_pwr_freerun == level)
3866 		return;
3867 
3868 	if (bid == BTC_ALL_BT) {
3869 		id_start = BTC_BT_1ST;
3870 		id_stop = BTC_BT_2ND;
3871 	} else {
3872 		id_start = bid;
3873 		id_stop = bid;
3874 	}
3875 
3876 	for (i = id_start; i <= id_stop; i++) {
3877 		if (i == BTC_BT_2ND) {
3878 			if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))
3879 				continue;
3880 
3881 			bt = &btc->cx.bt1;
3882 			h2c_func |= BT_H2C_FUNC_BT2ND;
3883 		}
3884 
3885 		buf[0] = (s8)(-level);
3886 		buf[1] = rf_band;  /* bit-map: bit1->5GHz/6Ghz, bit0->2.4GHz */
3887 
3888 		if (!force_exec && !btc->cli_h2c_cmd) {
3889 			if (rf_band == RTW89_BAND_2G &&
3890 			    bt->tx_power_now == level)
3891 				continue;
3892 			else if (rf_band != RTW89_BAND_2G &&
3893 				 bt->tx_power_now_6g == level)
3894 				continue;
3895 		}
3896 
3897 		if (rtwdev->chip->chip_gen == RTW89_CHIP_AX)
3898 			len = SET_RF_PARA_AX_LEN;
3899 
3900 		if (!_send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, len)) {
3901 			btc->dm.rf_trx_para.bt_tx_power[i] = level;
3902 			if (rf_band == RTW89_BAND_2G)
3903 				bt->tx_power_now = level;
3904 			else
3905 				bt->tx_power_now_6g = level;
3906 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
3907 				    "[BTC], %s(): bt%d_tx_power_level = %d\n",
3908 				    __func__, i, level);
3909 		}
3910 	}
3911 }
3912 
3913 #define BTC_BT_RX_NORMAL_LVL 7
_set_bt_rx_gain(struct rtw89_dev * rtwdev,bool force_exec,u8 bid,u8 rf_band,u8 level)3914 static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, bool force_exec, u8 bid,
3915 			    u8 rf_band, u8 level)
3916 {
3917 	struct rtw89_btc *btc = &rtwdev->btc;
3918 	struct rtw89_btc_cx *cx = &btc->cx;
3919 	struct rtw89_btc_bt_info *bt = &cx->bt0;
3920 	u8 h2c_func = SET_BT_LNA_CONSTRAIN;
3921 	u8 i, id_start, id_stop;
3922 	bool state = false;
3923 	u32 scbd_bit = 0;
3924 	u8 buf[2] = {};
3925 	u8 len = sizeof(*buf);
3926 
3927 	if (bt->bcnt[BTC_BCNT_INFOUPDATE] == 0 || !rf_band)
3928 		return;
3929 
3930 	if (bt->rf_para.rx_gain_freerun == level ||
3931 	    level > BTC_BT_RX_NORMAL_LVL || !rtwdev->chip->scbd ||
3932 	    bid > BTC_ALL_BT)
3933 		return;
3934 
3935 	if (bid == BTC_ALL_BT) {
3936 		id_start = BTC_BT_1ST;
3937 		id_stop = BTC_BT_2ND;
3938 	} else {
3939 		id_start = bid;
3940 		id_stop = bid;
3941 	}
3942 
3943 	if (rf_band == RTW89_BAND_2G)
3944 		scbd_bit |= BTC_WSCB_RXGAIN;
3945 	else
3946 		scbd_bit |= BTC_WSCB_RXGAIN_56G;
3947 
3948 	for (i = id_start; i <= id_stop; i++) {
3949 		if (i == BTC_BT_2ND) {
3950 			if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))
3951 				continue;
3952 
3953 			bt = &cx->bt1;
3954 			h2c_func |= BT_H2C_FUNC_BT2ND;
3955 		}
3956 
3957 		/* return if same setup */
3958 		if (!force_exec && !btc->cli_h2c_cmd) {
3959 			if (rf_band == RTW89_BAND_2G &&
3960 			    bt->lna_constrain == level)
3961 				continue;
3962 			else if (rf_band != RTW89_BAND_2G &&
3963 				 bt->lna_constrain_6g == level)
3964 				continue;
3965 		}
3966 
3967 		buf[0] = level;
3968 		buf[1] = rf_band;
3969 
3970 		if (rtwdev->chip->chip_gen == RTW89_CHIP_AX)
3971 			len = SET_RF_PARA_AX_LEN;
3972 
3973 		if (_send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, len)) {
3974 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
3975 				    "[BTC], %s(): bt%d_rx_gain_level = %d\n",
3976 				    __func__, i, level);
3977 		}
3978 
3979 		btc->dm.rf_trx_para.bt_rx_gain[i] = level;
3980 
3981 		if (buf[0] != BTC_BT_RX_NORMAL_LVL)
3982 			state = true;
3983 
3984 		_write_scbd(rtwdev, bid, scbd_bit, state);
3985 	}
3986 }
3987 
_set_bt_corx_table(struct rtw89_dev * rtwdev,bool en)3988 static void _set_bt_corx_table(struct rtw89_dev *rtwdev, bool en)
3989 {
3990 	struct rtw89_btc *btc = &rtwdev->btc;
3991 	struct rtw89_btc_cx *cx = &btc->cx;
3992 	struct rtw89_btc_bt_info *bt = &cx->bt0;
3993 	struct rtw89_btc_dm *dm = &btc->dm;
3994 	u8 is_24g, is_56g, i;
3995 	u32 scbd_bit;
3996 
3997 	/*
3998 	 * true: bt use Hi-LNA rx gain table (f/e/3/2) in -3x~-9xdBm for co-rx
3999 	 * false: bt use original rx gain table (f/b/7/3/2)
4000 	 */
4001 
4002 	if (btc->dm.fdd_bind.bt_sel == BIT(BTC_BT_EXT))
4003 		return;
4004 
4005 	for (i = BTC_BT_1ST; i <= BTC_BT_2ND; i++) {
4006 		scbd_bit = 0;
4007 		if (i == BTC_BT_2ND) {
4008 			if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))
4009 				continue;
4010 			bt = &cx->bt1;
4011 		}
4012 
4013 		is_24g = (dm->corx_map[BTC_RF_S0][i] ||
4014 			  dm->corx_map[BTC_RF_S1][i]) & BIT(RTW89_BAND_2G);
4015 		is_56g = (dm->corx_map[BTC_RF_S0][i] ||
4016 			  dm->corx_map[BTC_RF_S1][i]) & BIT(RTW89_BAND_5G);
4017 		if (is_24g)
4018 			scbd_bit |= BTC_WSCB_BT_HILNA;
4019 		if (is_56g)
4020 			scbd_bit |= BTC_WSCB_BT_HILNA_56G;
4021 
4022 		if ((is_24g && (en != (!!bt->hi_lna_rx))) ||
4023 		    (is_56g && (en != (!!bt->hi_lna_rx_6g))))
4024 			_write_scbd(rtwdev, i, scbd_bit, en);
4025 	}
4026 }
4027 
_set_rf_trx_para_v9(struct rtw89_dev * rtwdev)4028 static void _set_rf_trx_para_v9(struct rtw89_dev *rtwdev)
4029 {
4030 	struct rtw89_btc *btc = &rtwdev->btc;
4031 	struct rtw89_btc_cx *cx = &btc->cx;
4032 	struct rtw89_btc_wl_smap *wl_smap = &cx->wl.status.map;
4033 	struct rtw89_btc_dm *dm = &btc->dm;
4034 	bool bt_2r = false;
4035 	u8 wl_stb_chg = 0;
4036 
4037 	if (wl_smap->rf_off || wl_smap->lps == BTC_LPS_RF_OFF)
4038 		return;
4039 
4040 	/* must call after _set_halbb_btg_ctrl() */
4041 	if (dm->tdd_bind.wl_link_mode != BTC_WLINK_NOLINK) {
4042 		wl_stb_chg = 1;
4043 		if (dm->wl_btg_rx)
4044 			bt_2r = true;
4045 	}
4046 
4047 	_set_bt_corx_table(rtwdev, bt_2r);
4048 
4049 	if (wl_stb_chg != dm->wl_stb_chg) {
4050 		dm->wl_stb_chg = wl_stb_chg;
4051 		dm->ost_info.wl_btg_standby_chg = wl_stb_chg;
4052 		rtwdev->chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg);
4053 	}
4054 }
4055 
_set_rf_trx_para(struct rtw89_dev * rtwdev)4056 static void _set_rf_trx_para(struct rtw89_dev *rtwdev)
4057 {
4058 	const struct rtw89_chip_info *chip = rtwdev->chip;
4059 	struct rtw89_btc *btc = &rtwdev->btc;
4060 	const struct rtw89_btc_ver *ver = btc->ver;
4061 	struct rtw89_btc_dm *dm = &btc->dm;
4062 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4063 	struct rtw89_btc_wl_role_info *r = &wl->role_info;
4064 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
4065 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
4066 	struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
4067 	struct rtw89_btc_rf_trx_para_v9 para;
4068 	u8 bmode = dm->tdd_bind.wl_link_mode;
4069 	u8 rf_band = dm->tdd_bind.rf_band;
4070 	u8 i, ul_para_num, dl_para_num;
4071 	u8 mode = BTC_WLINK_NOLINK;
4072 	u8 bid = BTC_BT_1ST, lv;
4073 	u32 wl_stb_chg;
4074 
4075 	if (ver->fcxtrx == 9) {
4076 		/* Early v9 need to assign UL/DL RF para at driver */
4077 		if (chip->rf_para_ulink_v9) {
4078 			ul_para_num = chip->rf_para_ulink_num_v9;
4079 			dl_para_num = chip->rf_para_dlink_num_v9;
4080 		} else {
4081 			_set_rf_trx_para_v9(rtwdev);
4082 			return;
4083 		}
4084 	} else if ((ver->fcxtrx == 0 || ver->fcxtrx == 7 || ver->fcxtrx == 107) &&
4085 		   chip->rf_para_ulink_v0) {
4086 		ul_para_num = chip->rf_para_ulink_num_v0;
4087 		dl_para_num = chip->rf_para_dlink_num_v0;
4088 	} else {
4089 		rtw89_warn(rtwdev, "[BTC]%s(), No rf_para for verseion %d\n",
4090 			   __func__, ver->fcxtrx);
4091 		goto next;
4092 	}
4093 
4094 	if (bmode == BTC_WLINK_NOLINK) {
4095 		return;
4096 	} else if (rf_band == RTW89_BAND_5G) {
4097 		mode = BTC_WLINK_V0_5G;
4098 	} else if (rf_band == RTW89_BAND_2G && bmode == BTC_WLINK_STA) {
4099 		mode = BTC_WLINK_V0_2G_STA;
4100 	}
4101 
4102 	/* decide trx_para_level */
4103 	if (btc->ant_type == BTC_ANT_SHARED) {
4104 		/* fix LNA2 + TIA gain not change by GNT_BT */
4105 		if ((btc->dm.wl_btg_rx && b->link_cnt.now != 0) ||
4106 		    dm->bt_only == 1)
4107 			dm->trx_para_level = 1; /* for better BT ACI issue */
4108 		else
4109 			dm->trx_para_level = 0;
4110 	} else { /* non-shared antenna  */
4111 		dm->trx_para_level = 5;
4112 		/* modify trx_para if WK 2.4G-STA-DL + bt link */
4113 		if (b->link_cnt.now != 0 &&
4114 		    mode == BTC_WLINK_V0_2G_STA &&
4115 		    wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { /* uplink */
4116 			if (wl->rssi_level == 4 && bt->rssi_level > 2)
4117 				dm->trx_para_level = 6;
4118 			else if (wl->rssi_level == 3 && bt->rssi_level > 3)
4119 				dm->trx_para_level = 7;
4120 		}
4121 	}
4122 
4123 	lv = dm->trx_para_level;
4124 	if (lv >= ul_para_num ||
4125 	    lv >= dl_para_num) {
4126 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4127 			    "[BTC], %s(): invalid level_id: %d\n",
4128 			    __func__, lv);
4129 		return;
4130 	}
4131 
4132 	if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4133 		if (ver->fcxtrx == 9) {
4134 			para = chip->rf_para_ulink_v9[lv];
4135 		} else {
4136 			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) {
4137 				para.wl_tx_power[i] = chip->rf_para_ulink_v0[lv].wl_tx_power;
4138 				para.wl_rx_gain[i] = chip->rf_para_ulink_v0[lv].wl_rx_gain;
4139 			}
4140 			for (i = BTC_BT_1ST; i < BTC_ALL_BT; i++) {
4141 				para.bt_tx_power[i] = chip->rf_para_ulink_v0[lv].bt_tx_power;
4142 				para.bt_rx_gain[i] = chip->rf_para_ulink_v0[lv].bt_rx_gain;
4143 			}
4144 		}
4145 	} else {
4146 		if (ver->fcxtrx == 9) {
4147 			para = chip->rf_para_dlink_v9[lv];
4148 		} else {
4149 			for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) {
4150 				para.wl_tx_power[i] = chip->rf_para_dlink_v0[lv].wl_tx_power;
4151 				para.wl_rx_gain[i] = chip->rf_para_dlink_v0[lv].wl_rx_gain;
4152 			}
4153 			for (i = BTC_BT_1ST; i < BTC_ALL_BT; i++) {
4154 				para.bt_tx_power[i] = chip->rf_para_dlink_v0[lv].bt_tx_power;
4155 				para.bt_rx_gain[i] = chip->rf_para_dlink_v0[lv].bt_rx_gain;
4156 			}
4157 		}
4158 	}
4159 
4160 	if (dm->fddt_train) {
4161 		_set_wl_rx_gain(rtwdev, 1, RTW89_PHY_0);
4162 		_write_scbd(rtwdev, bid, BTC_WSCB_RXGAIN, true);
4163 	} else {
4164 		_set_wl_tx_power(rtwdev, para.wl_tx_power[RTW89_PHY_0], RTW89_PHY_0);
4165 		_set_wl_rx_gain(rtwdev, para.wl_rx_gain[RTW89_PHY_0], RTW89_PHY_0);
4166 		_set_bt_tx_power(rtwdev, true, bid, rf_band, para.bt_tx_power[BTC_BT_1ST]);
4167 		_set_bt_rx_gain(rtwdev, true, bid, rf_band, para.bt_rx_gain[BTC_BT_1ST]);
4168 	}
4169 
4170 next:
4171 	if (!bt->enable.now || dm->wl_only || wl_smap->rf_off ||
4172 	    wl_smap->lps == BTC_LPS_RF_OFF || mode == BTC_WLINK_V0_5G ||
4173 	    (rtwdev->dbcc_en && r->dbcc_2g_phy != RTW89_PHY_1))
4174 		wl_stb_chg = 0;
4175 	else
4176 		wl_stb_chg = 1;
4177 
4178 	if (wl_stb_chg != dm->wl_stb_chg) {
4179 		dm->wl_stb_chg = wl_stb_chg;
4180 		chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg);
4181 	}
4182 }
4183 
_update_btc_state_map(struct rtw89_dev * rtwdev)4184 static void _update_btc_state_map(struct rtw89_dev *rtwdev)
4185 {
4186 	struct rtw89_btc *btc = &rtwdev->btc;
4187 	struct rtw89_btc_cx *cx = &btc->cx;
4188 	struct rtw89_btc_wl_info *wl = &cx->wl;
4189 	struct rtw89_btc_bt_info *bt = &cx->bt0;
4190 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
4191 
4192 	if (wl->status.map.dhcp || wl->status.map._4way ||
4193 	    wl->status.map.roaming || wl->status.map.transacting ||
4194 	    wl->status.map.handshake) {
4195 		cx->state_map = BTC_WLINKING;
4196 	} else if (wl->status.map.scan) { /* wl scan */
4197 		if (bt_linfo->status.map.inq_pag)
4198 			cx->state_map = BTC_WSCAN_BSCAN;
4199 		else
4200 			cx->state_map = BTC_WSCAN_BNOSCAN;
4201 	} else if (wl->status.map.busy) { /* only busy */
4202 		if (bt_linfo->status.map.inq_pag)
4203 			cx->state_map = BTC_WBUSY_BSCAN;
4204 		else
4205 			cx->state_map = BTC_WBUSY_BNOSCAN;
4206 	} else { /* wl idle */
4207 		cx->state_map = BTC_WIDLE;
4208 	}
4209 }
4210 
_get_wl_guard_bw(struct rtw89_dev * rtwdev,u8 index)4211 static u8 _get_wl_guard_bw(struct rtw89_dev *rtwdev, u8 index)
4212 {
4213 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4214 	u8 guard_ch = rtwdev->chip->afh_guard_ch;
4215 	u8 bw = 0;
4216 
4217 	/* default AFH channel sapn = center-ch +- 6MHz  */
4218 	switch (index) {
4219 	case RTW89_CHANNEL_WIDTH_20:
4220 		if (dm->freerun || dm->fddt_train)
4221 			bw = 48;
4222 		else
4223 			bw = 20 + guard_ch * 2;
4224 		break;
4225 	case RTW89_CHANNEL_WIDTH_40:
4226 		bw = 40 + guard_ch * 2;
4227 		break;
4228 	case RTW89_CHANNEL_WIDTH_80:
4229 		bw = 80 + guard_ch * 2;
4230 		break;
4231 	case RTW89_CHANNEL_WIDTH_160:
4232 	case RTW89_CHANNEL_WIDTH_80_80:
4233 		bw = 160 + guard_ch * 2;
4234 		break;
4235 	case RTW89_CHANNEL_WIDTH_320:
4236 		bw = 320 + guard_ch * 2;
4237 		break;
4238 	case RTW89_CHANNEL_WIDTH_5:
4239 		bw = 5 + guard_ch * 2;
4240 		break;
4241 	case RTW89_CHANNEL_WIDTH_10:
4242 		bw = 10 + guard_ch * 2;
4243 		break;
4244 	default:
4245 		bw = 0;
4246 		break;
4247 	}
4248 
4249 	return bw;
4250 }
4251 
_set_wl_ch_map(struct rtw89_dev * rtwdev)4252 static void _set_wl_ch_map(struct rtw89_dev *rtwdev)
4253 {
4254 	struct rtw89_btc *btc = &rtwdev->btc;
4255 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4256 	struct rtw89_btc_wl_afh_info *afh;
4257 	u16 ch_start, ch_end, i;
4258 	u8 b_group, b_pos; /* byte-group, bit-position */
4259 	u8 hwb;
4260 
4261 	if (wl->afh_info[RTW89_MAC_0][RTW89_BAND_2G].en &&
4262 	    wl->afh_info[RTW89_MAC_1][RTW89_BAND_2G].en) {
4263 		/* select wilder bw if 1+1 */
4264 		if (wl->afh_info[RTW89_MAC_1][RTW89_BAND_2G].bw >
4265 		    wl->afh_info[RTW89_MAC_0][RTW89_BAND_2G].bw)
4266 			hwb = RTW89_MAC_1;
4267 		else
4268 			hwb = RTW89_MAC_0;
4269 	} else if (wl->afh_info[RTW89_MAC_1][RTW89_BAND_2G].en) {
4270 		hwb = RTW89_MAC_1;
4271 	} else {
4272 		hwb = RTW89_MAC_0;
4273 	}
4274 
4275 	afh = &wl->afh_info[hwb][RTW89_BAND_2G];
4276 
4277 	/* focus on WL 2.4GHz link */
4278 	if (!afh->en || afh->band != RTW89_BAND_2G)
4279 		return;
4280 
4281 	memset(wl->ch_map, 0x0, sizeof(wl->ch_map));
4282 	memset(wl->ch_map_le, 0x0, sizeof(wl->ch_map_le));
4283 
4284 	ch_start = afh->ch * 5 + 2407 - afh->bw / 2;
4285 	ch_end = ch_start + afh->bw;
4286 
4287 	for (i = ch_start; i < ch_end; i++) {
4288 		if (i < 2402 || i > 2480)
4289 			continue;
4290 		b_group = (i - 2402) / 8;
4291 		b_pos = 7 - ((i - 2402) % 8);
4292 		wl->ch_map[b_group] |= BIT(b_pos);
4293 
4294 		if (i % 2)  /* BLE ch = even-freq (ex:2402,2404) */
4295 			continue;
4296 
4297 		b_group = (i - 2402) / 16;
4298 		b_pos = 7 - (((i - 2402) / 2) % 8);
4299 		wl->ch_map_le[b_group] |= BIT(b_pos);
4300 	}
4301 }
4302 
_get_w2b_fbd_ch(struct rtw89_dev * rtwdev,u8 bt_fb_band,u32 wl_vco_freq,u32 * ch_lo_bound,u32 * ch_up_bound)4303 static u8 _get_w2b_fbd_ch(struct rtw89_dev *rtwdev,
4304 			  u8 bt_fb_band, u32 wl_vco_freq,
4305 			  u32 *ch_lo_bound, u32 *ch_up_bound)
4306 {
4307 	u32 ch_lo, ch_pup, ch_min, ch_max;
4308 	u8 out_of_range = 0;
4309 	s32 val_lo, val_up;
4310 	u32 vco_lo_in_KHz; /* VCO pulling lower bound */
4311 	u32 vco_up_in_KHz; /* VCO pulling Upper bound */
4312 	u32 freq_start;
4313 
4314 	vco_lo_in_KHz = wl_vco_freq - BTC_VCO_GUARD_W2B * 1000; /* KHz */
4315 	vco_up_in_KHz = wl_vco_freq + BTC_VCO_GUARD_W2B * 1000;
4316 
4317 	switch (bt_fb_band) {
4318 	default:
4319 	case BTC_BT_B2G: /* BT 2GHz forbiddened Channel */
4320 		val_lo = vco_lo_in_KHz * BTC_LO_2G_DNM / BTC_LO_2G_NMR;
4321 		val_up = vco_up_in_KHz * BTC_LO_2G_DNM / BTC_LO_2G_NMR;
4322 		freq_start = BTC_FREQ_B2G * 1000; /* KHz */
4323 		ch_min = BTC_CH_B2G_MIN;
4324 		ch_max = BTC_CH_B2G_MAX;
4325 		break;
4326 	case BTC_BT_B5G: /* BT 5/6GHz forbiddened Channel */
4327 		val_lo = vco_lo_in_KHz * BTC_LO_6G_DNM / BTC_LO_6G_NMR;
4328 		val_up = vco_up_in_KHz * BTC_LO_6G_DNM / BTC_LO_6G_NMR;
4329 		freq_start = BTC_FREQ_B6G * 1000; /* KHz */
4330 		ch_min = BTC_CH_B5G_MIN;
4331 		ch_max = BTC_CH_B5G_MAX;
4332 		break;
4333 	}
4334 
4335 	/* Search forbiddened Channel (un-process range)*/
4336 	ch_lo = (val_lo - freq_start) / 1000;
4337 	if ((val_lo - freq_start) % 1000 != 0) /* Round-UP */
4338 		ch_lo++;
4339 
4340 	ch_pup = (val_up - freq_start) / 1000; /* Round-down */
4341 
4342 	/* Search forbiddened Channel */
4343 	if (ch_lo > ch_max || ch_pup < ch_min) { /* out-of-range -> NA */
4344 		out_of_range = 1;
4345 		*ch_lo_bound = 0;
4346 		*ch_up_bound = 0;
4347 	}
4348 
4349 	if (ch_lo < ch_min)
4350 		*ch_lo_bound = ch_min;
4351 	else if (ch_lo <= ch_max)
4352 		*ch_lo_bound = ch_lo;
4353 
4354 	if (ch_pup > ch_max)
4355 		*ch_up_bound = ch_max;
4356 	else if (ch_pup >= ch_min)
4357 		*ch_up_bound = ch_pup;
4358 
4359 	if (bt_fb_band == BTC_BT_B5G) { /* BT ch is 8MHz-spacing for 5/6GHz */
4360 		*ch_lo_bound = *ch_lo_bound / 8; /* low-bound -> Round-down */
4361 
4362 		if (*ch_up_bound % 8 != 0) /* Up-bound -> cover wider range */
4363 			*ch_up_bound = *ch_up_bound / 8 + 1;
4364 		else
4365 			*ch_up_bound = *ch_up_bound / 8;
4366 	}
4367 
4368 	return out_of_range;
4369 }
4370 
_set_wl_ch_info(struct rtw89_dev * rtwdev)4371 static void _set_wl_ch_info(struct rtw89_dev *rtwdev)
4372 {
4373 	static const u8 path_hwb[BTC_RF_NUM] = {RTW89_PHY_0, RTW89_PHY_1};
4374 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4375 	struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
4376 	struct rtw89_btc_wl_info *wl = &cx->wl;
4377 	u32 vco_freq, ch_lo = 0, ch_up = 0;
4378 	u16 rf_band, freq, f_diff;
4379 	u8 i, j, ch;
4380 
4381 	if (!(rtwdev->chip->para_ver & BTC_FEAT_MULTI_PTA)) /* only new-PTA require setup */
4382 		return;
4383 
4384 	for (i = RTW89_PHY_0; i <= RTW89_PHY_1; i++) {
4385 		if (wl->mlo_info.wmode[i] == RTW89_MR_WMODE_NONE) { /* no-connect */
4386 			dm->ost_info.rf_center_freq[i] = 0;
4387 			dm->ost_info.fbd_group_en[i][0] = 0;
4388 			dm->ost_info.fbd_group_en[i][1] = 0;
4389 			dm->ost_info.fbd_group_bound[i][0] = 0;
4390 			dm->ost_info.fbd_group_bound[i][1] = 0;
4391 			continue;
4392 		}
4393 
4394 		ch = wl->rf_ch_info[i].center_ch;
4395 		switch (wl->rf_ch_info[i].band) {
4396 		case RTW89_BAND_2G:
4397 		default:
4398 			rf_band = 0;
4399 			if (ch == 14)
4400 				freq = BTC_FREQ_W2G_CH14;
4401 			else
4402 				freq = BTC_FREQ_W2G + (ch - 1) * 5;
4403 			vco_freq = freq * 1000 * BTC_LO_2G_NMR / BTC_LO_2G_DNM;
4404 			break;
4405 		case RTW89_BAND_5G:
4406 			rf_band = BIT(15);
4407 			freq = BTC_FREQ_W5G + (ch - 1) * 5;
4408 			vco_freq = freq * 1000 * BTC_LO_5G_NMR / BTC_LO_5G_DNM;
4409 			break;
4410 		case RTW89_BAND_6G:
4411 			rf_band = BIT(15);
4412 			freq = BTC_FREQ_W6G + (ch - 1) * 5;
4413 			vco_freq = freq * 1000 * BTC_LO_6G_NMR / BTC_LO_6G_DNM;
4414 			break;
4415 		}
4416 
4417 		dm->ost_info.rf_center_freq[i] = rf_band + freq;
4418 
4419 		for (j = BTC_BT_B2G; j <= BTC_BT_B5G; j++) {
4420 			/* no WL->BT forbidden channel */
4421 			if (_get_w2b_fbd_ch(rtwdev, j, vco_freq, &ch_lo, &ch_up)) {
4422 				dm->ost_info.fbd_group_en[i][j] = j << 1;
4423 				dm->ost_info.fbd_group_bound[i][j] = 0;
4424 				continue;
4425 			}
4426 
4427 			dm->ost_info.fbd_group_en[i][j] = (j << 1) + 0x1;
4428 			dm->ost_info.fbd_group_bound[i][j] = (ch_up << 8) + ch_lo;
4429 		}
4430 	}
4431 
4432 	for (i = BTC_RF_S0; i <= BTC_RF_S1; i++) {
4433 		for (j = BTC_BT_1ST; j <= BTC_BT_EXT; j++) {
4434 			/*
4435 			 * If WL & BT share same ANT/Path, set freq-diff > 2GHz,
4436 			 * because TDD will always run in 5/6GHz band.
4437 			 * Otherwise, the frq-diff thres is decided by the RF
4438 			 * out-of-channel rejection capability.
4439 			 */
4440 			if (dm->ant_xmap[i][j])
4441 				f_diff = 0x7ff; /* 2047MHz */
4442 			else
4443 				f_diff = rtwdev->chip->fdd_iso_freq;
4444 
4445 			dm->ost_info.freq_diff_thres[path_hwb[i]][j] = f_diff;
4446 		}
4447 	}
4448 }
4449 
_set_bt_afh_info(struct rtw89_dev * rtwdev)4450 static void _set_bt_afh_info(struct rtw89_dev *rtwdev)
4451 {
4452 	struct rtw89_btc *btc = &rtwdev->btc;
4453 	struct rtw89_btc_cx *cx = &btc->cx;
4454 	struct rtw89_btc_wl_info *wl = &cx->wl;
4455 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
4456 	struct rtw89_btc_wl_rlink *rlink;
4457 	u8 h2c_func, hwb, bt_link_chg;
4458 	u8 i, j, sz, bw;
4459 	u8 buf[4];
4460 
4461 	if (btc->manual_ctrl || wl->status.map.rf_off ||
4462 	    (wl->status.val & btc_scanning_map.val))
4463 		return;
4464 
4465 	memset(wl->afh_info, 0, sizeof(wl->afh_info));
4466 
4467 	for (j = RTW89_MAC_0; j < RTW89_MAC_NUM; j++) {
4468 		/* skip HW-Band if no fdd/fdd bind */
4469 		if ((!(btc->dm.tdd_bind.wl_hwb_sel & BIT(j))) &&
4470 		    (!(btc->dm.fdd_bind.wl_hwb_sel & BIT(j))))
4471 			continue;
4472 
4473 		for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
4474 			rlink = &wl_rinfo->rlink[i][j];
4475 
4476 			/* Skip no-active case */
4477 			if (!rlink->connected || !rlink->active ||
4478 			    rlink->rf_band >= RTW89_BAND_NUM)
4479 				continue;
4480 
4481 			/* In addition to AP/P2P, skip if same-rf-band*/
4482 			if (wl->afh_info[j][rlink->rf_band].en &&
4483 			    (rlink->role != RTW89_WIFI_ROLE_AP &&
4484 			     rlink->role != RTW89_WIFI_ROLE_P2P_GO &&
4485 			     rlink->role != RTW89_WIFI_ROLE_P2P_CLIENT))
4486 				continue;
4487 
4488 			bw = _get_wl_guard_bw(rtwdev, rlink->bw);
4489 			wl->afh_info[j][rlink->rf_band].en = 1;
4490 			wl->afh_info[j][rlink->rf_band].ch = rlink->ch;
4491 			wl->afh_info[j][rlink->rf_band].bw = bw;
4492 			wl->afh_info[j][rlink->rf_band].band = rlink->rf_band;
4493 		}
4494 	}
4495 
4496 	for (j = RTW89_BAND_2G; j < RTW89_BAND_NUM; j++) {
4497 		/* skip non-2.4GHz if BT is 2.4GHz only*/
4498 		if (!(rtwdev->chip->para_ver &  BTC_FEAT_BT_6G)) {
4499 			if (j != RTW89_BAND_2G)
4500 				continue;
4501 			sz = 3;
4502 		} else {
4503 			sz = 4;
4504 		}
4505 
4506 		if (wl->afh_info[RTW89_MAC_0][j].en &&
4507 		    wl->afh_info[RTW89_MAC_1][j].en) {
4508 			/* select wilder bw if 1+1 */
4509 			if (wl->afh_info[RTW89_MAC_1][j].bw >
4510 			    wl->afh_info[RTW89_MAC_0][j].bw)
4511 				hwb = RTW89_MAC_1;
4512 			else
4513 				hwb = RTW89_MAC_0;
4514 		} else if (wl->afh_info[RTW89_MAC_1][j].en) {
4515 			hwb = RTW89_MAC_1;
4516 		} else {
4517 			hwb = RTW89_MAC_0;
4518 		}
4519 
4520 		if (j == RTW89_BAND_2G) {
4521 			if (cx->bt0.link_info.link_cnt.chg ||
4522 			    cx->bt1.link_info.link_cnt.chg)
4523 				bt_link_chg = 1;
4524 			else
4525 				bt_link_chg = 0;
4526 		} else {
4527 			if (cx->bt0.link_info_56g.link_cnt.chg ||
4528 			    cx->bt1.link_info_56g.link_cnt.chg)
4529 				bt_link_chg = 1;
4530 			else
4531 				bt_link_chg = 0;
4532 		}
4533 
4534 		/* return if no-afh-info-change/no wl-bt link change */
4535 		if (!memcmp(&wl->afh_info_last[hwb][j],
4536 			    &wl->afh_info[hwb][j],
4537 			    sizeof(struct rtw89_btc_wl_afh_info)) &&
4538 			    !bt_link_chg &&
4539 			    !wl->link_mode_chg)
4540 			continue;
4541 
4542 		memcpy(&wl->afh_info_last[hwb][j],
4543 		       &wl->afh_info[hwb][j],
4544 		       sizeof(struct rtw89_btc_wl_afh_info));
4545 
4546 		buf[0] = wl->afh_info[hwb][j].en;
4547 		buf[1] = wl->afh_info[hwb][j].ch;
4548 		buf[2] = wl->afh_info[hwb][j].bw;
4549 		buf[3] = wl->afh_info[hwb][j].band;
4550 
4551 		h2c_func = SET_BT_WL_CH_INFO;
4552 		if (cx->bt0.enable.now)
4553 			_send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, sz);
4554 
4555 		/* send mailbox to 2nd-BT if exist */
4556 		if (cx->bt1.enable.now) {
4557 			h2c_func |= BT_H2C_FUNC_BT2ND;
4558 			_send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, sz);
4559 		}
4560 
4561 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
4562 			    "[BTC], %s(): en=%d, ch=%d, bw=%d, rf_band=%d\n",
4563 			    __func__, buf[0], buf[1], buf[2], buf[3]);
4564 
4565 		wl->wcnt[BTC_WCNT_CH_UPDATE]++;
4566 
4567 		/* ToDo: Remove if BT update new-define to support 6GHz */
4568 		if (j == RTW89_BAND_2G)
4569 			break;
4570 	}
4571 
4572 	/* for AFH map display in coex log */
4573 	_set_wl_ch_map(rtwdev);
4574 
4575 	/* set HWB center-ch/forbidden group to ost_info for CR setup in FW */
4576 	_set_wl_ch_info(rtwdev);
4577 }
4578 
_check_freerun(struct rtw89_dev * rtwdev)4579 static bool _check_freerun(struct rtw89_dev *rtwdev)
4580 {
4581 	struct rtw89_btc *btc = &rtwdev->btc;
4582 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4583 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
4584 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
4585 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
4586 	struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc;
4587 	struct rtw89_btc_module *md = &btc->mdinfo;
4588 
4589 	if (btc->ant_type == BTC_ANT_SHARED) {
4590 		btc->dm.trx_para_level = 0;
4591 		return false;
4592 	}
4593 
4594 	/* The below is dedicated antenna case */
4595 	if (wl_rinfo->connect_cnt > BTC_TDMA_WLROLE_MAX) {
4596 		btc->dm.trx_para_level = 5;
4597 		return true;
4598 	}
4599 
4600 	if (bt_linfo->link_cnt.now == 0) {
4601 		btc->dm.trx_para_level = 5;
4602 		return true;
4603 	}
4604 
4605 	if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) {
4606 		btc->dm.trx_para_level = 5;
4607 		return true;
4608 	}
4609 
4610 	/* TODO get isolation by BT psd */
4611 	if (md->ant.isolation >= BTC_FREERUN_ANTISO_MIN) {
4612 		btc->dm.trx_para_level = 5;
4613 		return true;
4614 	}
4615 
4616 	if (!wl->status.map.busy) {/* wl idle -> freerun */
4617 		btc->dm.trx_para_level = 5;
4618 		return true;
4619 	} else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */
4620 		btc->dm.trx_para_level = 0;
4621 		return false;
4622 	} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4623 		if (wl->rssi_level == 0 && bt_linfo->rssi > 31) {
4624 			btc->dm.trx_para_level = 6;
4625 			return true;
4626 		} else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) {
4627 			btc->dm.trx_para_level = 7;
4628 			return true;
4629 		}
4630 		btc->dm.trx_para_level = 0;
4631 		return false;
4632 	} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) {
4633 		if (bt_linfo->rssi > 28) {
4634 			btc->dm.trx_para_level = 6;
4635 			return true;
4636 		}
4637 	}
4638 
4639 	btc->dm.trx_para_level = 0;
4640 	return false;
4641 }
4642 
4643 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; })
4644 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; })
4645 #define _tdma_set_rxflctrl(btc, rxflc) ({(btc)->dm.tdma.rxflctrl = rxflc; })
4646 #define _tdma_set_txflctrl(btc, txflc) ({(btc)->dm.tdma.txflctrl = txflc; })
4647 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; })
4648 
4649 struct btc_btinfo_lb2 {
4650 	u8 connect: 1;
4651 	u8 sco_busy: 1;
4652 	u8 inq_pag: 1;
4653 	u8 acl_busy: 1;
4654 	u8 hfp: 1;
4655 	u8 hid: 1;
4656 	u8 a2dp: 1;
4657 	u8 pan: 1;
4658 };
4659 
4660 struct btc_btinfo_lb3 {
4661 	u8 retry: 4;
4662 	u8 cqddr: 1;
4663 	u8 inq: 1;
4664 	u8 mesh_busy: 1;
4665 	u8 pag: 1;
4666 };
4667 
4668 struct btc_btinfo_hb0 {
4669 	s8 rssi;
4670 };
4671 
4672 struct btc_btinfo_hb1 {
4673 	u8 ble_connect: 1;
4674 	u8 reinit: 1;
4675 	u8 relink: 1;
4676 	u8 igno_wl: 1;
4677 	u8 voice: 1;
4678 	u8 ble_scan: 1;
4679 	u8 role_sw: 1;
4680 	u8 multi_link: 1;
4681 };
4682 
4683 struct btc_btinfo_hb2 {
4684 	u8 pan_active: 1;
4685 	u8 afh_update: 1;
4686 	u8 a2dp_active: 1;
4687 	u8 slave: 1;
4688 	u8 hid_slot: 2;
4689 	u8 hid_cnt: 2;
4690 };
4691 
4692 struct btc_btinfo_hb3 {
4693 	u8 a2dp_bitpool: 6;
4694 	u8 tx_3m: 1;
4695 	u8 a2dp_sink: 1;
4696 };
4697 
4698 union btc_btinfo {
4699 	u8 val;
4700 	struct btc_btinfo_lb2 lb2;
4701 	struct btc_btinfo_lb3 lb3;
4702 	struct btc_btinfo_hb0 hb0;
4703 	struct btc_btinfo_hb1 hb1;
4704 	struct btc_btinfo_hb2 hb2;
4705 	struct btc_btinfo_hb3 hb3;
4706 };
4707 
_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)4708 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
4709 			enum btc_reason_and_action action)
4710 {
4711 	const struct rtw89_chip_info *chip = rtwdev->chip;
4712 
4713 	chip->ops->btc_set_policy(rtwdev, policy_type);
4714 	_fw_set_policy(rtwdev, policy_type, action);
4715 }
4716 
_set_tdma_bind(struct rtw89_dev * rtwdev,bool tdma_on)4717 static void _set_tdma_bind(struct rtw89_dev *rtwdev, bool tdma_on)
4718 {
4719 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4720 	struct rtw89_btc_bind_info *bind;
4721 	u8 null_role = RTW89_WIFI_ROLE_STATION;
4722 	u8 bt_sel;
4723 
4724 	if (dm->tdd_en)
4725 		bind = &dm->tdd_bind; /* tdd = 1 && fdd = 0 or 1 */
4726 	else
4727 		bind = &dm->fdd_bind; /* tdd = 0 && fdd = 1 */
4728 
4729 	if (bind->bt_sel >= (BIT(BTC_BT_1ST) | BIT(BTC_BT_2ND)))
4730 		bt_sel = BTC_ALL_BT;
4731 	else if (bind->bt_sel == BIT(BTC_BT_2ND))
4732 		bt_sel = BTC_BT_2ND;
4733 	else
4734 		bt_sel = BTC_BT_1ST;
4735 
4736 	/* notify BT TDMA on/off by scoreboard for ACL/Scan schedule */
4737 	_write_scbd(rtwdev, bt_sel, BTC_WSCB_TDMA, tdma_on);
4738 
4739 	/*
4740 	 * set hwb/bt bind to TDMA policy parameter
4741 	 * FW-BTC will setup related hwbx vs. BTx coex tables by slot toggle
4742 	 * ex: HWb0 + BT0 + BT1, HWB0-BT0/HWB0-BT1 coex by WL/BT slot toggle
4743 	 */
4744 	dm->tdma.bind = ((bind->bt_sel & 0xf) << 4) + (bind->wl_hwb_sel & 0x3);
4745 	if (dm->tdd_en)
4746 		dm->tdma.bind |= BIT(2);
4747 	if (dm->fdd_en)
4748 		dm->tdma.bind |= BIT(3);
4749 	if (rtwdev->btc.ver->fcxtdma != 8)
4750 		dm->tdma.bind |= 0;
4751 
4752 	/* set Null-tx role for 2 HW-BAND TDMA (MLMR) */
4753 	if (!dm->eslot_ctrl.en && dm->tdma.rxflctrl &&
4754 	    (bind->wl_hwb_sel == (BIT(RTW89_PHY_1) | BIT(RTW89_PHY_0)))) {
4755 		null_role = (null_role << 4) + null_role;
4756 		_tdma_set_flctrl_role(&rtwdev->btc, null_role);
4757 	}
4758 }
4759 
4760 #define BTC_B1_MAX 250 /* unit ms */
rtw89_btc_set_policy(struct rtw89_dev * rtwdev,u16 policy_type)4761 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type)
4762 {
4763 	struct rtw89_btc *btc = &rtwdev->btc;
4764 	struct rtw89_btc_dm *dm = &btc->dm;
4765 	struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
4766 	u8 type;
4767 	u32 tbl_w1, tbl_b1, tbl_b4;
4768 	bool tdma_on = false;
4769 
4770 	if (btc->ant_type == BTC_ANT_SHARED) {
4771 		if (btc->cx.wl.status.map._4way)
4772 			tbl_w1 = cxtbl[1];
4773 		else
4774 			tbl_w1 = cxtbl[8];
4775 		tbl_b1 = cxtbl[3];
4776 		tbl_b4 = cxtbl[3];
4777 	} else {
4778 		tbl_w1 = cxtbl[16];
4779 		tbl_b1 = cxtbl[17];
4780 		tbl_b4 = cxtbl[17];
4781 	}
4782 
4783 	type = (u8)((policy_type & BTC_CXP_MASK) >> 8);
4784 	btc->bt_req_en = false;
4785 
4786 	switch (type) {
4787 	case BTC_CXP_USERDEF0:
4788 		*t = t_def[CXTD_OFF];
4789 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4790 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4791 		_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
4792 		btc->update_policy_force = true;
4793 		break;
4794 	case BTC_CXP_OFF: /* TDMA off */
4795 		tdma_on = false;
4796 		*t = t_def[CXTD_OFF];
4797 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4798 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4799 
4800 		switch (policy_type) {
4801 		case BTC_CXP_OFF_BT:
4802 			_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
4803 			break;
4804 		case BTC_CXP_OFF_WL:
4805 			_slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
4806 			break;
4807 		case BTC_CXP_OFF_EQ0:
4808 			_slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
4809 			break;
4810 		case BTC_CXP_OFF_EQ1:
4811 			_slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
4812 			break;
4813 		case BTC_CXP_OFF_EQ2:
4814 			_slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
4815 			break;
4816 		case BTC_CXP_OFF_EQ3:
4817 			_slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
4818 			break;
4819 		case BTC_CXP_OFF_BWB0:
4820 			_slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
4821 			break;
4822 		case BTC_CXP_OFF_BWB1:
4823 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
4824 			break;
4825 		case BTC_CXP_OFF_BWB3:
4826 			_slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
4827 			break;
4828 		}
4829 		break;
4830 	case BTC_CXP_OFFB: /* TDMA off + beacon protect */
4831 		tdma_on = false;
4832 		*t = t_def[CXTD_OFF_B2];
4833 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4834 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4835 		_slot_set(btc, CXST_B2, 10, cxtbl[1], SLOT_ISO);
4836 
4837 		switch (policy_type) {
4838 		case BTC_CXP_OFFB_BWB0:
4839 			_slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
4840 			break;
4841 		case BTC_CXP_OFFB_BWB1:
4842 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
4843 			break;
4844 		case BTC_CXP_OFFB_BWB2:
4845 			_slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
4846 			break;
4847 		case BTC_CXP_OFFB_BWB3:
4848 			_slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
4849 			break;
4850 		case BTC_CXP_OFFB_BWB4:
4851 			_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
4852 			break;
4853 		}
4854 		break;
4855 	case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
4856 		btc->bt_req_en = true;
4857 		tdma_on = true;
4858 		*t = t_def[CXTD_OFF_EXT];
4859 		switch (policy_type) {
4860 		case BTC_CXP_OFFE_DEF:
4861 			_slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
4862 				     s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
4863 			_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4864 				     s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4865 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4866 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4867 			_slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
4868 				     s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
4869 			break;
4870 		case BTC_CXP_OFFE_DEF2:
4871 			_slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
4872 			_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4873 				     s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4874 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4875 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4876 			_slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
4877 				     s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
4878 			break;
4879 		}
4880 		break;
4881 	case BTC_CXP_FIX: /* TDMA Fix-Slot */
4882 		tdma_on = true;
4883 		*t = t_def[CXTD_FIX];
4884 		switch (policy_type) {
4885 		case BTC_CXP_FIX_TD3030:
4886 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4887 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4888 			break;
4889 		case BTC_CXP_FIX_TD5050:
4890 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4891 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
4892 			break;
4893 		case BTC_CXP_FIX_TD2030:
4894 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4895 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4896 			break;
4897 		case BTC_CXP_FIX_TD4010:
4898 			_slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
4899 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4900 			break;
4901 		case BTC_CXP_FIX_TD4010ISO:
4902 			_slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
4903 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4904 			break;
4905 		case BTC_CXP_FIX_TD4010ISO_DL:
4906 			_slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
4907 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
4908 			break;
4909 		case BTC_CXP_FIX_TD4010ISO_UL:
4910 			_slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
4911 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
4912 			break;
4913 		case BTC_CXP_FIX_TD7010:
4914 			_slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
4915 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4916 			break;
4917 		case BTC_CXP_FIX_TD2060:
4918 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4919 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4920 			break;
4921 		case BTC_CXP_FIX_TD3060:
4922 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4923 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4924 			break;
4925 		case BTC_CXP_FIX_TD2080:
4926 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4927 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
4928 			break;
4929 		case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
4930 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4931 				  tbl_w1, SLOT_ISO);
4932 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4933 				  tbl_b1, SLOT_MIX);
4934 			break;
4935 		}
4936 		break;
4937 	case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
4938 		tdma_on = true;
4939 		*t = t_def[CXTD_PFIX];
4940 		if (btc->cx.wl.role_info.role_map  & BIT(RTW89_WIFI_ROLE_AP))
4941 			_tdma_set_flctrl(btc, CXFLC_QOSNULL);
4942 
4943 		switch (policy_type) {
4944 		case BTC_CXP_PFIX_TD3030:
4945 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4946 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4947 			break;
4948 		case BTC_CXP_PFIX_TD5050:
4949 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4950 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
4951 			break;
4952 		case BTC_CXP_PFIX_TD2030:
4953 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4954 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4955 			break;
4956 		case BTC_CXP_PFIX_TD2060:
4957 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4958 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4959 			break;
4960 		case BTC_CXP_PFIX_TD3070:
4961 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4962 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4963 			break;
4964 		case BTC_CXP_PFIX_TD2080:
4965 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4966 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
4967 			break;
4968 		}
4969 		break;
4970 	case BTC_CXP_AUTO: /* TDMA Auto-Slot */
4971 		tdma_on = true;
4972 		*t = t_def[CXTD_AUTO];
4973 		switch (policy_type) {
4974 		case BTC_CXP_AUTO_TD50B1:
4975 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4976 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4977 			break;
4978 		case BTC_CXP_AUTO_TD60B1:
4979 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4980 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4981 			break;
4982 		case BTC_CXP_AUTO_TD20B1:
4983 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4984 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4985 			break;
4986 		case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
4987 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4988 				  tbl_w1, SLOT_ISO);
4989 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4990 				  tbl_b1, SLOT_MIX);
4991 			break;
4992 		}
4993 		break;
4994 	case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
4995 		tdma_on = true;
4996 		*t = t_def[CXTD_PAUTO];
4997 		switch (policy_type) {
4998 		case BTC_CXP_PAUTO_TD50B1:
4999 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
5000 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5001 			break;
5002 		case BTC_CXP_PAUTO_TD60B1:
5003 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
5004 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5005 			break;
5006 		case BTC_CXP_PAUTO_TD20B1:
5007 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5008 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5009 			break;
5010 		case BTC_CXP_PAUTO_TDW1B1:
5011 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5012 				  tbl_w1, SLOT_ISO);
5013 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
5014 				  tbl_b1, SLOT_MIX);
5015 			break;
5016 		}
5017 		break;
5018 	case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
5019 		tdma_on = true;
5020 		*t = t_def[CXTD_AUTO2];
5021 		switch (policy_type) {
5022 		case BTC_CXP_AUTO2_TD3050:
5023 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5024 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
5025 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5026 			break;
5027 		case BTC_CXP_AUTO2_TD3070:
5028 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5029 			_slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
5030 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5031 			break;
5032 		case BTC_CXP_AUTO2_TD5050:
5033 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
5034 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
5035 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5036 			break;
5037 		case BTC_CXP_AUTO2_TD6060:
5038 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
5039 			_slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
5040 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5041 			break;
5042 		case BTC_CXP_AUTO2_TD2080:
5043 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5044 			_slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
5045 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5046 			break;
5047 		case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
5048 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5049 				  tbl_w1, SLOT_ISO);
5050 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
5051 				  tbl_b4, SLOT_MIX);
5052 			break;
5053 		}
5054 		break;
5055 	case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
5056 		tdma_on = true;
5057 		*t = t_def[CXTD_PAUTO2];
5058 		switch (policy_type) {
5059 		case BTC_CXP_PAUTO2_TD3050:
5060 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5061 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
5062 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5063 			break;
5064 		case BTC_CXP_PAUTO2_TD3070:
5065 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5066 			_slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
5067 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5068 			break;
5069 		case BTC_CXP_PAUTO2_TD5050:
5070 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
5071 			_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
5072 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5073 			break;
5074 		case BTC_CXP_PAUTO2_TD6060:
5075 			_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
5076 			_slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
5077 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5078 			break;
5079 		case BTC_CXP_PAUTO2_TD2080:
5080 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5081 			_slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
5082 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5083 			break;
5084 		case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
5085 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5086 				  tbl_w1, SLOT_ISO);
5087 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
5088 				  tbl_b4, SLOT_MIX);
5089 			break;
5090 		}
5091 		break;
5092 	}
5093 	_set_tdma_bind(rtwdev, tdma_on);
5094 }
5095 EXPORT_SYMBOL(rtw89_btc_set_policy);
5096 
rtw89_btc_set_policy_v1(struct rtw89_dev * rtwdev,u16 policy_type)5097 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
5098 {
5099 	struct rtw89_btc *btc = &rtwdev->btc;
5100 	struct rtw89_btc_dm *dm = &btc->dm;
5101 	struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
5102 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc;
5103 	struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt0.link_info.hid_desc;
5104 	struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt0.link_info.hfp_desc;
5105 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5106 	u8 type, null_role;
5107 	u32 tbl_w1, tbl_b1, tbl_b4;
5108 	bool tdma_on = false;
5109 	u16 dur_1 = 0, dur_2;
5110 
5111 	if (wl->status.map.lps) {
5112 		_slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
5113 			     s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
5114 		_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
5115 			     s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
5116 		_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
5117 			     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
5118 	}
5119 
5120 	type = FIELD_GET(BTC_CXP_MASK, policy_type);
5121 
5122 	if (btc->ant_type == BTC_ANT_SHARED) {
5123 		if (btc->cx.wl.status.map._4way)
5124 			tbl_w1 = cxtbl[1];
5125 		else if (hid->exist && hid->type == BTC_HID_218)
5126 			tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */
5127 		else
5128 			tbl_w1 = cxtbl[8];
5129 
5130 		if (dm->leak_ap &&
5131 		    (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) {
5132 			tbl_b1 = cxtbl[3];
5133 			tbl_b4 = cxtbl[3];
5134 		} else if (hid->exist && hid->type == BTC_HID_218) {
5135 			tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */
5136 			tbl_b4 = cxtbl[4];
5137 		} else {
5138 			tbl_b1 = cxtbl[2];
5139 			tbl_b4 = cxtbl[2];
5140 		}
5141 	} else {
5142 		tbl_b1 = cxtbl[17];
5143 		tbl_b4 = cxtbl[17];
5144 
5145 		if (wl->bg_mode)
5146 			tbl_w1 = cxtbl[8];
5147 		else if ((wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) &&
5148 			 hid->exist)
5149 			tbl_w1 = cxtbl[19];
5150 		else
5151 			tbl_w1 = cxtbl[16];
5152 	}
5153 
5154 	switch (type) {
5155 	case BTC_CXP_USERDEF0:
5156 		btc->update_policy_force = true;
5157 		*t = t_def[CXTD_OFF];
5158 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
5159 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
5160 		_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
5161 		break;
5162 	case BTC_CXP_OFF: /* TDMA off */
5163 		tdma_on = false;
5164 		*t = t_def[CXTD_OFF];
5165 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
5166 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
5167 
5168 		switch (policy_type) {
5169 		case BTC_CXP_OFF_BT:
5170 			_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
5171 			break;
5172 		case BTC_CXP_OFF_WL:
5173 			_slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
5174 			break;
5175 		case BTC_CXP_OFF_WL2:
5176 			_slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
5177 			_slot_set_type(btc, CXST_OFF, SLOT_ISO);
5178 			break;
5179 		case BTC_CXP_OFF_EQ0:
5180 			_slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
5181 			_slot_set_type(btc, CXST_OFF, SLOT_ISO);
5182 			break;
5183 		case BTC_CXP_OFF_EQ1:
5184 			_slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
5185 			break;
5186 		case BTC_CXP_OFF_EQ2:
5187 			_slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
5188 			break;
5189 		case BTC_CXP_OFF_EQ3:
5190 			_slot_set_tbl(btc, CXST_OFF, cxtbl[24]);
5191 			break;
5192 		case BTC_CXP_OFF_EQ4:
5193 			_slot_set_tbl(btc, CXST_OFF, cxtbl[26]);
5194 			break;
5195 		case BTC_CXP_OFF_EQ5:
5196 			_slot_set_tbl(btc, CXST_OFF, cxtbl[27]);
5197 			break;
5198 		case BTC_CXP_OFF_BWB0:
5199 			_slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
5200 			break;
5201 		case BTC_CXP_OFF_BWB1:
5202 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
5203 			break;
5204 		case BTC_CXP_OFF_BWB2:
5205 			_slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
5206 			break;
5207 		case BTC_CXP_OFF_BWB3:
5208 			_slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
5209 			break;
5210 		default:
5211 			break;
5212 		}
5213 		break;
5214 	case BTC_CXP_OFFB: /* TDMA off + beacon protect */
5215 		tdma_on = false;
5216 		*t = t_def[CXTD_OFF_B2];
5217 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
5218 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
5219 		_slot_set(btc, CXST_B2, 10, cxtbl[1], SLOT_ISO);
5220 
5221 		switch (policy_type) {
5222 		case BTC_CXP_OFFB_BWB0:
5223 			_slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
5224 			break;
5225 		case BTC_CXP_OFFB_BWB1:
5226 			_slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
5227 			break;
5228 		case BTC_CXP_OFFB_BWB2:
5229 			_slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
5230 			break;
5231 		case BTC_CXP_OFFB_BWB3:
5232 			_slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
5233 			break;
5234 		case BTC_CXP_OFFB_BWB4:
5235 			_slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
5236 			break;
5237 		}
5238 		break;
5239 	case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
5240 		tdma_on = true;
5241 		*t = t_def[CXTD_OFF_EXT];
5242 
5243 		/* To avoid wl-s0 tx break by hid/hfp tx */
5244 		if (hid->exist || hfp->exist)
5245 			tbl_w1 = cxtbl[16];
5246 
5247 		if (dm->eslot_ctrl.en) {
5248 			null_role = u8_encode_bits(dm->eslot_ctrl.nulltx_role1, 0x0f) |
5249 				    u8_encode_bits(dm->eslot_ctrl.nulltx_role2, 0xf0);
5250 			_tdma_set_flctrl_role(btc, null_role);
5251 			_tdma_set_rxflctrl(btc, 1);
5252 			_tdma_set_txflctrl(btc, 1);
5253 			/* Set Null-Tx time-tick by E2G duration */
5254 			dm->eslot_ctrl.nulltx_pre_time = 5; /* TODO: BIS COEX */
5255 			dur_1 = dm->eslot_ctrl.nulltx_pre_time;
5256 		}
5257 
5258 		dur_2 = dm->e2g_slot_limit;
5259 
5260 		switch (policy_type) {
5261 		case BTC_CXP_OFFE_2GBWISOB: /* for normal-case */
5262 			_slot_set(btc, CXST_E2G, dur_1, tbl_w1, SLOT_ISO);
5263 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
5264 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
5265 			_slot_set_dur(btc, CXST_EBT, dur_2);
5266 			break;
5267 		case BTC_CXP_OFFE_2GISOB: /* for bt no-link */
5268 			_slot_set(btc, CXST_E2G, dur_1, cxtbl[1], SLOT_ISO);
5269 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
5270 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
5271 			_slot_set_dur(btc, CXST_EBT, dur_2);
5272 			break;
5273 		case BTC_CXP_OFFE_DEF:
5274 			_slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
5275 				     s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
5276 			_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
5277 				     s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
5278 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
5279 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
5280 			_slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
5281 				     s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
5282 			_slot_set_dur(btc, CXST_EBT, dur_2);
5283 			break;
5284 		case BTC_CXP_OFFE_DEF2:
5285 			_slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
5286 			_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
5287 				     s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
5288 			_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
5289 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
5290 			_slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
5291 				     s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
5292 			_slot_set_dur(btc, CXST_EBT, dur_2);
5293 			break;
5294 		case BTC_CXP_OFFE_2GBWMIXB:
5295 			if (a2dp->exist)
5296 				_slot_set(btc, CXST_E2G, dur_1, cxtbl[2], SLOT_MIX);
5297 			else
5298 				_slot_set(btc, CXST_E2G, dur_1, tbl_w1, SLOT_MIX);
5299 			_slot_set_le(btc, CXST_EBT, cpu_to_le16(40),
5300 				     s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
5301 			_slot_set_dur(btc, CXST_EBT, dur_2);
5302 			break;
5303 		case BTC_CXP_OFFE_WL: /* for 4-way */
5304 			_slot_set(btc, CXST_E2G, dur_1, cxtbl[1], SLOT_MIX);
5305 			_slot_set(btc, CXST_EBT, dur_1, cxtbl[1], SLOT_MIX);
5306 			break;
5307 		default:
5308 			break;
5309 		}
5310 		_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
5311 			     s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
5312 		_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
5313 			     s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
5314 		break;
5315 	case BTC_CXP_FIX: /* TDMA Fix-Slot */
5316 		tdma_on = true;
5317 		*t = t_def[CXTD_FIX];
5318 
5319 		switch (policy_type) {
5320 		case BTC_CXP_FIX_TD3030:
5321 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5322 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
5323 			break;
5324 		case BTC_CXP_FIX_TD5050:
5325 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
5326 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
5327 			break;
5328 		case BTC_CXP_FIX_TD2030:
5329 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5330 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
5331 			break;
5332 		case BTC_CXP_FIX_TD4010:
5333 			_slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
5334 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
5335 			break;
5336 		case BTC_CXP_FIX_TD4010ISO:
5337 			_slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
5338 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
5339 			break;
5340 		case BTC_CXP_FIX_TD4010ISO_DL:
5341 			_slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
5342 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
5343 			break;
5344 		case BTC_CXP_FIX_TD4010ISO_UL:
5345 			_slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
5346 			_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
5347 			break;
5348 		case BTC_CXP_FIX_TD7010:
5349 			_slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
5350 			_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
5351 			break;
5352 		case BTC_CXP_FIX_TD2060:
5353 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5354 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
5355 			break;
5356 		case BTC_CXP_FIX_TD3060:
5357 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5358 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
5359 			break;
5360 		case BTC_CXP_FIX_TD2080:
5361 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5362 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
5363 			break;
5364 		case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
5365 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5366 				  tbl_w1, SLOT_ISO);
5367 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
5368 				  tbl_b1, SLOT_MIX);
5369 			break;
5370 		default:
5371 			break;
5372 		}
5373 		break;
5374 	case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
5375 		tdma_on = true;
5376 		*t = t_def[CXTD_PFIX];
5377 
5378 		switch (policy_type) {
5379 		case BTC_CXP_PFIX_TD3030:
5380 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5381 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
5382 			break;
5383 		case BTC_CXP_PFIX_TD5050:
5384 			_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
5385 			_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
5386 			break;
5387 		case BTC_CXP_PFIX_TD2030:
5388 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5389 			_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
5390 			break;
5391 		case BTC_CXP_PFIX_TD2060:
5392 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5393 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
5394 			break;
5395 		case BTC_CXP_PFIX_TD3070:
5396 			_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5397 			_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
5398 			break;
5399 		case BTC_CXP_PFIX_TD2080:
5400 			_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5401 			_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
5402 			break;
5403 		case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */
5404 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5405 				  tbl_w1, SLOT_ISO);
5406 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
5407 				  tbl_b1, SLOT_MIX);
5408 			break;
5409 		default:
5410 			break;
5411 		}
5412 		break;
5413 	case BTC_CXP_AUTO: /* TDMA Auto-Slot */
5414 		tdma_on = true;
5415 		*t = t_def[CXTD_AUTO];
5416 
5417 		switch (policy_type) {
5418 		case BTC_CXP_AUTO_TD50B1:
5419 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
5420 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5421 			break;
5422 		case BTC_CXP_AUTO_TD60B1:
5423 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
5424 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5425 			break;
5426 		case BTC_CXP_AUTO_TD20B1:
5427 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
5428 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5429 			break;
5430 		case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
5431 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5432 				  tbl_w1, SLOT_ISO);
5433 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
5434 				  tbl_b1, SLOT_MIX);
5435 			break;
5436 		default:
5437 			break;
5438 		}
5439 		break;
5440 	case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
5441 		tdma_on = true;
5442 		*t = t_def[CXTD_PAUTO];
5443 
5444 		switch (policy_type) {
5445 		case BTC_CXP_PAUTO_TD50B1:
5446 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
5447 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5448 			break;
5449 		case BTC_CXP_PAUTO_TD60B1:
5450 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
5451 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5452 			break;
5453 		case BTC_CXP_PAUTO_TD20B1:
5454 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
5455 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5456 			break;
5457 		case BTC_CXP_PAUTO_TDW1B1:
5458 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5459 				  tbl_w1, SLOT_ISO);
5460 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
5461 				  tbl_b1, SLOT_MIX);
5462 			break;
5463 		default:
5464 			break;
5465 		}
5466 		break;
5467 	case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
5468 		tdma_on = true;
5469 		*t = t_def[CXTD_AUTO2];
5470 
5471 		switch (policy_type) {
5472 		case BTC_CXP_AUTO2_TD3050:
5473 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
5474 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5475 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
5476 			break;
5477 		case BTC_CXP_AUTO2_TD3070:
5478 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
5479 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5480 			_slot_set(btc, CXST_B4,  70, tbl_b4, SLOT_MIX);
5481 			break;
5482 		case BTC_CXP_AUTO2_TD5050:
5483 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
5484 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5485 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
5486 			break;
5487 		case BTC_CXP_AUTO2_TD6060:
5488 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
5489 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5490 			_slot_set(btc, CXST_B4,  60, tbl_b4, SLOT_MIX);
5491 			break;
5492 		case BTC_CXP_AUTO2_TD2080:
5493 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
5494 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5495 			_slot_set(btc, CXST_B4,  80, tbl_b4, SLOT_MIX);
5496 			break;
5497 		case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
5498 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5499 				  tbl_w1, SLOT_ISO);
5500 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
5501 				  tbl_b1, SLOT_MIX);
5502 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
5503 				  tbl_b4, SLOT_MIX);
5504 			break;
5505 		default:
5506 			break;
5507 		}
5508 		break;
5509 	case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
5510 		tdma_on = true;
5511 		*t = t_def[CXTD_PAUTO2];
5512 
5513 		switch (policy_type) {
5514 		case BTC_CXP_PAUTO2_TD3050:
5515 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
5516 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5517 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
5518 			break;
5519 		case BTC_CXP_PAUTO2_TD3070:
5520 			_slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
5521 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5522 			_slot_set(btc, CXST_B4,  70, tbl_b4, SLOT_MIX);
5523 			break;
5524 		case BTC_CXP_PAUTO2_TD5050:
5525 			_slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
5526 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5527 			_slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
5528 			break;
5529 		case BTC_CXP_PAUTO2_TD6060:
5530 			_slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
5531 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5532 			_slot_set(btc, CXST_B4,  60, tbl_b4, SLOT_MIX);
5533 			break;
5534 		case BTC_CXP_PAUTO2_TD2080:
5535 			_slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
5536 			_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5537 			_slot_set(btc, CXST_B4,  80, tbl_b4, SLOT_MIX);
5538 			break;
5539 		case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
5540 			_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5541 				  tbl_w1, SLOT_ISO);
5542 			_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
5543 				  tbl_b1, SLOT_MIX);
5544 			_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
5545 				  tbl_b4, SLOT_MIX);
5546 			break;
5547 		default:
5548 			break;
5549 		}
5550 		break;
5551 	}
5552 
5553 	/* enter leak_slot after each null-1 */
5554 	if (dm->leak_ap && dm->tdma.leak_n > 1)
5555 		_tdma_set_lek(btc, 1);
5556 
5557 	if (dm->tdma_instant_excute ||
5558 	    dm->error.map.tdma_no_sync ||
5559 	    dm->error.map.slot_no_sync ||
5560 	    dm->lps_ctrl_change) {
5561 		btc->dm.tdma.option_ctrl |= BIT(0);
5562 		btc->update_policy_force = true;
5563 	}
5564 
5565 	if (btc->cli_h2c_cmd)
5566 		btc->update_policy_force = true;
5567 
5568 	_set_tdma_bind(rtwdev, tdma_on);
5569 }
5570 EXPORT_SYMBOL(rtw89_btc_set_policy_v1);
5571 
_set_bt_plut(struct rtw89_dev * rtwdev,u8 phy_map,u8 tx_val,u8 rx_val)5572 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
5573 			 u8 tx_val, u8 rx_val)
5574 {
5575 	struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
5576 	struct rtw89_mac_ax_plt plt;
5577 
5578 	plt.tx = tx_val;
5579 	plt.rx = rx_val;
5580 
5581 	if (rtwdev->btc.ver->fwlrole == 8) {
5582 		plt.band = wl->pta_req_mac;
5583 		if (wl->bt_polut_type[plt.band] == tx_val)
5584 			return;
5585 
5586 		wl->bt_polut_type[plt.band] = tx_val;
5587 		rtw89_mac_cfg_plt(rtwdev, &plt);
5588 	} else {
5589 		plt.band = RTW89_MAC_0;
5590 
5591 		if (phy_map & BTC_PHY_0)
5592 			rtw89_mac_cfg_plt(rtwdev, &plt);
5593 
5594 		if (!rtwdev->dbcc_en)
5595 			return;
5596 
5597 		plt.band = RTW89_MAC_1;
5598 		if (phy_map & BTC_PHY_1)
5599 			rtw89_mac_cfg_plt(rtwdev, &plt);
5600 	}
5601 }
5602 
_set_ant(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)5603 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
5604 		     u8 phy_map, u8 type)
5605 {
5606 	struct rtw89_btc *btc = &rtwdev->btc;
5607 	struct rtw89_btc_cx *cx = &btc->cx;
5608 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5609 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5610 	u32 ant_path_type = rtw89_get_antpath_type(phy_map, type);
5611 	struct rtw89_btc_dm *dm = &btc->dm;
5612 	u8 gwl = BTC_GNT_HW, gwl0, gwl1, gbt;
5613 	bool cx_ctrl;
5614 
5615 	if (btc->cli_h2c_cmd || wl_rinfo->dbcc_chg ||
5616 	    dm->run_reason == BTC_RSN_NTFY_POWEROFF ||
5617 	    dm->run_reason == BTC_RSN_NTFY_RADIO_STATE ||
5618 	    dm->run_reason == BTC_RSN_CMD_SET_COEX)
5619 		force_exec = FC_EXEC;
5620 
5621 	if (wl_rinfo->link_mode != BTC_WLINK_DB_MCC &&
5622 	    btc->dm.wl_btg_rx == 2)
5623 		force_exec = FC_EXEC;
5624 
5625 	if (!force_exec && ant_path_type == dm->set_ant_path) {
5626 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
5627 			    "[BTC], %s(): return by no change!!\n",
5628 			     __func__);
5629 		return;
5630 	} else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
5631 		   wl->rfk_info.state != BTC_WRFK_STOP) {
5632 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
5633 			    "[BTC], %s(): return by wl rfk!!\n", __func__);
5634 		return;
5635 	}
5636 
5637 	dm->set_ant_path = ant_path_type;
5638 
5639 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
5640 		    "[BTC], %s(): path=0x%x, set_type=0x%x\n",
5641 		    __func__, phy_map, dm->set_ant_path & 0xff);
5642 
5643 	switch (type) {
5644 	case BTC_ANT_WPOWERON:
5645 		cx_ctrl = BTC_CTRL_BY_BT;
5646 		break;
5647 	case BTC_ANT_WINIT:
5648 		cx_ctrl = BTC_CTRL_BY_WL;
5649 		/* To avoid BT MP driver case (bt_enable but no mailbox) */
5650 		if ((cx->bt0.enable.now && cx->bt0.run_patch_code) ||
5651 		    (cx->bt1.enable.now && cx->bt1.run_patch_code))
5652 			_set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
5653 				 BTC_WLACT_SW_LO);
5654 		else
5655 			_set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
5656 				 BTC_WLACT_SW_HI);
5657 		break;
5658 	case BTC_ANT_WONLY:
5659 		cx_ctrl = BTC_CTRL_BY_WL;
5660 		_set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
5661 			 BTC_WLACT_SW_HI);
5662 		break;
5663 	case BTC_ANT_WOFF:
5664 		cx_ctrl = BTC_CTRL_BY_BT;
5665 		_set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
5666 			 BTC_WLACT_SW_LO);
5667 		break;
5668 	case BTC_ANT_PTA:
5669 	default:
5670 		cx_ctrl = BTC_CTRL_BY_WL;
5671 		gbt = BTC_GNT_HW;
5672 		if ((rtwdev->chip->para_ver & BTC_FEAT_MULTI_PTA) ||
5673 		    !wl_rinfo->dbcc_en) {
5674 			gwl = BTC_GNT_HW;
5675 			_set_gnt(rtwdev, BTC_PHY_ALL, gwl, gbt, BTC_WLACT_HW);
5676 		} else {
5677 			/* for DBCC Only-1-PTA */
5678 			if (wl_rinfo->dbcc_2g_phy == RTW89_PHY_0) {
5679 				gwl0 = BTC_GNT_HW;
5680 				gwl1 = BTC_GNT_SW_HI;
5681 			} else {
5682 				gwl0 = BTC_GNT_SW_HI;
5683 				gwl1 = BTC_GNT_HW;
5684 			}
5685 			_set_gnt(rtwdev, BTC_PHY_0, gwl0, gbt, BTC_WLACT_HW);
5686 			_set_gnt(rtwdev, BTC_PHY_1, gwl1, gbt, BTC_WLACT_HW);
5687 		}
5688 		break;
5689 	case BTC_ANT_FDD:
5690 		cx_ctrl = BTC_CTRL_BY_WL;
5691 		_set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_HW,
5692 			 BTC_WLACT_HW);
5693 		break;
5694 	case BTC_ANT_FREERUN:
5695 		cx_ctrl = BTC_CTRL_BY_WL;
5696 		_set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_HI,
5697 			 BTC_WLACT_SW_LO);
5698 		break;
5699 	case BTC_ANT_WRFK:
5700 		cx_ctrl = BTC_CTRL_BY_WL;
5701 		_set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
5702 			 BTC_WLACT_HW);
5703 		break;
5704 	case BTC_ANT_WRFK2:
5705 		cx_ctrl = BTC_CTRL_BY_WL;
5706 		_set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
5707 			 BTC_WLACT_SW_HI); /* no BT-Tx */
5708 		break;
5709 	}
5710 
5711 	rtw89_chip_cfg_ctrl_path(rtwdev, cx_ctrl);
5712 	_set_bt_plut(rtwdev, phy_map, BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
5713 }
5714 
_action_wl_only(struct rtw89_dev * rtwdev)5715 static void _action_wl_only(struct rtw89_dev *rtwdev)
5716 {
5717 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
5718 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY);
5719 }
5720 
_action_wl_init(struct rtw89_dev * rtwdev)5721 static void _action_wl_init(struct rtw89_dev *rtwdev)
5722 {
5723 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
5724 
5725 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT);
5726 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT);
5727 }
5728 
_action_wl_off(struct rtw89_dev * rtwdev,u8 mode)5729 static void _action_wl_off(struct rtw89_dev *rtwdev, u8 mode)
5730 {
5731 	struct rtw89_btc *btc = &rtwdev->btc;
5732 	struct rtw89_btc_dm *dm = &btc->dm;
5733 	struct rtw89_btc_cx *cx = &btc->cx;
5734 	struct rtw89_btc_wl_info *wl = &cx->wl;
5735 
5736 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
5737 
5738 	if (wl->status.map.rf_off || btc->dm.bt_only)
5739 		_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF);
5740 	else if (wl->status.map.lps == BTC_LPS_RF_ON ||
5741 		 cx->bt0.whql_test || cx->bt1.whql_test)
5742 		_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_PTA);
5743 
5744 	if (dm->out_of_band)
5745 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OFF);
5746 	else if (cx->bt0.whql_test || cx->bt1.whql_test)
5747 		_set_policy(rtwdev, BTC_CXP_OFFB_BWB4, BTC_ACT_WL_OFF);
5748 	else
5749 		_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
5750 }
5751 
_action_freerun(struct rtw89_dev * rtwdev)5752 static void _action_freerun(struct rtw89_dev *rtwdev)
5753 {
5754 	struct rtw89_btc *btc = &rtwdev->btc;
5755 
5756 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
5757 
5758 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN);
5759 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN);
5760 
5761 	btc->dm.freerun = true;
5762 }
5763 
_action_bt_whql(struct rtw89_dev * rtwdev)5764 static void _action_bt_whql(struct rtw89_dev *rtwdev)
5765 {
5766 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
5767 
5768 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5769 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL);
5770 }
5771 
_action_bt_off(struct rtw89_dev * rtwdev)5772 static void _action_bt_off(struct rtw89_dev *rtwdev)
5773 {
5774 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
5775 
5776 	_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
5777 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF);
5778 }
5779 
_action_bt_idle(struct rtw89_dev * rtwdev)5780 static void _action_bt_idle(struct rtw89_dev *rtwdev)
5781 {
5782 	struct rtw89_btc *btc = &rtwdev->btc;
5783 	struct rtw89_btc_bt_link_info *b = &btc->cx.bt0.link_info;
5784 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5785 
5786 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5787 
5788 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5789 		switch (btc->cx.state_map) {
5790 		case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/
5791 		case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */
5792 			if (b->status.map.connect)
5793 				_set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_IDLE);
5794 			else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
5795 				_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_DL, BTC_ACT_BT_IDLE);
5796 			else
5797 				_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_UL, BTC_ACT_BT_IDLE);
5798 			break;
5799 		case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */
5800 			_set_policy(rtwdev, BTC_CXP_PFIX_TD5050,
5801 				    BTC_ACT_BT_IDLE);
5802 			break;
5803 		case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */
5804 			_set_policy(rtwdev, BTC_CXP_FIX_TD5050,
5805 				    BTC_ACT_BT_IDLE);
5806 			break;
5807 		case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */
5808 			_set_policy(rtwdev, BTC_CXP_FIX_TD7010,
5809 				    BTC_ACT_BT_IDLE);
5810 			break;
5811 		case BTC_WIDLE:  /* wl-idle + bt-idle */
5812 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE);
5813 			break;
5814 		}
5815 	} else { /* dedicated-antenna */
5816 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE);
5817 	}
5818 }
5819 
_action_bt_hfp(struct rtw89_dev * rtwdev)5820 static void _action_bt_hfp(struct rtw89_dev *rtwdev)
5821 {
5822 	struct rtw89_btc *btc = &rtwdev->btc;
5823 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5824 
5825 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5826 
5827 	if (btc->ant_type == BTC_ANT_SHARED) {
5828 		if (btc->cx.wl.status.map._4way) {
5829 			_set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP);
5830 		} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
5831 			btc->cx.bt0.scan_rx_low_pri = true;
5832 			_set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP);
5833 		} else {
5834 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
5835 		}
5836 	} else {
5837 		if (wl->bg_mode)
5838 			_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
5839 		else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
5840 			_set_policy(rtwdev, BTC_CXP_OFF_EQ5, BTC_ACT_BT_HFP);
5841 		else
5842 			_set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP);
5843 	}
5844 }
5845 
_action_bt_hid(struct rtw89_dev * rtwdev)5846 static void _action_bt_hid(struct rtw89_dev *rtwdev)
5847 {
5848 	const struct rtw89_chip_info *chip = rtwdev->chip;
5849 	struct rtw89_btc *btc = &rtwdev->btc;
5850 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5851 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
5852 	struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc;
5853 	u16 policy_type = BTC_CXP_OFF_BT;
5854 
5855 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5856 
5857 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5858 		if (wl->status.map._4way) {
5859 			policy_type = BTC_CXP_OFF_WL;
5860 		} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
5861 			btc->cx.bt0.scan_rx_low_pri = true;
5862 			if (hid->type & BTC_HID_BLE)
5863 				policy_type = BTC_CXP_OFF_BWB0;
5864 			else
5865 				policy_type = BTC_CXP_OFF_BWB2;
5866 		} else if (hid->type == BTC_HID_218) {
5867 			bt->scan_rx_low_pri = true;
5868 			policy_type = BTC_CXP_OFF_BWB2;
5869 		} else if (chip->para_ver == 0x1) {
5870 			policy_type = BTC_CXP_OFF_BWB3;
5871 		} else {
5872 			policy_type = BTC_CXP_OFF_BWB1;
5873 		}
5874 	} else { /* dedicated-antenna */
5875 		if (wl->bg_mode)
5876 			policy_type = BTC_CXP_OFF_BWB1;
5877 		else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
5878 			policy_type = BTC_CXP_OFF_EQ4;
5879 		else
5880 			policy_type = BTC_CXP_OFF_EQ3;
5881 	}
5882 
5883 	_set_policy(rtwdev, policy_type, BTC_ACT_BT_HID);
5884 }
5885 
_action_bt_a2dp(struct rtw89_dev * rtwdev)5886 static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
5887 {
5888 	struct rtw89_btc *btc = &rtwdev->btc;
5889 	struct rtw89_btc_dm *dm = &btc->dm;
5890 
5891 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5892 
5893 	dm->slot_dur[CXST_W1] = 20;
5894 	dm->slot_dur[CXST_B1] = BTC_B1_MAX;
5895 
5896 	switch (btc->cx.state_map) {
5897 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
5898 		_set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
5899 		break;
5900 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
5901 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP);
5902 		break;
5903 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */
5904 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP);
5905 		break;
5906 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
5907 	case BTC_WLINKING: /* wl-connecting + bt-A2DP */
5908 		if (btc->cx.wl.rfk_info.con_rfk)
5909 			_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP);
5910 		else
5911 			_set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP);
5912 		break;
5913 	case BTC_WIDLE:  /* wl-idle + bt-A2DP */
5914 		_set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP);
5915 		break;
5916 	}
5917 }
5918 
_action_bt_a2dpsink(struct rtw89_dev * rtwdev)5919 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev)
5920 {
5921 	struct rtw89_btc *btc = &rtwdev->btc;
5922 
5923 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5924 
5925 	switch (btc->cx.state_map) {
5926 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */
5927 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK);
5928 		break;
5929 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */
5930 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK);
5931 		break;
5932 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */
5933 		_set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK);
5934 		break;
5935 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */
5936 		_set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK);
5937 		break;
5938 	case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */
5939 		if (btc->cx.wl.rfk_info.con_rfk)
5940 			_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DPSINK);
5941 		else
5942 			_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
5943 		break;
5944 	case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */
5945 		_set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK);
5946 		break;
5947 	}
5948 }
5949 
_action_bt_pan(struct rtw89_dev * rtwdev)5950 static void _action_bt_pan(struct rtw89_dev *rtwdev)
5951 {
5952 	struct rtw89_btc *btc = &rtwdev->btc;
5953 	struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt0.link_info;
5954 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
5955 	struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
5956 
5957 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5958 
5959 	switch (btc->cx.state_map) {
5960 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */
5961 		if (a2dp.active || !pan.exist) {
5962 			btc->dm.slot_dur[CXST_W1] = 80;
5963 			btc->dm.slot_dur[CXST_B1] = 20;
5964 			_set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN);
5965 		} else {
5966 			_set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
5967 		}
5968 		break;
5969 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */
5970 		_set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN);
5971 		break;
5972 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */
5973 		_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN);
5974 		break;
5975 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */
5976 		_set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN);
5977 		break;
5978 	case BTC_WLINKING: /* wl-connecting + bt-PAN */
5979 		_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO, BTC_ACT_BT_PAN);
5980 		break;
5981 	case BTC_WIDLE: /* wl-idle + bt-pan */
5982 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN);
5983 		break;
5984 	}
5985 }
5986 
_action_bt_a2dp_hid(struct rtw89_dev * rtwdev)5987 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
5988 {
5989 	struct rtw89_btc *btc = &rtwdev->btc;
5990 	struct rtw89_btc_dm *dm = &btc->dm;
5991 
5992 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5993 
5994 	dm->slot_dur[CXST_W1] = 20;
5995 	dm->slot_dur[CXST_B1] = BTC_B1_MAX;
5996 
5997 	switch (btc->cx.state_map) {
5998 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */
5999 	case BTC_WIDLE:  /* wl-idle + bt-A2DP */
6000 		_set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
6001 		break;
6002 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */
6003 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_HID);
6004 		break;
6005 
6006 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */
6007 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
6008 		break;
6009 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */
6010 	case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */
6011 		if (btc->cx.wl.rfk_info.con_rfk)
6012 			_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP_HID);
6013 		else
6014 			_set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
6015 		break;
6016 	}
6017 }
6018 
_action_bt_a2dp_pan(struct rtw89_dev * rtwdev)6019 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev)
6020 {
6021 	struct rtw89_btc *btc = &rtwdev->btc;
6022 
6023 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6024 
6025 	switch (btc->cx.state_map) {
6026 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */
6027 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
6028 		break;
6029 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */
6030 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
6031 		break;
6032 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */
6033 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN);
6034 		break;
6035 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */
6036 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
6037 		break;
6038 	case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */
6039 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN);
6040 		break;
6041 	case BTC_WIDLE:  /* wl-idle + bt-A2DP+PAN */
6042 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN);
6043 		break;
6044 	}
6045 }
6046 
_action_bt_pan_hid(struct rtw89_dev * rtwdev)6047 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev)
6048 {
6049 	struct rtw89_btc *btc = &rtwdev->btc;
6050 
6051 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6052 
6053 	switch (btc->cx.state_map) {
6054 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */
6055 		_set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID);
6056 		break;
6057 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */
6058 		_set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID);
6059 		break;
6060 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */
6061 		_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID);
6062 		break;
6063 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */
6064 		_set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID);
6065 		break;
6066 	case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */
6067 		_set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID);
6068 		break;
6069 	case BTC_WIDLE: /* wl-idle + bt-PAN+HID */
6070 		_set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID);
6071 		break;
6072 	}
6073 }
6074 
_action_bt_bis(struct rtw89_dev * rtwdev)6075 static void _action_bt_bis(struct rtw89_dev *rtwdev)
6076 {
6077 	struct rtw89_btc *btc = &rtwdev->btc;
6078 	struct rtw89_btc_dm *dm = &btc->dm;
6079 	u16 policy_type;
6080 
6081 	if (dm->bis_tdma)
6082 		policy_type = BTC_CXP_OFFE_2GBWISOB;
6083 	else
6084 		policy_type = BTC_CXP_OFF_EQ0;
6085 
6086 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_PTA);
6087 	_set_policy(rtwdev, policy_type, BTC_ACT_BT_BIS);
6088 }
6089 
_action_bt_cis(struct rtw89_dev * rtwdev)6090 static void _action_bt_cis(struct rtw89_dev *rtwdev)
6091 {
6092 	struct rtw89_btc *btc = &rtwdev->btc;
6093 	struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt0.link_info;
6094 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6095 	struct rtw89_btc_dm *dm = &btc->dm;
6096 	u16 policy_type;
6097 
6098 	if (bt_linfo->a2dp_desc.active) {
6099 		dm->slot_dur[CXST_W1] = 80;
6100 		dm->slot_dur[CXST_B1] = 20;
6101 		policy_type = BTC_CXP_PFIX_TDW1B1;
6102 	} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
6103 		policy_type = BTC_CXP_OFF_BWB0;
6104 	} else {
6105 		policy_type = BTC_CXP_OFF_BWB1;
6106 	}
6107 
6108 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_PTA);
6109 	_set_policy(rtwdev, policy_type, BTC_ACT_BT_CIS);
6110 }
6111 
_action_bt_a2dp_pan_hid(struct rtw89_dev * rtwdev)6112 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev)
6113 {
6114 	struct rtw89_btc *btc = &rtwdev->btc;
6115 
6116 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6117 
6118 	switch (btc->cx.state_map) {
6119 	case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */
6120 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
6121 			    BTC_ACT_BT_A2DP_PAN_HID);
6122 		break;
6123 	case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */
6124 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
6125 			    BTC_ACT_BT_A2DP_PAN_HID);
6126 		break;
6127 	case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */
6128 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3070,
6129 			    BTC_ACT_BT_A2DP_PAN_HID);
6130 		break;
6131 	case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */
6132 	case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */
6133 		_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050,
6134 			    BTC_ACT_BT_A2DP_PAN_HID);
6135 		break;
6136 	case BTC_WIDLE:  /* wl-idle + bt-A2DP+PAN+HID */
6137 		_set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080,
6138 			    BTC_ACT_BT_A2DP_PAN_HID);
6139 		break;
6140 	}
6141 }
6142 
_action_wl_5g(struct rtw89_dev * rtwdev)6143 static void _action_wl_5g(struct rtw89_dev *rtwdev)
6144 {
6145 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_FDD);
6146 	_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G);
6147 }
6148 
_action_wl_other(struct rtw89_dev * rtwdev)6149 static void _action_wl_other(struct rtw89_dev *rtwdev)
6150 {
6151 	struct rtw89_btc *btc = &rtwdev->btc;
6152 
6153 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6154 
6155 	if (btc->ant_type == BTC_ANT_SHARED)
6156 		_set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER);
6157 	else
6158 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER);
6159 }
6160 
_action_wl_nc(struct rtw89_dev * rtwdev)6161 static void _action_wl_nc(struct rtw89_dev *rtwdev)
6162 {
6163 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6164 	_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC);
6165 }
6166 
_action_wl_rfk(struct rtw89_dev * rtwdev)6167 static void _action_wl_rfk(struct rtw89_dev *rtwdev)
6168 {
6169 	struct rtw89_btc *btc = &rtwdev->btc;
6170 	struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info;
6171 
6172 	if (rfk.state != BTC_WRFK_START)
6173 		return;
6174 
6175 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n",
6176 		    __func__, rfk.band);
6177 
6178 	btc->dm.tdma_instant_excute = 1;
6179 
6180 	if (rfk.state == BTC_WRFK_ONESHOT_START ||
6181 	    btc->ant_type == BTC_ANT_SHARED) {
6182 		_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2);
6183 		_set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK);
6184 	} else {
6185 		_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
6186 		_set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK);
6187 	}
6188 }
6189 
_set_btg_ctrl(struct rtw89_dev * rtwdev)6190 static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
6191 {
6192 	struct rtw89_btc *btc = &rtwdev->btc;
6193 	struct rtw89_btc_dm *dm = &btc->dm;
6194 	struct rtw89_btc_fbtc_outsrc_set_info *o_info = &dm->ost_info;
6195 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6196 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
6197 	const struct rtw89_chip_info *chip = rtwdev->chip;
6198 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
6199 	u32 is_btg = BTC_BTGCTRL_DISABLE;
6200 
6201 	if (btc->manual_ctrl)
6202 		return;
6203 
6204 	/* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */
6205 	if (btc->ant_type == BTC_ANT_SHARED) {
6206 		if (!(bt->run_patch_code && bt->enable.now))
6207 			is_btg = BTC_BTGCTRL_DISABLE;
6208 		else if (wl->rf_band_map[RTW89_MAC_0] & BIT(RTW89_BAND_2G) ||
6209 			 wl->rf_band_map[RTW89_MAC_1] & BIT(RTW89_BAND_2G))
6210 			is_btg = BTC_BTGCTRL_ENABLE;
6211 		else
6212 			is_btg = BTC_BTGCTRL_DISABLE;
6213 
6214 		/* bb call ctrl_btg() in WL FW by slot */
6215 		if (!btc->ver->fcxosi &&
6216 		    wl_rinfo->link_mode == BTC_WLINK_DB_MCC)
6217 			is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL;
6218 	}
6219 
6220 	if (is_btg == dm->wl_btg_rx)
6221 		return;
6222 	else
6223 		dm->wl_btg_rx = is_btg;
6224 
6225 	/* skip setup if btg_ctrl set by wl fw */
6226 	if (!btc->ver->fcxosi && is_btg > BTC_BTGCTRL_ENABLE)
6227 		return;
6228 
6229 	/* Below flow is for BTC_FEAT_NEW_BBAPI_FLOW = 1 */
6230 	if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */
6231 		if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */
6232 			o_info->btg_rx[BTC_RF_S0] = BTC_BTGCTRL_DISABLE;
6233 		else
6234 			o_info->btg_rx[BTC_RF_S0] = is_btg;
6235 
6236 		if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */
6237 			o_info->btg_rx[BTC_RF_S1] = BTC_BTGCTRL_DISABLE;
6238 		else
6239 			o_info->btg_rx[BTC_RF_S1] = is_btg;
6240 	} else { /* 2+0 or 0+2 */
6241 		o_info->btg_rx[BTC_RF_S0] = is_btg;
6242 		o_info->btg_rx[BTC_RF_S1] = is_btg;
6243 	}
6244 
6245 	if (btc->ver->fcxosi)
6246 		return;
6247 
6248 	chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S0],
6249 				  RTW89_PHY_0);
6250 	if (chip->chip_id != RTL8922A)
6251 		return;
6252 
6253 	chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S1],
6254 				  RTW89_PHY_1);
6255 }
6256 
_set_wl_preagc_ctrl(struct rtw89_dev * rtwdev)6257 static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev)
6258 {
6259 	struct rtw89_btc *btc = &rtwdev->btc;
6260 	struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info;
6261 	struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt0.link_info;
6262 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6263 	struct rtw89_btc_wl_role_info *rinfo = &wl->role_info;
6264 	const struct rtw89_chip_info *chip = rtwdev->chip;
6265 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
6266 	struct rtw89_btc_dm *dm = &btc->dm;
6267 	u8 is_preagc, val;
6268 
6269 	if (btc->manual_ctrl)
6270 		return;
6271 
6272 	if (!(bt->run_patch_code && bt->enable.now)) {
6273 		is_preagc = BTC_PREAGC_DISABLE;
6274 	} else if (dm->tdd_bind.rf_band == BIT(RTW89_BAND_5G)) {
6275 		is_preagc = BTC_PREAGC_DISABLE;
6276 	} else if (rinfo->link_mode == BTC_WLINK_NOLINK ||
6277 		 btc->cx.bt0.link_info.link_cnt.now == 0) {
6278 		is_preagc = BTC_PREAGC_DISABLE;
6279 	} else if (dm->tdma_now.type != CXTDMA_OFF &&
6280 		 !bt_linfo->hfp_desc.exist &&
6281 		 !bt_linfo->hid_desc.exist &&
6282 		 dm->fddt_train == BTC_FDDT_DISABLE) {
6283 		is_preagc = BTC_PREAGC_DISABLE;
6284 	} else if (rinfo->dbcc_en && (rinfo->dbcc_2g_phy != RTW89_PHY_1)) {
6285 		is_preagc = BTC_PREAGC_DISABLE;
6286 	} else if (btc->ant_type == BTC_ANT_SHARED) {
6287 		is_preagc = BTC_PREAGC_DISABLE;
6288 	} else {
6289 		is_preagc = BTC_PREAGC_ENABLE;
6290 	}
6291 
6292 	if (!btc->ver->fcxosi && rinfo->link_mode == BTC_WLINK_DB_MCC)
6293 		is_preagc = BTC_PREAGC_BB_FWCTRL;
6294 
6295 	if (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
6296 	    dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) {
6297 		_get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val);
6298 		dm->wl_pre_agc_rb = val;
6299 	}
6300 
6301 	if ((wl->coex_mode == BTC_MODE_NORMAL &&
6302 	     (dm->run_reason == BTC_RSN_NTFY_INIT ||
6303 	      dm->run_reason == BTC_RSN_NTFY_SWBAND ||
6304 	      dm->wl_pre_agc_rb != dm->wl_pre_agc)) ||
6305 	    is_preagc != dm->wl_pre_agc) {
6306 		dm->wl_pre_agc = is_preagc;
6307 
6308 		if (!btc->ver->fcxosi && is_preagc > BTC_PREAGC_ENABLE)
6309 			return;
6310 
6311 		if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */
6312 			if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */
6313 				o_info->nbtg_tx[BTC_RF_S0] = BTC_PREAGC_DISABLE;
6314 			else
6315 				o_info->nbtg_tx[BTC_RF_S0] = is_preagc;
6316 
6317 			if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */
6318 				o_info->nbtg_tx[BTC_RF_S1] = BTC_PREAGC_DISABLE;
6319 			else
6320 				o_info->nbtg_tx[BTC_RF_S1] = is_preagc;
6321 
6322 		} else { /* 2+0 or 0+2 */
6323 			o_info->nbtg_tx[BTC_RF_S0] = is_preagc;
6324 			o_info->nbtg_tx[BTC_RF_S1] = is_preagc;
6325 		}
6326 
6327 		if (btc->ver->fcxosi)
6328 			return;
6329 
6330 		chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S0],
6331 					   RTW89_PHY_0);
6332 		if (chip->chip_id != RTL8922A)
6333 			return;
6334 		chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S1],
6335 					   RTW89_PHY_1);
6336 	}
6337 }
6338 
6339 struct rtw89_txtime_data {
6340 	struct rtw89_dev *rtwdev;
6341 	int type;
6342 	u32 tx_time;
6343 	u8 tx_retry;
6344 	u16 enable;
6345 	bool reenable;
6346 };
6347 
__rtw89_tx_time_iter(struct rtw89_vif_link * rtwvif_link,struct rtw89_sta_link * rtwsta_link,struct rtw89_txtime_data * iter_data)6348 static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link,
6349 				 struct rtw89_sta_link *rtwsta_link,
6350 				 struct rtw89_txtime_data *iter_data)
6351 {
6352 	struct rtw89_dev *rtwdev = iter_data->rtwdev;
6353 	struct rtw89_btc *btc = &rtwdev->btc;
6354 	struct rtw89_btc_cx *cx = &btc->cx;
6355 	struct rtw89_btc_wl_info *wl = &cx->wl;
6356 	struct rtw89_btc_wl_link_info *plink = NULL;
6357 	u8 port = rtwvif_link->port;
6358 	u32 tx_time = iter_data->tx_time;
6359 	u8 tx_retry = iter_data->tx_retry;
6360 	u16 enable = iter_data->enable;
6361 	bool reenable = iter_data->reenable;
6362 
6363 	plink = &wl->rlink_info[port][rtwsta_link->link_id];
6364 
6365 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
6366 		    "[BTC], %s(): port = %d\n", __func__, port);
6367 
6368 	if (!plink->connected) {
6369 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6370 			    "[BTC], %s(): connected = %d\n",
6371 			    __func__, plink->connected);
6372 		return;
6373 	}
6374 
6375 	/* backup the original tx time before tx-limit on */
6376 	if (reenable) {
6377 		rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time);
6378 		rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry);
6379 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6380 			    "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n",
6381 			    __func__, plink->tx_time, plink->tx_retry);
6382 	}
6383 
6384 	/* restore the original tx time if no tx-limit */
6385 	if (!enable) {
6386 		rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time);
6387 		rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true,
6388 					     plink->tx_retry);
6389 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6390 			    "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n",
6391 			    __func__, plink->tx_time, plink->tx_retry);
6392 
6393 	} else {
6394 		rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time);
6395 		rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry);
6396 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6397 			    "[BTC], %s(): set, tx_time=%d tx_retry= %d\n",
6398 			    __func__, tx_time, tx_retry);
6399 	}
6400 }
6401 
rtw89_tx_time_iter(void * data,struct ieee80211_sta * sta)6402 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
6403 {
6404 	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
6405 	struct rtw89_txtime_data *iter_data =
6406 				(struct rtw89_txtime_data *)data;
6407 	struct rtw89_vif_link *rtwvif_link;
6408 	struct rtw89_sta_link *rtwsta_link;
6409 	unsigned int link_id;
6410 
6411 	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
6412 		rtwvif_link = rtwsta_link->rtwvif_link;
6413 		__rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data);
6414 	}
6415 }
6416 
_set_wl_tx_limit(struct rtw89_dev * rtwdev)6417 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
6418 {
6419 	struct rtw89_btc *btc = &rtwdev->btc;
6420 	struct rtw89_btc_cx *cx = &btc->cx;
6421 	struct rtw89_btc_dm *dm = &btc->dm;
6422 	struct rtw89_btc_wl_info *wl = &cx->wl;
6423 	struct rtw89_btc_bt_info *bt = &cx->bt0;
6424 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
6425 	struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
6426 	struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
6427 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
6428 	struct rtw89_txtime_data data = {.rtwdev = rtwdev};
6429 	bool reenable = false;
6430 	u8 tx_retry;
6431 	u32 tx_time;
6432 	u16 enable;
6433 
6434 	if (btc->manual_ctrl)
6435 		return;
6436 
6437 	if (btc->dm.freerun || btc->ctrl.igno_bt || b->link_cnt.now == 0 ||
6438 	    dm->tdd_bind.rf_band == BIT(RTW89_BAND_5G) ||
6439 	    wl_rinfo->link_mode == BTC_WLINK_NOLINK) {
6440 		enable = 0;
6441 		tx_time = BTC_MAX_TX_TIME_DEF;
6442 		tx_retry = BTC_MAX_TX_RETRY_DEF;
6443 	} else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) {
6444 		enable = 1;
6445 		tx_time = BTC_MAX_TX_TIME_L2;
6446 		tx_retry = BTC_MAX_TX_RETRY_L1;
6447 	} else if (hfp->exist || hid->exist) {
6448 		enable = 1;
6449 		tx_time = BTC_MAX_TX_TIME_L3;
6450 		tx_retry = BTC_MAX_TX_RETRY_L1;
6451 	} else {
6452 		enable = 0;
6453 		tx_time = BTC_MAX_TX_TIME_DEF;
6454 		tx_retry = BTC_MAX_TX_RETRY_DEF;
6455 	}
6456 
6457 	if (dm->wl_tx_limit.enable == enable &&
6458 	    dm->wl_tx_limit.tx_time == tx_time &&
6459 	    dm->wl_tx_limit.tx_retry == tx_retry)
6460 		return;
6461 
6462 	if (!dm->wl_tx_limit.enable && enable)
6463 		reenable = true;
6464 
6465 	dm->wl_tx_limit.enable = enable;
6466 	dm->wl_tx_limit.tx_time = tx_time;
6467 	dm->wl_tx_limit.tx_retry = tx_retry;
6468 
6469 	data.enable = enable;
6470 	data.tx_time = tx_time;
6471 	data.tx_retry = tx_retry;
6472 	data.reenable = reenable;
6473 
6474 	ieee80211_iterate_stations_atomic(rtwdev->hw,
6475 					  rtw89_tx_time_iter,
6476 					  &data);
6477 }
6478 
_set_phl_bt_slot_req(struct rtw89_dev * rtwdev)6479 static void _set_phl_bt_slot_req(struct rtw89_dev *rtwdev)
6480 {
6481 	struct rtw89_btc *btc = &rtwdev->btc;
6482 	struct rtw89_btc_cx *cx = &btc->cx;
6483 	struct rtw89_btc_wl_info *wl = &cx->wl;
6484 	struct rtw89_btc_dm *dm = &btc->dm;
6485 	u8 len = 0;
6486 	u8 i;
6487 
6488 	/* don't change bt slot req state during RFK for p2p/mcc case */
6489 	if (dm->run_reason == BTC_RSN_NTFY_WL_RFK ||
6490 	    wl->status.map.transacting)
6491 		return;
6492 
6493 	/* enable bt-slot req if ext-slot-control */
6494 	if (dm->tdma_now.type == CXTDMA_OFF &&
6495 	    dm->tdma_now.ext_ctrl == CXECTL_EXT &&
6496 	    dm->tdd_bind.bt_sel != 0) {
6497 		if (btc->cx.wl.status.val & btc_scanning_map.val)
6498 			btc->bt_req_en = false;
6499 		else
6500 			btc->bt_req_en = true;
6501 	} else {
6502 		btc->bt_req_en = false;
6503 	}
6504 
6505 	if (dm->slot_req_more) {
6506 		len = BTC_BSLOT_A2DP_HID;
6507 	} else {
6508 		if (dm->tdd_bind.bt_link_weight >= BTC_BSLOT_A2DP_HID)
6509 			len = BTC_BSLOT_A2DP_HID;
6510 		else if (dm->tdd_bind.bt_link_weight <= BTC_BSLOT_IDLE)
6511 			len = BTC_BSLOT_IDLE;
6512 		else
6513 			len = dm->tdd_bind.bt_link_weight;
6514 	}
6515 
6516 	if (dm->tdd_bind.rf_band == BIT(RTW89_BAND_5G))
6517 		len = 100 - len;
6518 
6519 	if (!btc->bt_req_en)
6520 		len = 0;
6521 
6522 	for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) {
6523 		if (!(dm->tdd_bind.wl_hwb_sel & BIT(i)))
6524 			continue;
6525 
6526 		if (len == btc->bt_req_len[i])
6527 			continue;
6528 
6529 		btc->bt_req_len[i] = len;
6530 
6531 		rtw89_core_ntfy_btc_event(rtwdev,
6532 					  RTW89_BTC_HMSG_SET_BT_REQ_SLOT, i);
6533 
6534 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
6535 			    "[BTC], %s(): HWB%d bt_req_len = %d\n",
6536 			    __func__, i, btc->bt_req_len[i]);
6537 	}
6538 }
6539 
_set_bt_rx_agc(struct rtw89_dev * rtwdev)6540 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
6541 {
6542 	struct rtw89_btc *btc = &rtwdev->btc;
6543 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6544 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
6545 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
6546 	bool bt_hi_lna_rx = false;
6547 
6548 	if (wl_rinfo->link_mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
6549 		bt_hi_lna_rx = true;
6550 
6551 	if (bt_hi_lna_rx == bt->hi_lna_rx)
6552 		return;
6553 
6554 	_write_scbd(rtwdev, BTC_BT_1ST, BTC_WSCB_BT_HILNA, bt_hi_lna_rx);
6555 }
6556 
_set_bt_rx_scan_pri(struct rtw89_dev * rtwdev)6557 static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev)
6558 {
6559 	struct rtw89_btc *btc = &rtwdev->btc;
6560 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
6561 
6562 	_write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_RXSCAN_PRI,
6563 		    (bool)(!!bt->scan_rx_low_pri));
6564 }
6565 
_wl_req_mac(struct rtw89_dev * rtwdev,u8 mac)6566 static void _wl_req_mac(struct rtw89_dev *rtwdev, u8 mac)
6567 {
6568 	struct rtw89_btc *btc = &rtwdev->btc;
6569 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6570 	struct rtw89_btc_dm *dm = &btc->dm;
6571 	u32 add;
6572 
6573 	if (mac == wl->pta_req_mac)
6574 		return;
6575 
6576 	dm->ost_info.pta_req_hw_band = mac;
6577 	wl->pta_req_mac = mac;
6578 	wl->pta_reg_mac_chg = true;
6579 
6580 	if (btc->ver->fcxosi)
6581 		return;
6582 
6583 	if (rtwdev->chip->chip_gen == RTW89_CHIP_BE)
6584 		add = R_BE_BTC_CFG;
6585 	else
6586 		add = R_AX_BTC_CFG;
6587 
6588 	if (mac == RTW89_MAC_0)
6589 		rtw89_write32_clr(rtwdev, add, B_AX_WL_SRC);
6590 	else
6591 		rtw89_write32_set(rtwdev, add, B_AX_WL_SRC);
6592 }
6593 
_update_zb_coex_tbl(struct rtw89_dev * rtwdev)6594 static void _update_zb_coex_tbl(struct rtw89_dev *rtwdev)
6595 {
6596 	struct rtw89_btc *btc = &rtwdev->btc;
6597 	u32 zb_tbl0 = 0xda5a5a5a, zb_tbl1 = 0xda5a5a5a;
6598 	u8 link_mode_chg = btc->cx.wl.link_mode_chg;
6599 	u8 mode = btc->cx.wl.role_info.link_mode;
6600 
6601 	if (btc->dm.run_reason != BTC_RSN_NTFY_INIT && !link_mode_chg)
6602 		return;
6603 
6604 	if (!(btc->mdinfo.wa_type & BTC_WA_HFP_ZB))
6605 		return;
6606 
6607 	if (btc->dm.tdd_bind.rf_band == BIT(RTW89_BAND_5G) ||
6608 	    rtwdev->btc.dm.freerun) {
6609 		zb_tbl0 = 0xffffffff;
6610 		zb_tbl1 = 0xffffffff;
6611 	} else if (mode == BTC_WLINK_DB_MCC) {
6612 		zb_tbl0 = 0xffffffff; /* for E5G slot */
6613 		zb_tbl1 = 0xda5a5a5a; /* for E2G slot */
6614 	}
6615 	rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_0, zb_tbl0);
6616 	rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_1, zb_tbl1);
6617 }
6618 
_set_fw_report_map(struct rtw89_dev * rtwdev)6619 static void _set_fw_report_map(struct rtw89_dev *rtwdev)
6620 {
6621 	struct rtw89_btc *btc = &rtwdev->btc;
6622 	struct rtw89_btc_wl_smap *wl_smap = &btc->cx.wl.status.map;
6623 	struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0;
6624 	struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1;
6625 	u32 rpt_map = btc->fwinfo.rpt_en_map;
6626 	u32 bt_rom_code_id, bt_fw_ver;
6627 	bool bt_ver_unknown = false;
6628 	u32 bitmap;
6629 
6630 	if (wl_smap->rf_off == 1 || wl_smap->lps != BTC_LPS_OFF) {
6631 		rtw89_btc_fw_en_rpt(rtwdev, false, 0);
6632 		return;
6633 	}
6634 
6635 	rpt_map |= rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_MREG);
6636 
6637 	bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_SCAN_INFO);
6638 	if ((bt0->run_patch_code && bt0->enable.now) ||
6639 	    (bt1->run_patch_code && bt1->enable.now))
6640 		rpt_map |= bitmap;
6641 	else
6642 		rpt_map &= ~bitmap;
6643 
6644 	bt_rom_code_id = chip_id_to_bt_rom_code_id(rtwdev->btc.ver->chip_id);
6645 	bt_fw_ver = bt0->ver_info.fw & 0xffff;
6646 	if (bt_fw_ver == 0 ||
6647 	    (bt_fw_ver == bt_rom_code_id && bt0->run_patch_code))
6648 		bt_ver_unknown = true;
6649 
6650 	bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_VER_INFO);
6651 	if (bt0->enable.now && bt_ver_unknown)
6652 		rpt_map |= bitmap;
6653 	else
6654 		rpt_map &= ~bitmap;
6655 
6656 	bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_AFH_MAP) |
6657 		 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_AFH_MAP_LE) |
6658 		 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_TX_PWR_LVL);
6659 	if (bt0->link_info.link_cnt.now ||
6660 	    bt0->link_info_56g.link_cnt.now ||
6661 	    bt1->link_info.link_cnt.now ||
6662 	    bt1->link_info_56g.link_cnt.now)
6663 		rpt_map |= bitmap;
6664 	else
6665 		rpt_map &= ~bitmap;
6666 
6667 	bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_DEVICE_INFO);
6668 	if ((bt0->link_info.a2dp_desc.exist &&
6669 	     bt0->link_info.a2dp_desc.play_latency) ||
6670 	    (bt1->link_info.a2dp_desc.exist &&
6671 	     bt1->link_info.a2dp_desc.play_latency))
6672 		rpt_map |= bitmap;
6673 	else
6674 		rpt_map &= ~bitmap;
6675 
6676 	rtw89_btc_fw_en_rpt(rtwdev, false, rpt_map);
6677 }
6678 
_action_common(struct rtw89_dev * rtwdev)6679 static void _action_common(struct rtw89_dev *rtwdev)
6680 {
6681 	struct rtw89_btc *btc = &rtwdev->btc;
6682 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6683 	struct rtw89_btc_wl_role_info *rinfo = &wl->role_info;
6684 	struct rtw89_btc_dm *dm = &btc->dm;
6685 	u8 i;
6686 
6687 	_wl_req_mac(rtwdev, rinfo->pta_req_band);
6688 	_update_zb_coex_tbl(rtwdev);
6689 	_set_btg_ctrl(rtwdev);
6690 	_set_wl_preagc_ctrl(rtwdev);
6691 	_set_wl_tx_limit(rtwdev);
6692 	_set_phl_bt_slot_req(rtwdev);
6693 	_set_bt_afh_info(rtwdev);
6694 	_set_bt_rx_agc(rtwdev);
6695 	_set_rf_trx_para(rtwdev);
6696 	_set_bt_rx_scan_pri(rtwdev);
6697 	_set_fw_report_map(rtwdev);
6698 
6699 	if (dm->run_reason == BTC_RSN_NTFY_INIT ||
6700 	    dm->run_reason == BTC_RSN_NTFY_RADIO_STATE ||
6701 	    dm->run_reason == BTC_RSN_NTFY_POWEROFF)
6702 		_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6703 
6704 	for (i = BTC_BT_1ST; i <= BTC_BT_2ND; i++)
6705 		_sned_h2c_w2bscbd(rtwdev, false, i);
6706 
6707 	if (btc->ver->fcxosi) {
6708 		if (memcmp(&dm->ost_info_last, &dm->ost_info,
6709 			   sizeof(dm->ost_info_last)) ||
6710 		    dm->run_reason == BTC_RSN_NTFY_INIT ||
6711 		    dm->run_reason == BTC_RSN_NTFY_RADIO_STATE) {
6712 			dm->ost_info_last = dm->ost_info;
6713 			_fw_set_drv_info(rtwdev, CXDRVINFO_OSI);
6714 		}
6715 	}
6716 	dm->tdma_instant_excute = 0;
6717 	dm->lps_ctrl_change = false;
6718 	wl->role_info.link_mode_chg = 0;
6719 	wl->pta_reg_mac_chg = false;
6720 	dm->pre_agc_chg = false;
6721 	wl->dbcc_chg = 0;
6722 }
6723 
_action_by_bt(struct rtw89_dev * rtwdev)6724 static void _action_by_bt(struct rtw89_dev *rtwdev)
6725 {
6726 	struct rtw89_btc *btc = &rtwdev->btc;
6727 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
6728 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
6729 	struct rtw89_btc_bt_leaudio_desc leaudio = bt_linfo->leaudio_desc;
6730 	struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
6731 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
6732 	struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
6733 	struct rtw89_btc_dm *dm = &btc->dm;
6734 	u8 profile_map = 0;
6735 
6736 	if (dm->freerun_chk) {
6737 		_action_freerun(rtwdev);
6738 		return;
6739 	}
6740 
6741 	if (bt_linfo->hfp_desc.exist)
6742 		profile_map |= BTC_BT_HFP;
6743 
6744 	if (bt_linfo->hid_desc.exist)
6745 		profile_map |= BTC_BT_HID;
6746 
6747 	if (bt_linfo->a2dp_desc.exist)
6748 		profile_map |= BTC_BT_A2DP;
6749 
6750 	if (bt_linfo->pan_desc.exist)
6751 		profile_map |= BTC_BT_PAN;
6752 
6753 	if (leaudio.bis_exist)
6754 		profile_map |= BTC_BT_BIS;
6755 
6756 	if (leaudio.cis_exist)
6757 		profile_map |= BTC_BT_CIS;
6758 
6759 	switch (profile_map) {
6760 	case BTC_BT_NOPROFILE:
6761 		if (pan.active)
6762 			_action_bt_pan(rtwdev);
6763 		else
6764 			_action_bt_idle(rtwdev);
6765 		break;
6766 	case BTC_BT_HFP:
6767 		_action_bt_hfp(rtwdev);
6768 		break;
6769 	case BTC_BT_HFP | BTC_BT_HID:
6770 	case BTC_BT_HID:
6771 		_action_bt_hid(rtwdev);
6772 		break;
6773 	case BTC_BT_A2DP:
6774 		if (a2dp.sink)
6775 			_action_bt_a2dpsink(rtwdev);
6776 		else if (bt_linfo->multi_link.now && !hid.pair_cnt)
6777 			_action_bt_a2dp_pan(rtwdev);
6778 		else
6779 			_action_bt_a2dp(rtwdev);
6780 		break;
6781 	case BTC_BT_PAN:
6782 		_action_bt_pan(rtwdev);
6783 		break;
6784 	case BTC_BT_BIS:
6785 		_action_bt_bis(rtwdev);
6786 		break;
6787 	case BTC_BT_CIS:
6788 	case BTC_BT_CIS | BTC_BT_HID:
6789 		_action_bt_cis(rtwdev);
6790 		break;
6791 	case BTC_BT_A2DP | BTC_BT_HFP:
6792 	case BTC_BT_A2DP | BTC_BT_HID:
6793 	case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID:
6794 		if (a2dp.sink)
6795 			_action_bt_a2dpsink(rtwdev);
6796 		else if (pan.active)
6797 			_action_bt_a2dp_pan_hid(rtwdev);
6798 		else
6799 			_action_bt_a2dp_hid(rtwdev);
6800 		break;
6801 	case BTC_BT_A2DP | BTC_BT_PAN:
6802 		if (a2dp.sink)
6803 			_action_bt_a2dpsink(rtwdev);
6804 		else
6805 			_action_bt_a2dp_pan(rtwdev);
6806 		break;
6807 	case BTC_BT_PAN | BTC_BT_HFP:
6808 	case BTC_BT_PAN | BTC_BT_HID:
6809 	case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID:
6810 		_action_bt_pan_hid(rtwdev);
6811 		break;
6812 	case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID:
6813 	case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP:
6814 	default:
6815 		if (a2dp.sink)
6816 			_action_bt_a2dpsink(rtwdev);
6817 		else
6818 			_action_bt_a2dp_pan_hid(rtwdev);
6819 		break;
6820 	}
6821 }
6822 
_action_wl_2g_sta(struct rtw89_dev * rtwdev)6823 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev)
6824 {
6825 	_action_by_bt(rtwdev);
6826 }
6827 
_action_wl_25g_mcc(struct rtw89_dev * rtwdev)6828 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev)
6829 {
6830 	struct rtw89_btc *btc = &rtwdev->btc;
6831 	u16 policy_type = BTC_CXP_OFF_BT;
6832 
6833 	if (btc->ant_type == BTC_ANT_SHARED) {
6834 		if (btc->cx.wl.status.map._4way)
6835 			policy_type = BTC_CXP_OFFE_WL;
6836 		else if (btc->cx.wl.status.val & btc_scanning_map.val)
6837 			policy_type = BTC_CXP_OFFE_2GBWMIXB;
6838 		else if (btc->cx.bt0.link_info.status.map.connect == 0)
6839 			policy_type = BTC_CXP_OFFE_2GISOB;
6840 		else
6841 			policy_type = BTC_CXP_OFFE_2GBWISOB;
6842 	} else { /* dedicated-antenna */
6843 		policy_type = BTC_CXP_OFF_EQ0;
6844 	}
6845 
6846 	btc->dm.e2g_slot_limit = BTC_E2G_LIMIT_DEF;
6847 
6848 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
6849 	_set_policy(rtwdev, policy_type, BTC_ACT_WL_25G_MCC);
6850 }
6851 
_action_wl_scan(struct rtw89_dev * rtwdev)6852 static void _action_wl_scan(struct rtw89_dev *rtwdev)
6853 {
6854 	struct rtw89_btc *btc = &rtwdev->btc;
6855 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6856 	struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6857 
6858 	if (btc->cx.state_map != BTC_WLINKING &&
6859 	    btc->ctrl.wl_ctrl_info.fw_scan) {
6860 		_action_wl_25g_mcc(rtwdev);
6861 		rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n");
6862 	} else if (rtwdev->dbcc_en) {
6863 		if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G &&
6864 		    wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
6865 			_action_wl_5g(rtwdev);
6866 		else
6867 			_action_by_bt(rtwdev);
6868 	} else {
6869 		if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G)
6870 			_action_wl_5g(rtwdev);
6871 		else
6872 			_action_by_bt(rtwdev);
6873 	}
6874 }
6875 
_action_wl_2g_mcc(struct rtw89_dev * rtwdev)6876 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev)
6877 {	struct rtw89_btc *btc = &rtwdev->btc;
6878 
6879 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6880 
6881 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6882 		if (btc->cx.bt0.link_info.link_cnt.now == 0)
6883 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
6884 				    BTC_ACT_WL_2G_MCC);
6885 		else
6886 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF,
6887 				    BTC_ACT_WL_2G_MCC);
6888 	} else { /* dedicated-antenna */
6889 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC);
6890 	}
6891 }
6892 
_action_wl_2g_scc(struct rtw89_dev * rtwdev)6893 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev)
6894 {
6895 	struct rtw89_btc *btc = &rtwdev->btc;
6896 	struct rtw89_btc_dm *dm = &btc->dm;
6897 	u16 policy_type;
6898 
6899 	if (!dm->tdd_bind.bt_smap.connect)
6900 		policy_type = BTC_CXP_OFFE_2GISOB;
6901 	else
6902 		policy_type = BTC_CXP_OFFE_2GBWISOB;
6903 
6904 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_PTA);
6905 	_set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
6906 }
6907 
_action_wl_2g_ap(struct rtw89_dev * rtwdev)6908 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
6909 {
6910 	struct rtw89_btc *btc = &rtwdev->btc;
6911 
6912 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6913 
6914 	if (btc->ant_type == BTC_ANT_SHARED) {
6915 		if (btc->cx.bt0.link_info.link_cnt.now == 0)
6916 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
6917 				    BTC_ACT_WL_2G_AP);
6918 		else
6919 			_set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP);
6920 	} else {/* dedicated-antenna */
6921 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP);
6922 	}
6923 }
6924 
_action_wl_2g_go(struct rtw89_dev * rtwdev)6925 static void _action_wl_2g_go(struct rtw89_dev *rtwdev)
6926 {
6927 	struct rtw89_btc *btc = &rtwdev->btc;
6928 
6929 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6930 
6931 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6932 		if (btc->cx.bt0.link_info.link_cnt.now == 0)
6933 			_set_policy(rtwdev,
6934 				    BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO);
6935 		else
6936 			_set_policy(rtwdev,
6937 				    BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO);
6938 	} else { /* dedicated-antenna */
6939 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO);
6940 	}
6941 }
6942 
_action_wl_2g_gc(struct rtw89_dev * rtwdev)6943 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev)
6944 {
6945 	struct rtw89_btc *btc = &rtwdev->btc;
6946 
6947 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6948 
6949 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6950 		_action_by_bt(rtwdev);
6951 	} else {/* dedicated-antenna */
6952 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC);
6953 	}
6954 }
6955 
_action_wl_2g_nan(struct rtw89_dev * rtwdev)6956 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev)
6957 {
6958 	struct rtw89_btc *btc = &rtwdev->btc;
6959 
6960 	_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6961 
6962 	if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6963 		if (btc->cx.bt0.link_info.link_cnt.now == 0)
6964 			_set_policy(rtwdev,
6965 				    BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN);
6966 		else
6967 			_set_policy(rtwdev,
6968 				    BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN);
6969 	} else { /* dedicated-antenna */
6970 		_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN);
6971 	}
6972 }
6973 
_sned_h2c_w2bscbd(struct rtw89_dev * rtwdev,bool force_exec,u8 bid)6974 static u8 _sned_h2c_w2bscbd(struct rtw89_dev *rtwdev, bool force_exec, u8 bid)
6975 {
6976 	struct rtw89_btc *btc = &rtwdev->btc;
6977 	struct rtw89_btc_cx *cx = &btc->cx;
6978 	struct rtw89_btc_wl_info *wl = &cx->wl;
6979 	u8 cnt_idx = BTC_WCNT_SCBDUPDATE;
6980 	u8 h2c_func = SET_IOFLD_SCBD;
6981 	u8 buf[4];
6982 
6983 	if (bid == BTC_BT_2ND) {
6984 		if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))
6985 			return 0;
6986 
6987 		h2c_func |= BT_H2C_FUNC_BT2ND;
6988 		cnt_idx = BTC_WCNT_SCBDUPDATE2;
6989 	}
6990 
6991 	if (wl->scbd_chg[bid] || force_exec) {
6992 		/* Add delay to avoid BT FW loss information */
6993 
6994 		btc_dw2b(buf, 0, (wl->scbd[bid] | BIT(31))); /* trig */
6995 		if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO) {
6996 			if (!_send_fw_cmd(rtwdev, BTFC_SET,
6997 					  h2c_func, buf, sizeof(buf)))
6998 				return 0;
6999 		} else {
7000 			rtw89_mac_cfg_sb(rtwdev, wl->scbd[bid]);
7001 		}
7002 		wl->scbd_chg[bid] = 0;
7003 		wl->wcnt[cnt_idx]++;
7004 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7005 			    "[BTC], %s() write BT%d scbd:0x%08x\n",
7006 			    __func__, bid, wl->scbd[bid]);
7007 	}
7008 	return 1;
7009 }
7010 
_write_scbd(struct rtw89_dev * rtwdev,u8 bid,u32 val,bool state)7011 static void _write_scbd(struct rtw89_dev *rtwdev, u8 bid, u32 val, bool state)
7012 {
7013 	const struct rtw89_chip_info *chip = rtwdev->chip;
7014 	struct rtw89_btc *btc = &rtwdev->btc;
7015 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7016 	struct rtw89_btc_dm *dm = &btc->dm;
7017 	u8 force_exec, id, id_start, id_stop;
7018 	u32 scbd = 0;
7019 
7020 	if (!chip->scbd)
7021 		return;
7022 
7023 	if (bid == BTC_ALL_BT) {
7024 		id_start = BTC_BT_1ST;
7025 		id_stop = BTC_BT_2ND;
7026 	} else {
7027 		id_start = bid;
7028 		id_stop = bid;
7029 	}
7030 
7031 	for (id = id_start; id <= id_stop; id++) {
7032 		force_exec = false;
7033 		if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) &&
7034 		    id == BTC_BT_2ND)
7035 			continue;
7036 
7037 		if (state)
7038 			scbd = wl->scbd[id] | val;
7039 		else
7040 			scbd = wl->scbd[id] & (~val);
7041 
7042 		if (val & BTC_WSCB_CTCODE ||
7043 		    val & BTC_WSCB_RXGAIN ||
7044 		    val & BTC_WSCB_RXGAIN_56G) { /* instant exec */
7045 			force_exec = true;
7046 			wl->scbd[id] = scbd;
7047 			dm->scbd_write_instant = 1;
7048 			if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO)
7049 				_sned_h2c_w2bscbd(rtwdev, force_exec, id);
7050 			else
7051 				rtw89_mac_cfg_sb(rtwdev, wl->scbd[id]);
7052 			dm->scbd_write_instant = 0;
7053 		} else if ((val & BTC_WSCB_ACTIVE ||
7054 			   val & BTC_WSCB_ON ||
7055 			   val & BTC_WSCB_WLRFK) ||
7056 			   scbd != wl->scbd[id]) {
7057 			/*
7058 			 * Just update wl->scbd[] and set wl->scbd_chg[],
7059 			 * moved "Write scoreboard I/O" to  _action_common()
7060 			 * _write_scbd will be executed if run_coex()
7061 			 */
7062 			wl->scbd[id] = scbd;
7063 			wl->scbd_chg[id] = 1;
7064 		}
7065 	}
7066 }
7067 
7068 static u8
_update_rssi_state(struct rtw89_dev * rtwdev,u8 pre_state,u8 rssi,u8 thresh)7069 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh)
7070 {
7071 	const struct rtw89_chip_info *chip = rtwdev->chip;
7072 	u8 next_state, tol = chip->rssi_tol;
7073 
7074 	if (pre_state == BTC_RSSI_ST_LOW ||
7075 	    pre_state == BTC_RSSI_ST_STAY_LOW) {
7076 		if (rssi >= (thresh + tol))
7077 			next_state = BTC_RSSI_ST_HIGH;
7078 		else
7079 			next_state = BTC_RSSI_ST_STAY_LOW;
7080 	} else {
7081 		if (rssi < thresh)
7082 			next_state = BTC_RSSI_ST_LOW;
7083 		else
7084 			next_state = BTC_RSSI_ST_STAY_HIGH;
7085 	}
7086 
7087 	return next_state;
7088 }
7089 
7090 static
_update_dbcc_band(struct rtw89_dev * rtwdev,enum rtw89_phy_idx phy_idx)7091 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
7092 {
7093 	struct rtw89_btc *btc = &rtwdev->btc;
7094 
7095 	btc->cx.wl.dbcc_info.real_band[phy_idx] =
7096 		btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ?
7097 		btc->cx.wl.dbcc_info.scan_band[phy_idx] :
7098 		btc->cx.wl.dbcc_info.op_band[phy_idx];
7099 }
7100 
7101 #define BTC_CHK_HANG_MAX 3
7102 #define BTC_SCB_INV_VALUE GENMASK(31, 0)
7103 
_get_role_link_mode(u8 role)7104 static u8 _get_role_link_mode(u8 role)
7105 {
7106 	switch (role) {
7107 	case RTW89_WIFI_ROLE_STATION:
7108 	default:
7109 		return BTC_WLINK_STA;
7110 	case RTW89_WIFI_ROLE_P2P_GO:
7111 		return BTC_WLINK_GO;
7112 	case RTW89_WIFI_ROLE_P2P_CLIENT:
7113 		return BTC_WLINK_GC;
7114 	case RTW89_WIFI_ROLE_AP:
7115 		return BTC_WLINK_AP;
7116 	}
7117 }
7118 
_chk_role_ch_group(const struct rtw89_btc_chdef * r1,const struct rtw89_btc_chdef * r2)7119 static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1,
7120 			       const struct rtw89_btc_chdef *r2)
7121 {
7122 	if (r1->chan != r2->chan) { /* primary ch is different */
7123 		return false;
7124 	} else if (r1->bw == RTW89_CHANNEL_WIDTH_40 &&
7125 		   r2->bw == RTW89_CHANNEL_WIDTH_40) {
7126 		if (r1->offset != r2->offset)
7127 			return false;
7128 	}
7129 	return true;
7130 }
7131 
_chk_dbcc(struct rtw89_dev * rtwdev,struct rtw89_btc_chdef * ch,u8 * phy,u8 * role,u8 link_cnt)7132 static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch,
7133 		    u8 *phy, u8 *role, u8 link_cnt)
7134 {
7135 	struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
7136 	struct rtw89_btc_wl_role_info *rinfo = &wl->role_info;
7137 	bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false;
7138 	u8 j, k, dbcc_2g_cid = 0, dbcc_2g_cid2 = 0;
7139 
7140 	/* find out the 2G-PHY by connect-id ->ch  */
7141 	for (j = 0; j < link_cnt; j++) {
7142 		if (ch[j].center_ch <= 14) {
7143 			is_2g_ch_exist = true;
7144 			break;
7145 		}
7146 	}
7147 
7148 	/* If no any 2G-port exist, it's impossible because 5G-exclude */
7149 	if (!is_2g_ch_exist)
7150 		return BTC_WLINK_SB_MCC;
7151 
7152 	dbcc_2g_cid = j;
7153 	rinfo->dbcc_2g_phy = phy[dbcc_2g_cid];
7154 
7155 	if (rinfo->dbcc_2g_phy == RTW89_PHY_1)
7156 		rinfo->pta_req_band = RTW89_PHY_1;
7157 	else
7158 		rinfo->pta_req_band = RTW89_PHY_0;
7159 
7160 	/* connect_cnt <= 2 */
7161 	if (link_cnt < BTC_TDMA_WLROLE_MAX)
7162 		return _get_role_link_mode(role[dbcc_2g_cid]);
7163 
7164 	/* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */
7165 	for (k = 0; k < link_cnt; k++) {
7166 		if (k == dbcc_2g_cid)
7167 			continue;
7168 
7169 		if (phy[k] == rinfo->dbcc_2g_phy) {
7170 			is_multi_role_in_2g_phy = true;
7171 			dbcc_2g_cid2 = k;
7172 			break;
7173 		}
7174 	}
7175 
7176 	/* Single-role in 2G-PHY */
7177 	if (!is_multi_role_in_2g_phy)
7178 		return _get_role_link_mode(role[dbcc_2g_cid]);
7179 
7180 	/* 2-role in 2G-PHY */
7181 	if (ch[dbcc_2g_cid2].center_ch > 14)
7182 		return BTC_WLINK_DB_MCC;
7183 	else if (_chk_role_ch_group(&ch[dbcc_2g_cid], &ch[dbcc_2g_cid2]))
7184 		return BTC_WLINK_SCC;
7185 	else
7186 		return BTC_WLINK_SB_MCC;
7187 }
7188 
_update_wl_link_mode(struct rtw89_dev * rtwdev,u8 hw_band,u8 type)7189 static void _update_wl_link_mode(struct rtw89_dev *rtwdev, u8 hw_band, u8 type)
7190 {
7191 	struct rtw89_btc *btc = &rtwdev->btc;
7192 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7193 	struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info;
7194 	struct rtw89_btc_wl_role_info *r = &wl->role_info;
7195 	u8 p2p_exist = wl->role_info.p2p_exist;
7196 
7197 	if (hw_band == RTW89_PHY_1)
7198 		p2p_exist = wl->role_info.p2p_exist_hb1;
7199 
7200 	/* MLD: nLmR --> 2L1R: 2-Link by 1-RF,  2L2R: 2-link by 2-RF */
7201 	switch (type) {
7202 	case RTW89_MR_WTYPE_NONE: /* no-link */
7203 		r->link_mode = BTC_WLINK_NOLINK;
7204 		break;
7205 	case RTW89_MR_WTYPE_NONMLD:  /* Non_MLO 1-role 2+0/0+2 */
7206 	case RTW89_MR_WTYPE_MLD1L1R: /* MLO only-1 link 2+0/0+2 */
7207 		if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) {
7208 			r->link_mode = BTC_WLINK_GO;
7209 		} else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT &&
7210 			   p2p_exist) {
7211 			r->link_mode = BTC_WLINK_GC;
7212 		} else {
7213 			r->link_mode = BTC_WLINK_STA;
7214 		}
7215 		break;
7216 	case RTW89_MR_WTYPE_NONMLD_NONMLD: /* Non_MLO 2-role 2+0/0+2 */
7217 	case RTW89_MR_WTYPE_MLD1L1R_NONMLD: /* MLO only-1 link + P2P 2+0/0+2 */
7218 		if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_5GHZ ||
7219 		    mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_6GHZ) {
7220 			r->link_mode = BTC_WLINK_DB_MCC;
7221 		} else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ ||
7222 			   mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_5GHZ ||
7223 			   mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_6GHZ ||
7224 			   mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_5GHZ_6GHZ) {
7225 			r->link_mode = BTC_WLINK_SB_MCC;
7226 		} else {
7227 			r->link_mode = BTC_WLINK_SCC;
7228 		}
7229 		break;
7230 	case RTW89_MR_WTYPE_MLD2L1R: /* MLO_MLSR 2+0/0+2 */
7231 		if (p2p_exist) /* MLO_MLSR only support STA/GC */
7232 			r->link_mode = BTC_WLINK_GC;
7233 		else
7234 			r->link_mode = BTC_WLINK_STA;
7235 		break;
7236 	case RTW89_MR_WTYPE_MLD2L1R_NONMLD: /* MLO_MLSR + P2P 2+0/0+2 */
7237 	case RTW89_MR_WTYPE_MLD2L2R_NONMLD: /* MLO_MLMR + P2P 1+1/2+2*/
7238 		/* driver may doze 1-link (1+1) or 2+0->0+2->1+1
7239 		 * 2G+5G   -> TDMA slot switch by E2G/E5G
7240 		 * 5G only -> TDMA slot switch by E5G
7241 		 */
7242 		r->link_mode = BTC_WLINK_DB_MCC;
7243 		break;
7244 	case RTW89_MR_WTYPE_MLD2L2R: /* MLO_MLMR  1+1/2+2 */
7245 		/* MLMR only support STA now (2024) */
7246 		r->link_mode = BTC_WLINK_STA;
7247 		break;
7248 	}
7249 }
7250 
_update_wl_mlo_info(struct rtw89_dev * rtwdev,u8 hw_band)7251 static void _update_wl_mlo_info(struct rtw89_dev *rtwdev, u8 hw_band)
7252 {
7253 	struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
7254 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
7255 	struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info;
7256 	struct rtw89_mr_chanctx_info qinfo;
7257 	struct rtw89_chanctx *ch;
7258 	u8 rf_band = RTW89_BAND_2G;
7259 	u8 i, type;
7260 
7261 	/* parse MLO info form PHL API for each HW-band */
7262 	for (i = RTW89_MAC_0; i <= RTW89_MAC_1; i++) {
7263 		memset(&qinfo, 0, sizeof(qinfo));
7264 
7265 		rtw89_query_mr_chanctx_info(rtwdev, i, &qinfo);
7266 
7267 		switch (qinfo.ctxtype) {
7268 		default:
7269 			mlo_info->hwb_rf_band[i] = 0;
7270 			break;
7271 		case RTW89_MR_CTX1_2GHZ:
7272 		case RTW89_MR_CTX2_2GHZ:
7273 			mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_2G);
7274 			break;
7275 		case RTW89_MR_CTX1_5GHZ:
7276 		case RTW89_MR_CTX2_5GHZ:
7277 			mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_5G);
7278 			break;
7279 		case RTW89_MR_CTX1_6GHZ:
7280 		case RTW89_MR_CTX2_6GHZ:
7281 			mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_6G);
7282 			break;
7283 		case RTW89_MR_CTX2_2GHZ_5GHZ:
7284 			mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_2G) |
7285 						    BIT(RTW89_BAND_5G);
7286 			break;
7287 		case RTW89_MR_CTX2_2GHZ_6GHZ:
7288 			mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_2G) |
7289 						    BIT(RTW89_BAND_6G);
7290 			break;
7291 		case RTW89_MR_CTX2_5GHZ_6GHZ:
7292 			mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_5G) |
7293 						    BIT(RTW89_BAND_6G);
7294 			break;
7295 		}
7296 		mlo_info->wmode[i] = qinfo.wmode;
7297 		mlo_info->ch_type[i] = qinfo.ctxtype;
7298 		mlo_info->wtype = qinfo.wtype;
7299 		wl->rf_band_map[i] = mlo_info->hwb_rf_band[i];
7300 		ch = &rtwdev->hal.chanctx[i];
7301 		wl->rf_ch_info[i].center_ch = ch->chan.channel;
7302 		wl->rf_ch_info[i].band = ch->chan.band_type;
7303 		wl->rf_ch_info[i].chan = ch->chan.channel;
7304 		wl->rf_ch_info[i].offset = ch->chan.pri_ch_idx;
7305 		wl->rf_ch_info[i].bw = ch->chan.band_width;
7306 	}
7307 
7308 	mlo_info->link_status = rtwdev->mlo_dbcc_mode;
7309 	type = mlo_info->wtype;
7310 
7311 	if (mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R ||
7312 	    mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R ||
7313 	    mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R ||
7314 	    mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R_NONMLD ||
7315 	    mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD ||
7316 	    mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R_NONMLD)
7317 		mlo_info->mlo_en = 1;
7318 	else
7319 		mlo_info->mlo_en = 0;
7320 
7321 	if (mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_NONE &&
7322 	    mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_UNKNOWN &&
7323 	    mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_NONE &&
7324 	    mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_UNKNOWN)
7325 		mlo_info->dual_hw_band_en = 1; /* two HW-hand link exist */
7326 	else
7327 		mlo_info->dual_hw_band_en = 0;
7328 
7329 	if (mlo_info->link_status == MLO_2_PLUS_0_2RF ||
7330 	    mlo_info->link_status == MLO_0_PLUS_2_2RF ||
7331 	    mlo_info->link_status == MLO_2_PLUS_2_2RF)
7332 		mlo_info->mlo_adie = 2;
7333 	else
7334 		mlo_info->mlo_adie = 1;
7335 
7336 	switch (mlo_info->link_status) {
7337 	default:
7338 	case MLO_2_PLUS_0_1RF: /* 2+0 */
7339 	case MLO_2_PLUS_0_2RF:
7340 		_update_wl_link_mode(rtwdev, RTW89_MAC_0, type);
7341 		wl_rinfo->link_mode_hb1 = wl_rinfo->link_mode;
7342 		wl_rinfo->pta_req_band = RTW89_MAC_0;
7343 		wl_rinfo->dbcc_2g_phy = RTW89_PHY_0;
7344 		wl_rinfo->dbcc_en = 0;
7345 
7346 		rf_band = wl->rf_band_map[RTW89_PHY_0];
7347 		mlo_info->path_rf_band[BTC_RF_S0] = rf_band;
7348 		mlo_info->path_rf_band[BTC_RF_S1] = rf_band;
7349 		break;
7350 	case MLO_0_PLUS_2_1RF: /* 0+2 */
7351 	case MLO_0_PLUS_2_2RF:
7352 		_update_wl_link_mode(rtwdev, RTW89_MAC_1, type);
7353 		wl_rinfo->link_mode_hb1 = wl_rinfo->link_mode;
7354 		wl_rinfo->pta_req_band = RTW89_MAC_1;
7355 		wl_rinfo->dbcc_2g_phy = RTW89_PHY_1;
7356 		wl_rinfo->dbcc_en = 0;
7357 
7358 		rf_band = wl->rf_band_map[RTW89_PHY_1];
7359 		mlo_info->path_rf_band[BTC_RF_S0] = rf_band;
7360 		mlo_info->path_rf_band[BTC_RF_S1] = rf_band;
7361 		break;
7362 	case MLO_1_PLUS_1_1RF: /* 1+1 */
7363 	case MLO_1_PLUS_1_2RF: /* 1+1 */
7364 	case MLO_2_PLUS_2_2RF: /* 2+2 */
7365 	case DBCC_LEGACY: /* DBCC 1+1 */
7366 		/* Check ch count from ch_type and modify type*/
7367 		if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_2GHZ ||
7368 		    mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_5GHZ ||
7369 		    mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_6GHZ)
7370 			type = RTW89_MR_WTYPE_NONMLD; /* only 1-role */
7371 		else
7372 			type = RTW89_MR_WTYPE_NONMLD_NONMLD;
7373 
7374 		rf_band = wl->rf_band_map[hw_band];
7375 		_update_wl_link_mode(rtwdev, hw_band, type);
7376 
7377 		if (hw_band == RTW89_MAC_0) {
7378 			mlo_info->path_rf_band[BTC_RF_S0] = rf_band;
7379 		} else {
7380 			wl_rinfo->link_mode_hb1 = wl_rinfo->link_mode;
7381 			mlo_info->path_rf_band[BTC_RF_S1] = rf_band;
7382 		}
7383 
7384 		/* set pta_req_band for 1-PTA architecture */
7385 		if (wl->rf_band_map[RTW89_MAC_0] & BIT(RTW89_BAND_2G)) {
7386 			wl_rinfo->pta_req_band = RTW89_MAC_0;
7387 			wl_rinfo->dbcc_2g_phy = RTW89_PHY_0;
7388 		} else if (wl->rf_band_map[RTW89_MAC_1] & BIT(RTW89_BAND_2G)) {
7389 			wl_rinfo->pta_req_band = RTW89_MAC_1;
7390 			wl_rinfo->dbcc_2g_phy = RTW89_PHY_1;
7391 		} else { /* Both HW-BAND are not on 2.4G*/
7392 			wl_rinfo->pta_req_band = RTW89_MAC_0;
7393 			wl_rinfo->dbcc_2g_phy = RTW89_PHY_0;
7394 		}
7395 		break;
7396 	}
7397 
7398 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(), mode=%s, pta_band=%d",
7399 		    __func__, id_to_linkmode(wl_rinfo->link_mode),
7400 		    wl_rinfo->pta_req_band);
7401 }
7402 
_update_wl_non_mlo_info(struct rtw89_dev * rtwdev)7403 static void _update_wl_non_mlo_info(struct rtw89_dev *rtwdev)
7404 {
7405 	struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
7406 	struct rtw89_btc_wl_rlink *rlink = NULL;
7407 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
7408 	struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7409 	u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7410 	u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7411 	bool b2g = false, b5g = false, outloop = false;
7412 	u8 mode = BTC_WLINK_NOLINK;
7413 	u8 cnt_2g = 0, cnt_5g = 0;
7414 	u8 i, j, cnt = 0;
7415 
7416 	for (j = RTW89_PHY_0; j < RTW89_PHY_NUM; j++) {
7417 		wl->rf_band_map[j] = 0; /* j=link id, is the link use which band */
7418 		for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
7419 			rlink = &wl_rinfo->rlink[i][j];
7420 
7421 			if (!rlink->active || !rlink->connected)
7422 				continue;
7423 
7424 			if (cnt >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER) {
7425 				outloop = true;
7426 				break;
7427 			}
7428 
7429 			cid_ch[cnt] = wl->rlink_info[i][j].chdef;
7430 			cid_phy[cnt] = rlink->phy;
7431 			cid_role[cnt] = rlink->role;
7432 			cnt++;
7433 
7434 			if (rlink->rf_band != RTW89_BAND_2G) {
7435 				cnt_5g++;
7436 				b5g = true;
7437 			} else {
7438 				cnt_2g++;
7439 				b2g = true;
7440 			}
7441 			wl->rf_band_map[j] |= BIT(rlink->rf_band);
7442 		}
7443 		if (outloop)
7444 			break;
7445 	}
7446 
7447 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7448 		    "[BTC], %s(): cnt_2g=%d, cnt_5g=%d\n", __func__, cnt_2g, cnt_5g);
7449 
7450 	wl_rinfo->pta_req_band = RTW89_PHY_0; /* no 0+2 for non-MLO */
7451 	wl_rinfo->dbcc_en = rtwdev->dbcc_en;
7452 
7453 	/* Be careful to change the following sequence!! */
7454 	if (cnt == 0) {
7455 		mode = BTC_WLINK_NOLINK;
7456 	} else if (wl_rinfo->dbcc_en) {
7457 		/* update pta_req_band to 2.4GHz HW-BAND for DBCC = 1*/
7458 		mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt);
7459 	} else if (!b2g && b5g) {
7460 		mode = _get_role_link_mode(cid_role[0]);
7461 	} else if (b2g && b5g) {
7462 		mode = BTC_WLINK_DB_MCC;
7463 	} else if (cnt >= 2) {
7464 		if (_chk_role_ch_group(&cid_ch[0], &cid_ch[1]))
7465 			mode = BTC_WLINK_SCC;
7466 		else
7467 			mode = BTC_WLINK_SB_MCC;
7468 	} else {
7469 		mode = _get_role_link_mode(cid_role[0]);
7470 	}
7471 
7472 	wl_rinfo->link_mode = mode;
7473 	wl_rinfo->link_mode_hb1 = mode;
7474 }
7475 
_sync_wl_link_mode_v0(struct rtw89_dev * rtwdev)7476 static void _sync_wl_link_mode_v0(struct rtw89_dev *rtwdev)
7477 {
7478 	struct rtw89_btc_wl_role_info *r = &rtwdev->btc.cx.wl.role_info;
7479 	bool has_2g = false;
7480 	int i, j;
7481 
7482 	for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER && !has_2g; i++)
7483 		for (j = 0; j < RTW89_MAC_NUM && !has_2g; j++)
7484 			if (r->rlink[i][j].connected &&
7485 			    r->rlink[i][j].rf_band == RTW89_BAND_2G)
7486 				has_2g = true;
7487 
7488 	if (!has_2g && r->link_mode != BTC_WLINK_NOLINK) {
7489 		r->link_mode_v0 = BTC_WLINK_V0_5G;
7490 		return;
7491 	}
7492 
7493 	switch (r->link_mode) {
7494 	case BTC_WLINK_NOLINK:
7495 		r->link_mode_v0 = BTC_WLINK_V0_NOLINK;
7496 		break;
7497 	case BTC_WLINK_STA:
7498 		r->link_mode_v0 = BTC_WLINK_V0_2G_STA;
7499 		break;
7500 	case BTC_WLINK_AP:
7501 		r->link_mode_v0 = BTC_WLINK_V0_2G_AP;
7502 		break;
7503 	case BTC_WLINK_GO:
7504 		r->link_mode_v0 = BTC_WLINK_V0_2G_GO;
7505 		break;
7506 	case BTC_WLINK_GC:
7507 		r->link_mode_v0 = BTC_WLINK_V0_2G_GC;
7508 		break;
7509 	case BTC_WLINK_SCC:
7510 		r->link_mode_v0 = BTC_WLINK_V0_2G_SCC;
7511 		break;
7512 	case BTC_WLINK_SB_MCC:
7513 		r->link_mode_v0 = BTC_WLINK_V0_2G_MCC;
7514 		break;
7515 	case BTC_WLINK_DB_MCC:
7516 		r->link_mode_v0 = BTC_WLINK_V0_25G_MCC;
7517 		break;
7518 	default:
7519 		r->link_mode_v0 = BTC_WLINK_V0_OTHER;
7520 		break;
7521 	}
7522 }
7523 
_modify_role_link_mode(struct rtw89_dev * rtwdev,u8 hw_band)7524 static void _modify_role_link_mode(struct rtw89_dev *rtwdev, u8 hw_band)
7525 {
7526 	struct rtw89_btc *btc = &rtwdev->btc;
7527 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7528 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
7529 	u8 go_cleint_exist = wl->go_client_exist;
7530 	u8 *link_mode = &wl_rinfo->link_mode;
7531 	u32 role_map = wl_rinfo->role_map;
7532 	u8 noa_exist = wl->noa_exist;
7533 	u32 mrole = BTC_WLMROLE_NONE;
7534 
7535 	if (hw_band == RTW89_PHY_1) {
7536 		*link_mode = wl_rinfo->link_mode_hb1;
7537 		role_map = wl_rinfo->role_map_hb1;
7538 		go_cleint_exist = wl->go_client_exist_hb1;
7539 	}
7540 
7541 	/* if no client_joined, don't care P2P-GO/AP role */
7542 	if (((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
7543 	      (role_map & BIT(RTW89_WIFI_ROLE_AP))) && !go_cleint_exist) {
7544 		if (*link_mode == BTC_WLINK_SCC) {
7545 			*link_mode = BTC_WLINK_STA;
7546 		} else if (*link_mode == BTC_WLINK_GO ||
7547 			   *link_mode == BTC_WLINK_AP) {
7548 			*link_mode = BTC_WLINK_NOLINK;
7549 		}
7550 	}
7551 
7552 	/* Identify 2-Role type  */
7553 	if  (*link_mode == BTC_WLINK_SCC ||
7554 	     *link_mode == BTC_WLINK_SB_MCC ||
7555 	     *link_mode == BTC_WLINK_DB_MCC) {
7556 		if ((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
7557 		     (role_map & BIT(RTW89_WIFI_ROLE_AP))) {
7558 			if (noa_exist)
7559 				mrole = BTC_WLMROLE_STA_GO_NOA;
7560 			else
7561 				mrole = BTC_WLMROLE_STA_GO;
7562 		} else if (role_map & BIT(RTW89_WIFI_ROLE_P2P_CLIENT)) {
7563 			if (noa_exist)
7564 				mrole = BTC_WLMROLE_STA_GC_NOA;
7565 			else
7566 				mrole = BTC_WLMROLE_STA_GC;
7567 		} else {
7568 			mrole = BTC_WLMROLE_STA_STA;
7569 		}
7570 
7571 		if (hw_band == RTW89_PHY_0) {
7572 			wl_rinfo->mrole_type &= GENMASK(31, 16); /* clear Low-Word */
7573 			wl_rinfo->mrole_type |= mrole;
7574 		} else {
7575 			wl_rinfo->mrole_type &= GENMASK(15, 0); /* clear high-Word */
7576 			wl_rinfo->mrole_type |= (mrole << 16);
7577 		}
7578 	} else {
7579 		wl_rinfo->mrole_type = BTC_WLMROLE_NONE;
7580 	}
7581 
7582 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
7583 		    "[BTC], %s(): link_mode=%s, mrole_type=%d\n", __func__,
7584 		    id_to_linkmode(wl_rinfo->link_mode), wl_rinfo->mrole_type);
7585 }
7586 
_update_wl_info(struct rtw89_dev * rtwdev,struct rtw89_btc_wl_link_info * wl_linfo)7587 static void _update_wl_info(struct rtw89_dev *rtwdev, struct rtw89_btc_wl_link_info *wl_linfo)
7588 {
7589 	struct rtw89_btc *btc = &rtwdev->btc;
7590 	struct rtw89_btc_dm *dm = &btc->dm;
7591 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7592 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
7593 	struct rtw89_btc_wl_rlink *rlink = NULL;
7594 	u8 dbcc_en_ori, is_5g_hi_ch = 0, bg_mode = 0, p2p_exist = 0;
7595 	u8 go_client_exist = 0, noa_exist = 0;
7596 	u8 rlink_id = wl_linfo->phy;
7597 	u8 role_id = wl_linfo->pid;
7598 	u8 i, link_mode_ori;
7599 	u32 role_map = 0;
7600 
7601 	if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id >= RTW89_BAND_NUM)
7602 		return;
7603 
7604 	/*
7605 	 * Extract wl->link_info[role_id][rlink_id] to wl->role_info
7606 	 * role_id: role index
7607 	 * rlink_id: rlink index (= HW-band index)
7608 	 * pid: port_index
7609 	 */
7610 	rlink = &wl_rinfo->rlink[role_id][rlink_id];
7611 
7612 	rlink->role = wl_linfo->role;
7613 	rlink->active = wl_linfo->active; /* Doze or not */
7614 	rlink->pid = wl_linfo->pid;
7615 	rlink->mac_id = wl_linfo->mac_id;
7616 	rlink->phy = wl_linfo->phy;
7617 	rlink->rf_band = wl_linfo->chdef.band;
7618 	rlink->ch = wl_linfo->chdef.center_ch;
7619 	rlink->bw = wl_linfo->chdef.bw;
7620 	rlink->noa = wl_linfo->noa;
7621 	rlink->noa_dur = wl_linfo->noa_duration / 1000;
7622 	rlink->client_cnt = wl_linfo->client_cnt;
7623 	rlink->mode = wl_linfo->mode;
7624 
7625 	/* check if rlink connect? */
7626 	switch (wl_linfo->connected) {
7627 	case MLME_NO_LINK:
7628 		rlink->connected = 0;
7629 		break;
7630 	case MLME_LINKED:
7631 		rlink->connected = 1;
7632 
7633 		/* reset special-AP flag if station mode linked */
7634 		dm->leak_ap = 0;
7635 		break;
7636 	default:
7637 		return;
7638 	}
7639 
7640 	/* update by HW-Band */
7641 	for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { /* i = role_id */
7642 		rlink = &wl_rinfo->rlink[i][rlink_id];
7643 
7644 		if (!rlink->active || !rlink->connected)
7645 			continue;
7646 
7647 		role_map |= BIT(rlink->role);
7648 
7649 		/* Identify if P2P-Go (GO/GC/AP) exist at 2GHz band */
7650 		if (((rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
7651 		      rlink->role == RTW89_WIFI_ROLE_AP) &&
7652 		     rlink->client_cnt > 1)) {
7653 			p2p_exist = 1;
7654 			go_client_exist = 1;
7655 		}
7656 
7657 		if (rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)
7658 			p2p_exist = 1;
7659 
7660 		/* only one noa-role exist */
7661 		if (rlink->noa && rlink->noa_dur > 0)
7662 			noa_exist = 1;
7663 
7664 		/* for WL 5G-Rx interfered with BT issue */
7665 		if (rlink->rf_band == RTW89_BAND_5G && rlink->ch >= 100)
7666 			is_5g_hi_ch = 1;
7667 
7668 		if ((rlink->mode & BIT(BTC_WL_MODE_11B)) ||
7669 		    (rlink->mode & BIT(BTC_WL_MODE_11G)))
7670 			bg_mode = 1;
7671 	}
7672 
7673 	if (rlink_id == RTW89_PHY_0) {
7674 		link_mode_ori = wl_rinfo->link_mode;
7675 		wl->is_5g_hi_ch = is_5g_hi_ch;
7676 		wl->bg_mode = bg_mode;
7677 		wl->go_client_exist = go_client_exist;
7678 		wl->noa_exist = noa_exist;
7679 		wl_rinfo->p2p_exist = p2p_exist;
7680 		wl_rinfo->role_map = role_map;
7681 	} else {
7682 		link_mode_ori = wl_rinfo->link_mode_hb1;
7683 		wl->is_5g_hi_ch_hb1 = is_5g_hi_ch;
7684 		wl->bg_mode_hb1 = bg_mode;
7685 		wl->go_client_exist_hb1 = go_client_exist;
7686 		wl->noa_exist_hb1 = noa_exist;
7687 		wl_rinfo->p2p_exist_hb1 = p2p_exist;
7688 		wl_rinfo->role_map_hb1 = role_map;
7689 	}
7690 
7691 	dbcc_en_ori = wl_rinfo->dbcc_en;
7692 
7693 	/* for MLO-supported, link-mode from driver directly */
7694 	if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) {
7695 		_update_wl_mlo_info(rtwdev, rlink_id);
7696 	} else { /* for non-MLO-supported, link-mode by BTC */
7697 		_update_wl_non_mlo_info(rtwdev);
7698 	}
7699 
7700 	_modify_role_link_mode(rtwdev, rlink_id);
7701 	_sync_wl_link_mode_v0(rtwdev);
7702 
7703 	if ((rlink_id == RTW89_PHY_0 && wl_rinfo->link_mode != link_mode_ori) ||
7704 	    (rlink_id == RTW89_PHY_1 && wl_rinfo->link_mode_hb1 != link_mode_ori)) {
7705 		wl_rinfo->link_mode_chg = 1;
7706 		wl->link_mode_chg = 1;
7707 	}
7708 
7709 	if (wl_rinfo->dbcc_en != dbcc_en_ori) {
7710 		wl->dbcc_chg = 1;
7711 		wl->role_info.dbcc_chg = 1;
7712 		wl->wcnt[BTC_WCNT_DBCC_CHG]++;
7713 	}
7714 }
7715 
rtw89_coex_act1_work(struct wiphy * wiphy,struct wiphy_work * work)7716 void rtw89_coex_act1_work(struct wiphy *wiphy, struct wiphy_work *work)
7717 {
7718 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7719 						coex_act1_work.work);
7720 	struct rtw89_btc *btc = &rtwdev->btc;
7721 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7722 	struct rtw89_btc_cx *cx = &btc->cx;
7723 	struct rtw89_btc_wl_info *wl = &cx->wl;
7724 
7725 	lockdep_assert_wiphy(wiphy);
7726 
7727 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7728 	dm->cnt_notify[BTC_NCNT_TIMER]++;
7729 	if (wl->status.map.handshake ||
7730 	    wl->status.map._4way ||
7731 	    wl->status.map.dhcp) {
7732 		wl->status.map._4way = 0;
7733 		wl->status.map.dhcp = 0;
7734 		wl->status.map.handshake = 0;
7735 	}
7736 	_run_coex(rtwdev, BTC_RSN_ACT1_WORK);
7737 }
7738 
rtw89_coex_bt_devinfo_work(struct wiphy * wiphy,struct wiphy_work * work)7739 void rtw89_coex_bt_devinfo_work(struct wiphy *wiphy, struct wiphy_work *work)
7740 {
7741 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7742 						coex_bt_devinfo_work.work);
7743 	struct rtw89_btc *btc = &rtwdev->btc;
7744 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7745 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc;
7746 
7747 	lockdep_assert_wiphy(wiphy);
7748 
7749 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7750 	dm->cnt_notify[BTC_NCNT_TIMER]++;
7751 	a2dp->play_latency = 0;
7752 	_run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK);
7753 }
7754 
rtw89_coex_rfk_chk_work(struct wiphy * wiphy,struct wiphy_work * work)7755 void rtw89_coex_rfk_chk_work(struct wiphy *wiphy, struct wiphy_work *work)
7756 {
7757 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7758 						coex_rfk_chk_work.work);
7759 	struct rtw89_btc *btc = &rtwdev->btc;
7760 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7761 	struct rtw89_btc_cx *cx = &btc->cx;
7762 	struct rtw89_btc_wl_info *wl = &cx->wl;
7763 
7764 	lockdep_assert_wiphy(wiphy);
7765 
7766 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7767 	dm->cnt_notify[BTC_NCNT_TIMER]++;
7768 	if (wl->rfk_info.state != BTC_WRFK_STOP) {
7769 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7770 			    "[BTC], %s(): RFK timeout\n", __func__);
7771 		wl->wcnt[BTC_WCNT_RFK_TIMEOUT]++;
7772 		dm->error.map.wl_rfk_timeout = true;
7773 		wl->rfk_info.state = BTC_WRFK_STOP;
7774 		_write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLRFK, false);
7775 		_run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK);
7776 	}
7777 }
7778 
_update_bt_ctrl_lps(struct rtw89_dev * rtwdev)7779 static void _update_bt_ctrl_lps(struct rtw89_dev *rtwdev)
7780 {
7781 	struct rtw89_btc *btc = &rtwdev->btc;
7782 	struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0;
7783 	struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1;
7784 	struct rtw89_btc_dm *dm = &btc->dm;
7785 	bool lps_ctrl = false;
7786 
7787 	if (dm->out_of_band || dm->freerun)
7788 		lps_ctrl = false;
7789 	else if (bt0->whql_test || bt1->whql_test)
7790 		lps_ctrl = true;
7791 	else if (bt0->link_info.a2dp_desc.exist ||
7792 		 bt0->link_info.hfp_desc.exist ||
7793 		 bt0->link_info.pan_desc.exist)
7794 		lps_ctrl = true;
7795 	else if (bt1->link_info.a2dp_desc.exist ||
7796 		 bt1->link_info.hfp_desc.exist ||
7797 		 bt1->link_info.pan_desc.exist)
7798 		lps_ctrl = true;
7799 
7800 	if (dm->lps_ctrl_scbd != lps_ctrl) {
7801 		dm->lps_ctrl_scbd = lps_ctrl;
7802 		dm->lps_ctrl_change = true;
7803 	} else {
7804 		dm->lps_ctrl_change = false;
7805 	}
7806 }
7807 
_update_bt_scbd(struct rtw89_dev * rtwdev,u8 bid)7808 static void _update_bt_scbd(struct rtw89_dev *rtwdev, u8 bid)
7809 {
7810 	struct rtw89_btc_bt_link_info *bt_2g, *bt_56g;
7811 	struct rtw89_btc *btc = &rtwdev->btc;
7812 	struct rtw89_btc_cx *cx = &btc->cx;
7813 	struct rtw89_btc_dm *dm = &btc->dm;
7814 	struct rtw89_btc_bt_info *bt;
7815 	u32 val, any_bt_connect, any_bt_6g_connect = 0;
7816 	bool bt_link_change = false;
7817 	u8 id, id_start, id_stop;
7818 
7819 	if (!rtwdev->chip->scbd || bid > BTC_ALL_BT)
7820 		return;
7821 
7822 	if (bid == BTC_ALL_BT) {
7823 		id_start = BTC_BT_1ST;
7824 		id_stop = BTC_BT_2ND;
7825 	} else {
7826 		id_start = bid;
7827 		id_stop = bid;
7828 	}
7829 
7830 	dm->lps_ctrl_change = false;
7831 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s()\n", __func__);
7832 
7833 	for (id = id_start; id <= id_stop; id++) {
7834 		bt = (id == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1;
7835 		bt_2g = &bt->link_info;
7836 		bt_56g = &bt->link_info_56g;
7837 
7838 		if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) && id == BTC_BT_2ND)
7839 			break;
7840 
7841 		val = bt->scbd_c2h;
7842 
7843 		if (val == 0xffffffff) {
7844 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
7845 				    "[BTC], %s return by invalid scbd value\n",
7846 				    __func__);
7847 			return;
7848 		}
7849 
7850 		if (!(val & BTC_BSCB_ON))
7851 			bt->enable.now = 0;
7852 		else
7853 			bt->enable.now = 1;
7854 
7855 		if (bt->enable.now != bt->enable.last)
7856 			bt_link_change = true;
7857 
7858 		/* reset bt info if bt re-enable */
7859 		if (bt->enable.now && !bt->enable.last) {
7860 			if (id == BTC_BT_1ST)
7861 				_reset_btc_var(rtwdev, BTC_RESET_BTINFO);
7862 			else
7863 				_reset_btc_var(rtwdev, BTC_RESET_BTINFO2);
7864 
7865 			bt->bcnt[BTC_BCNT_REENABLE]++;
7866 			bt->enable.now = 1;
7867 			bt->rf_band_map = BIT(RTW89_BAND_2G);
7868 			bt->link_weight[BTC_BT_B2G] = 5; /* no-profile */
7869 		}
7870 		bt->enable.last = bt->enable.now;
7871 
7872 		/* if BT will disconnect and adopt protect plan */
7873 		if ((val & BTC_BSCB_BT_PROTECT) &&
7874 		    !(bt->scbd & BTC_BSCB_BT_PROTECT))
7875 			bt->bcnt[BTC_BCNT_PROTECT]++;
7876 
7877 		bt->mbx_avl = !!(val & BTC_BSCB_ACT);
7878 		if (bt->whql_test != !!(val & BTC_BSCB_WHQL))
7879 			bt_link_change = true;
7880 
7881 		bt->whql_test = !!(val & BTC_BSCB_WHQL);
7882 		bt->btg_type = (val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE);
7883 
7884 		bt_2g->a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT);
7885 		bt_2g->pan_desc.exist = !!(val & BTC_BSCB_PAN_ACT);
7886 		bt_2g->hfp_desc.exist = !!(val & BTC_BSCB_HFP_ACT);
7887 
7888 		bt->lna_constrain = 4 + !!(val & BTC_BSCB_BT_LNAB0) +
7889 				    !!(val & BTC_BSCB_BT_LNAB1) * 2;
7890 
7891 		if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) {
7892 			if (val & BTC_BSCB_BT_15DOT4)
7893 				bt->func_type |= (BTC_BTF_THREAD | BTC_BTF_ZB);
7894 			else
7895 				bt->func_type &= ~(BTC_BTF_THREAD | BTC_BTF_ZB);
7896 		}
7897 
7898 		bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
7899 		any_bt_connect = !!(val & BTC_BSCB_BT_CONNECT);
7900 
7901 		/* if connect change */
7902 		if (bt_2g->status.map.connect != any_bt_connect ||
7903 		    bt_56g->status.map.connect != any_bt_6g_connect) {
7904 			bt_link_change = true;
7905 			bt_2g->status.map.connect = any_bt_connect;
7906 			bt_56g->status.map.connect = any_bt_6g_connect;
7907 		}
7908 
7909 		bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
7910 		bt->scbd = val;
7911 	}
7912 
7913 	_update_bt_ctrl_lps(rtwdev);
7914 
7915 	if (bt_link_change) {
7916 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7917 			    "[BTC], %s: bt status change!!\n", __func__);
7918 		/* TODO: Need to notify driver to update EXT-CTRL-BT-SLOT */
7919 	}
7920 }
7921 
_update_bt_link_cnt(struct rtw89_dev * rtwdev,struct rtw89_btc_bt_info * bt,bool b56g)7922 static void _update_bt_link_cnt(struct rtw89_dev *rtwdev,
7923 				struct rtw89_btc_bt_info *bt, bool b56g)
7924 {
7925 	struct rtw89_btc_bt_link_info *b = b56g ? &bt->link_info_56g :
7926 						  &bt->link_info;
7927 	struct rtw89_btc_bt_leaudio_desc *leaudio = &b->leaudio_desc;
7928 	struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
7929 	struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
7930 	struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
7931 	struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc;
7932 	u8 bt_rf_band = b56g ? BTC_BT_B5G : BTC_BT_B2G;
7933 	u8 val;
7934 
7935 	b->link_cnt.last = b->link_cnt.now;
7936 	b->link_cnt.now = 0;
7937 	b->link_cnt.chg = 0;
7938 
7939 	b->link_cnt.now += hfp->exist;
7940 	b->link_cnt.now += hid->exist;
7941 	b->link_cnt.now += a2dp->exist;
7942 	b->link_cnt.now += pan->exist;
7943 	b->link_cnt.now += leaudio->bis_exist;
7944 	b->link_cnt.now += leaudio->cis_exist;
7945 
7946 	if (leaudio->bis_exist || a2dp->sink) {
7947 		val = 70;
7948 	} else if (a2dp->exist) {
7949 		val = 40;
7950 		if (a2dp->vendor_id == 0x4c)
7951 			val += 10;
7952 		if (hid->exist)
7953 			val += 10;
7954 	} else if (pan->exist || pan->active || a2dp->active ||
7955 		   b->status.map.inq_pag) {
7956 		val = 30;
7957 	} else if (b->link_cnt.now == 0) {
7958 		val = 5;
7959 	} else {
7960 		val = 9;
7961 	}
7962 	bt->link_weight[bt_rf_band] = val;
7963 
7964 	if (b->link_cnt.last != b->link_cnt.now)
7965 		b->link_cnt.chg = 1;
7966 }
7967 
_update_bt_leaudio_info(struct rtw89_dev * rtwdev,u8 bid,void * buf,u32 len)7968 static void _update_bt_leaudio_info(struct rtw89_dev *rtwdev, u8 bid,
7969 				    void *buf, u32 len)
7970 {
7971 	const struct rtw89_chip_info *chip = rtwdev->chip;
7972 	struct rtw89_btc *btc = &rtwdev->btc;
7973 	struct rtw89_btc_cx *cx = &btc->cx;
7974 	struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1;
7975 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
7976 	struct rtw89_btc_bt_leaudio_info *src = buf;
7977 	struct rtw89_btc_bt_leaudio_desc *leaudio;
7978 	bool bt_56g = false, cis_exist, bis_exist;
7979 	u8 bis_cnt, cis_cnt;
7980 
7981 	if ((src->len & BIT(7)) && bt->band_56G_support) {
7982 		b = &bt->link_info_56g;
7983 		bt_56g = true;
7984 	}
7985 
7986 	leaudio = &b->leaudio_desc;
7987 
7988 	if (!memcmp(b->leaudio_raw_info, src, BTC_BTINFO_MAX)) {
7989 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
7990 			    "[BTC], %s return by leaudio-info duplicate!\n",
7991 			    __func__);
7992 		bt->bcnt[BTC_BCNT_LEAUDIO_INFOSAME]++;
7993 		return;
7994 	}
7995 
7996 	memcpy(b->leaudio_raw_info, src, BTC_BTINFO_MAX);
7997 
7998 	bis_exist = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_BIS_EX);
7999 	cis_exist = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_CIS_EX);
8000 	bis_cnt = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_BIS_CNT);
8001 	cis_cnt = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_CIS_CNT);
8002 
8003 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
8004 		    "[BTC], %s: bis_exist:%d bis_cnt:%d cis_exist:%d cis_cnt:%d rssi:%d\n",
8005 		    __func__, bis_exist, bis_cnt, cis_exist, cis_cnt, src->rssi);
8006 
8007 	if (!bis_exist && !cis_exist)
8008 		memset(leaudio, 0, sizeof(*leaudio));
8009 
8010 	leaudio->bis_cnt = bis_cnt;
8011 	leaudio->bis_exist = bis_exist;
8012 	leaudio->cis_cnt = cis_cnt;
8013 	leaudio->cis_exist = cis_exist;
8014 
8015 	if (leaudio->bis_exist)
8016 		b->status.map.profile_map |= BTC_BT_BIS;
8017 	else
8018 		b->status.map.profile_map &= ~BTC_BT_BIS;
8019 
8020 	if (leaudio->cis_exist)
8021 		b->status.map.profile_map |= BTC_BT_CIS;
8022 	else
8023 		b->status.map.profile_map &= ~BTC_BT_CIS;
8024 
8025 	_update_bt_link_cnt(rtwdev, bt, bt_56g);
8026 
8027 	leaudio->rssi = chip->ops->btc_get_bt_rssi(rtwdev, src->rssi);
8028 
8029 	leaudio->bis_cnt_last = leaudio->bis_cnt;
8030 	leaudio->bis_exist_last = leaudio->bis_exist;
8031 	leaudio->cis_cnt_last = leaudio->cis_cnt;
8032 	leaudio->cis_exist_last = leaudio->cis_exist;
8033 }
8034 
_update_bt_bistdma_info(struct rtw89_dev * rtwdev,u8 bid,void * buf,u32 len)8035 static void _update_bt_bistdma_info(struct rtw89_dev *rtwdev, u8 bid,
8036 				    void *buf, u32 len)
8037 {
8038 	struct rtw89_btc *btc = &rtwdev->btc;
8039 	struct rtw89_btc_cx *cx = &btc->cx;
8040 	struct rtw89_btc_dm *dm = &btc->dm;
8041 	struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1;
8042 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
8043 	struct rtw89_btc_bt_bistdma_info_le *src = buf;
8044 	struct rtw89_btc_bt_leaudio_desc *leaudio;
8045 
8046 	if ((src->len & BIT(7)) && bt->band_56G_support)
8047 		b = &bt->link_info_56g;
8048 
8049 	leaudio = &b->leaudio_desc;
8050 
8051 	if (!memcmp(b->bistdma_raw_info, src, BTC_BTINFO_MAX)) {
8052 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8053 			    "[BTC], %s return by bistdma-info duplicate!\n",
8054 			    __func__);
8055 		bt->bcnt[BTC_BCNT_LEAUDIO_INFOSAME]++;
8056 		return;
8057 	}
8058 
8059 	memcpy(b->bistdma_raw_info, src, BTC_BTINFO_MAX);
8060 
8061 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
8062 		    "[BTC], %s: bis_start_end:%d bis_trx:%d\n",
8063 		    __func__,
8064 		    u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_START_END),
8065 		    u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_TRX));
8066 
8067 	leaudio->bis_trx = u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_TRX);
8068 	leaudio->bis_start_end = u8_get_bits(src->bis,
8069 					     RTW89_BTC_BIS_INFO_L2_START_END);
8070 
8071 	leaudio->diff_t = (src->diff_t_hb * 256 + src->diff_t_lb) * 625 / 1000;
8072 
8073 	if (btc->ant_type == BTC_ANT_SHARED && leaudio->diff_t > 13)
8074 		dm->bis_tdma = true;
8075 	else
8076 		dm->bis_tdma = false;
8077 }
8078 
8079 #define BTC_BTINFO_PWR_LEN 5
_update_bt_txpwr_info(struct rtw89_dev * rtwdev,u8 * buf,u32 len)8080 static void _update_bt_txpwr_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
8081 {
8082 	struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt0;
8083 	struct rtw89_btc_bt_link_info *b = &bt->link_info;
8084 
8085 	if (len != BTC_BTINFO_PWR_LEN)
8086 		return;
8087 
8088 	if (!memcmp(bt->txpwr_info, buf, sizeof(bt->txpwr_info))) {
8089 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8090 			    "[BTC], %s return by info duplicate!\n", __func__);
8091 		return;
8092 	}
8093 
8094 	memcpy(bt->txpwr_info, buf, BTC_BTINFO_MAX);
8095 	memcpy(&b->bt_txpwr_desc, &buf[2], sizeof(b->bt_txpwr_desc));
8096 }
8097 
_set_bind_info(struct rtw89_btc * btc,u8 type)8098 static void _set_bind_info(struct rtw89_btc *btc, u8 type)
8099 {
8100 	struct rtw89_btc_cx *cx = &btc->cx;
8101 	struct rtw89_btc_dm *dm = &btc->dm;
8102 	struct rtw89_btc_wl_info *wl = &cx->wl;
8103 	struct rtw89_btc_bt_info *bt = &cx->bt0;
8104 	struct rtw89_btc_bt_link_info *b;
8105 	struct rtw89_btc_bind_info *bd;
8106 	u8 path_hwb[BTC_RF_NUM] = {RTW89_PHY_0, RTW89_PHY_1};
8107 	u8 link_weight[BTC_ALL_BT_EZL][BTC_BT_BMAX];
8108 	u8 map[BTC_RF_NUM][BTC_ALL_BT_EZL];
8109 	u8 b2g_score = 0, b5g_score = 0;
8110 	u8 i, j, rf_band_map, thres;
8111 	u8 weight[BTC_BT_BMAX] = {};
8112 
8113 	if (type == BTC_MECH_TDD) {
8114 		bd = &dm->tdd_bind;
8115 		memcpy(map, dm->tdd_map, sizeof(map));
8116 		thres = 30; /* BT profile score threshold for TDMA */
8117 	} else {
8118 		bd = &dm->fdd_bind;
8119 		memcpy(map, dm->fdd_map, sizeof(map));
8120 		thres = 5;
8121 	}
8122 
8123 	memset(bd, 0, sizeof(*bd));
8124 	/* compare BT 2GHz/5GHz profile by link-weighting */
8125 	for (i = 0; i < BTC_BT_BMAX; i++) {
8126 		if (!cx->bt0.enable.now)
8127 			cx->bt0.link_weight[i] = 0;
8128 		if (!cx->bt1.enable.now)
8129 			cx->bt1.link_weight[i] = 0;
8130 		link_weight[BTC_BT_1ST][i] = cx->bt0.link_weight[i];
8131 		link_weight[BTC_BT_2ND][i] = cx->bt1.link_weight[i];
8132 		link_weight[BTC_BT_EXT][i] = cx->bt_ext.link_weight[i];
8133 	}
8134 
8135 	/*
8136 	 * get 2GHz/5GHz link weight score by "band-overlap" map
8137 	 * link_weight from _update_bt_link_cnt(),
8138 	 * if link_weight >30 --> TDMA-required
8139 	 */
8140 	for (j = 0; j < BTC_ALL_BT_EZL; j++) {
8141 		rf_band_map = map[BTC_RF_S0][j] | map[BTC_RF_S1][j];
8142 		if (rf_band_map & BIT(RTW89_BAND_2G))
8143 			b2g_score += link_weight[j][BTC_BT_B2G];
8144 		if (rf_band_map & BIT(RTW89_BAND_5G))
8145 			b5g_score += link_weight[j][BTC_BT_B5G];
8146 	}
8147 
8148 	/* rf-band bound by comparing link weight */
8149 	if (b2g_score == 0 && b5g_score == 0) /* no-rf-band overlap */
8150 		bd->rf_band = 0;
8151 	else if (b5g_score > b2g_score)
8152 		bd->rf_band = BIT(BTC_BT_B5G);
8153 	else
8154 		bd->rf_band = BIT(BTC_BT_B2G);
8155 
8156 	/*
8157 	 * if MR_WTYPE_MLD2L1R_NONMLD, FW will change 2+0/0+2/1+1
8158 	 * Therefore, BTC_MLO_RF_xxx is not real-time state.
8159 	 * In this case, RF_S0->HWB0, RF_S1->HWB1
8160 	 * If link-mode change by _ntfy_generic(BTC_GNTFY_MRCX_INFO)
8161 	 * HW-Band is decided by wl->mlo_info.mrcx_act_hwb_map
8162 	 */
8163 	if (wl->mlo_info.wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD) {
8164 		if (wl->role_info.link_mode != BTC_WLINK_DB_MCC) { /* mode chg */
8165 			if (wl->mlo_info.mrcx_act_hwb_map == BIT(RTW89_MAC_1))
8166 				path_hwb[BTC_RF_S0] = RTW89_PHY_1; /* S0/1->HWB1 */
8167 			else
8168 				path_hwb[BTC_RF_S1] = RTW89_PHY_0; /* S0/1->HWB0 */
8169 		}
8170 	} else {
8171 		/*
8172 		 * Dual-RF_band(HWB)TDMA if BT-profile is TDMA-type at both
8173 		 * 2GHz and 5GHz.
8174 		 * ex: 1+1: HWB0 5GHz + BT0 5GHz (BIS, HDT)
8175 		 * && HWB1 2.4GHz + BT1 2.4GHz(PAN)
8176 		 * for TDD: the link score must > 30 (from _bt_link_cnt)
8177 		 * for FDD: the link score must > 5 (bt enable)
8178 		 */
8179 		if ((wl->mlo_info.rf_combination == BTC_MLO_RF_1_PLUS_1 ||
8180 		     wl->mlo_info.rf_combination == BTC_MLO_RF_2_PLUS_2) &&
8181 		     (b2g_score >= thres && b5g_score >= thres)) {
8182 			bd->rf_band = BIT(BTC_BT_B2G) | BIT(BTC_BT_B5G);
8183 		}
8184 
8185 		if (wl->mlo_info.rf_combination == BTC_MLO_RF_2_PLUS_0)
8186 			path_hwb[BTC_RF_S1] = RTW89_PHY_0; /* 2+0 RF-S0/1->HWB0 */
8187 		else if (wl->mlo_info.rf_combination == BTC_MLO_RF_0_PLUS_2)
8188 			path_hwb[BTC_RF_S0] = RTW89_PHY_1; /* 2+0 RF-S0/1->HWB1 */
8189 	}
8190 
8191 	/* Get HWB-sel and BT-sel by rf-band-binding */
8192 	for (i = 0; i < BTC_RF_NUM; i++) {
8193 		for (j = 0; j < BTC_ALL_BT_EZL; j++) {
8194 			if (!(map[i][j] & bd->rf_band)) /* no-overlap */
8195 				continue;
8196 
8197 			bd->wl_hwb_sel |= BIT(path_hwb[i]);
8198 			bd->bt_sel |= BIT(j);
8199 		}
8200 	}
8201 
8202 	if (wl->mlo_info.wtype == RTW89_MR_WTYPE_MLD2L2R &&
8203 	    (bd->wl_hwb_sel == (BIT(RTW89_MAC_1) | BIT(RTW89_MAC_0)))) {
8204 		if (wl->role_info.link_mode == BTC_WLINK_AP ||
8205 		    wl->role_info.link_mode_hb1 == BTC_WLINK_AP)
8206 			bd->wl_link_mode = BTC_WLINK_DB_MCC;
8207 		else
8208 			bd->wl_link_mode = BTC_WLINK_STA;
8209 		bd->wl_bg_mode = wl->bg_mode | wl->bg_mode_hb1;
8210 	} else if (bd->wl_hwb_sel == (BIT(RTW89_MAC_1))) {
8211 		bd->wl_link_mode = wl->role_info.link_mode_hb1;
8212 		bd->wl_bg_mode = wl->bg_mode_hb1;
8213 	} else {/* HW-BAND-0 or no-hw-band */
8214 		bd->wl_hwb_sel = BIT(RTW89_MAC_0);
8215 		bd->wl_link_mode = wl->role_info.link_mode;
8216 		bd->wl_bg_mode = wl->bg_mode;
8217 	}
8218 
8219 	/* update Bind-BT status map for BT0/BT1 */
8220 	for (i = BTC_BT_1ST; i < BTC_ALL_BT_EZL; i++) {
8221 		if (!(bd->bt_sel & BIT(i)))
8222 			continue;
8223 
8224 		for (j = BTC_BT_B2G; j <= BTC_BT_B5G; j++) {
8225 			if (!(bd->rf_band & BIT(j)))
8226 				continue;
8227 
8228 			if (i == BTC_BT_EXT) {
8229 				bd->bt_profile |= cx->bt_ext.profile_map[j];
8230 				weight[j] = cx->bt_ext.link_weight[j];
8231 				if (weight[j] > bd->bt_link_weight) /* max */
8232 					bd->bt_link_weight = weight[j];
8233 				continue;
8234 			} else if (i == BTC_BT_1ST) {
8235 				bt = &cx->bt0;
8236 			} else {
8237 				bt = &cx->bt1;
8238 			}
8239 
8240 			if (j == BTC_BT_B2G)
8241 				b = &bt->link_info;
8242 			else
8243 				b = &bt->link_info_56g;
8244 
8245 			bd->bt_profile |= b->status.map.profile_map;
8246 			bd->bt_smap.a2dp_active |= b->a2dp_desc.active;
8247 			bd->bt_smap.a2dp_sink |= b->a2dp_desc.sink;
8248 			bd->bt_smap.pan_active |= b->pan_desc.active;
8249 			bd->bt_smap.connect |= b->status.map.connect;
8250 			bd->bt_smap.hid_cnt += b->hid_desc.pair_cnt;
8251 			bd->bt_smap.hid_type |= b->hid_desc.type;
8252 			bd->bt_smap.cis_cnt += b->leaudio_desc.cis_cnt;
8253 			bd->bt_smap.link_cnt += b->link_cnt.now;
8254 			bd->bt_smap.inq_page |= b->status.map.inq_pag;
8255 			bd->bt_smap.page |= b->pag;
8256 
8257 			if (bt->link_weight[j] > bd->bt_link_weight) /* max */
8258 				bd->bt_link_weight = bt->link_weight[j];
8259 
8260 			if (b->slave_role)
8261 				bd->bt_smap.slave_role = b->slave_role;
8262 
8263 			if (b->a2dp_desc.vendor_id != 0)
8264 				bd->bt_smap.a2dp_vendor_id =
8265 							b->a2dp_desc.vendor_id;
8266 		}
8267 	}
8268 
8269 	if (bd->bt_profile & BTC_BT_HFP)
8270 		bd->bt_smap.hfp_exist = 1;
8271 	if (bd->bt_profile & BTC_BT_HID)
8272 		bd->bt_smap.hid_exist = 1;
8273 	if (bd->bt_profile & BTC_BT_A2DP)
8274 		bd->bt_smap.a2dp_exist = 1;
8275 	if (bd->bt_profile & BTC_BT_PAN)
8276 		bd->bt_smap.pan_exist = 1;
8277 	if (bd->bt_profile & BTC_BT_BIS)
8278 		bd->bt_smap.bis_exist = 1;
8279 	if (bd->bt_profile & BTC_BT_CIS)
8280 		bd->bt_smap.cis_exist = 1;
8281 	if (bd->bt_profile & BTC_BT_THREAD)
8282 		bd->bt_smap.thread_exist = 1;
8283 	if (bd->bt_profile & BTC_BT_ULL)
8284 		bd->bt_smap.ull_exist = 1;
8285 }
8286 
8287 #define _bind_is_btonly 0x7
_set_coex_binding(struct rtw89_btc * btc)8288 static void _set_coex_binding(struct rtw89_btc *btc)
8289 {
8290 	struct rtw89_btc_cx *cx = &btc->cx;
8291 	struct rtw89_btc_extsoc_info *bt2 =  &cx->bt_ext;
8292 	struct rtw89_btc_bt_info *bt0 = &cx->bt0;
8293 	struct rtw89_btc_bt_info *bt1 = &cx->bt1;
8294 	struct rtw89_btc_wl_info *wl = &cx->wl;
8295 	struct rtw89_btc_dm *dm = &btc->dm;
8296 	u8 path_hwb[BTC_RF_NUM] = {RTW89_PHY_0, RTW89_PHY_1};
8297 	u8 wl_rf_band[RTW89_BAND_NUM] = {};
8298 	u8 i, j, val = 0;
8299 
8300 	/*
8301 	 * sit_xmap(Space-Interaction) = ant_xmap | xtk_xmap
8302 	 * 1: WL-BT space-interference, always 1 if BTG/BTA/SPDT = 1
8303 	 * if dedicated-ant, it may be 1 if BT-Tx is bigger than WL-Rx(xtk_xmap)
8304 	 *
8305 	 * ant_xmap(ANT-Division-Multiplexing)
8306 	 * ==> dedicated-ant->0, BTG/BTA/SPDT->1
8307 	 *
8308 	 * xtk_xmap(Cross-talk map)-> calculate WL/BT interference by SIR
8309 	 * ==> 1: interference, 0: no-interference
8310 	 *
8311 	 * fdm_map(Frequency-Division-Multiplexing): WL/BT RF_Band overlap-map
8312 	 * 2bit-map: bit[1]:5/6GHz, bit[0]:2.4GHz
8313 	 */
8314 	for (i = 0; i < RTW89_PHY_NUM; i++) {
8315 		if (wl->rf_band_map[i] & BIT(RTW89_BAND_2G))
8316 			wl_rf_band[i] |= BIT(RTW89_BAND_2G);
8317 
8318 		if (wl->rf_band_map[i] & (BIT(RTW89_BAND_5G) | BIT(RTW89_BAND_6G)))
8319 			wl_rf_band[i] |= BIT(RTW89_BAND_5G);
8320 
8321 		dm->fit_xmap[i][BTC_BT_1ST] = wl_rf_band[i] & bt0->rf_band_map;
8322 		dm->fit_xmap[i][BTC_BT_2ND] = wl_rf_band[i] & bt1->rf_band_map;
8323 		dm->fit_xmap[i][BTC_BT_EXT] = wl_rf_band[i] & bt2->rf_band_map;
8324 	}
8325 
8326 	/*
8327 	 * if MR_WTYPE_MLD2L1R_NONMLD, FW will change 2+0/0+2/1+1
8328 	 * Therefore, BTC_MLO_RF_xxx is not real-time state.
8329 	 * if link mode change by _ntfy_generic(BTC_GNTFY_MRCX_INFO)
8330 	 * the HW-BAND is decided by wl->mlo_info.mrcx_act_hwb_map
8331 	 * In this case, BTC_RF_S0->HWB0, BTC_RF_S1->HWB1
8332 	 */
8333 	if (wl->mlo_info.wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD) {
8334 		if (wl->role_info.link_mode != BTC_WLINK_DB_MCC) {/* mode chg */
8335 			if (wl->mlo_info.mrcx_act_hwb_map == BIT(RTW89_PHY_1))
8336 				path_hwb[BTC_RF_S0] = RTW89_PHY_1;/* S0/1->HWB1 */
8337 			else
8338 				path_hwb[BTC_RF_S1] = RTW89_PHY_0;/* S0/1->HWB0 */
8339 		}
8340 	} else {
8341 		if (wl->mlo_info.rf_combination == BTC_MLO_RF_2_PLUS_0)
8342 			path_hwb[BTC_RF_S1] = RTW89_PHY_0; /* 2+0 RF-S0/1->HWB0 */
8343 		else if (wl->mlo_info.rf_combination == BTC_MLO_RF_0_PLUS_2)
8344 			path_hwb[BTC_RF_S0] = RTW89_PHY_1; /* 2+0 RF-S0/1->HWB1 */
8345 	}
8346 
8347 	/*
8348 	 * tdd_map = sit_xmap * fdm_map, 1: WL-RF-Sx vs. BTx take TDD-Action
8349 	 * fdd_map =(!sit_xmap) * fdm_map, 1: WL-RF-Sx vs.BTx take FDD-Action
8350 	 * co-rx map = ant_xmap * fdm_map 1:WL/BT co-rx (for halbb-btg-ctrl)
8351 	 * sit_xmap,ant_xmap = 0 or 1, so tdd/fdd use multiplication (*)
8352 	 */
8353 
8354 	for (i = 0; i < BTC_RF_NUM; i++)
8355 		for (j = 0; j < BTC_ALL_BT_EZL; j++) {
8356 			dm->tdd_map[i][j] = dm->sit_xmap[i][j] *
8357 					    dm->fit_xmap[path_hwb[i]][j];
8358 			dm->fdd_map[i][j] = !dm->sit_xmap[i][j] *
8359 					     dm->fit_xmap[path_hwb[i]][j];
8360 			dm->corx_map[i][j] = dm->ant_xmap[i][j] *
8361 					     dm->fit_xmap[path_hwb[i]][j];
8362 	}
8363 
8364 	/* TDD-Binding */
8365 	_set_bind_info(btc, BTC_MECH_TDD);
8366 
8367 	/* FDD-Binding */
8368 	_set_bind_info(btc, BTC_MECH_FDD);
8369 
8370 	dm->out_of_band = !dm->tdd_bind.rf_band && !dm->fdd_bind.rf_band;
8371 	dm->fdd_en = !!dm->fdd_bind.rf_band;
8372 	dm->tdd_en = !!dm->tdd_bind.rf_band;
8373 
8374 	/* set BT on/off state for GNT_WL Combined-MUX control */
8375 	if (bt0->enable.now)
8376 		val |= BIT(0);
8377 
8378 	if (bt1->enable.now)
8379 		val |= BIT(1);
8380 
8381 	if (bt2->func_type)
8382 		val |= BIT(2);
8383 
8384 	dm->ost_info.bt_enable_state = dm->bt_only ? _bind_is_btonly : val;
8385 }
8386 
_update_run_ctrl_info(struct rtw89_dev * rtwdev)8387 static void _update_run_ctrl_info(struct rtw89_dev *rtwdev)
8388 {
8389 	struct rtw89_btc *btc = &rtwdev->btc;
8390 	struct rtw89_btc_dm *dm = &btc->dm;
8391 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8392 	struct rtw89_btc_ctrl ctrl = btc->ctrl;
8393 	struct rtw89_fbtc_wl_ctrl_info *wl_ctrl_info = &ctrl.wl_ctrl_info;
8394 	u8 i;
8395 
8396 	ctrl.wl_only = dm->wl_only;
8397 	ctrl.bt_only = dm->bt_only;
8398 	ctrl.ntfy_type = dm->run_reason;
8399 
8400 	wl_ctrl_info->smap_val = wl->status.val;
8401 	wl_ctrl_info->rfk_state = wl->rfk_info.state;
8402 	wl_ctrl_info->rfk_type = wl->rfk_info.type;
8403 	wl_ctrl_info->client_pstdma_on =  dm->client_ps_tdma_on;
8404 	wl_ctrl_info->fw_scan = wl->scan_info.fw_scan;
8405 
8406 	for (i = RTW89_MAC_0; i <= RTW89_MAC_1; i++) {
8407 		wl_ctrl_info->rf_band_map[i] = wl->rf_band_map[i];
8408 		wl_ctrl_info->rf_ch[i] = wl->rf_ch_info[i].center_ch;
8409 	}
8410 
8411 	if (!memcmp(&btc->ctrl, &ctrl, sizeof(struct rtw89_btc_ctrl))) {
8412 		memcpy(&btc->ctrl, &ctrl, sizeof(struct rtw89_btc_ctrl));
8413 		if (btc->ver->fcxctrl >= 9)
8414 			_fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
8415 	}
8416 }
8417 
8418 static
_run_coex(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason)8419 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
8420 {
8421 	struct rtw89_btc *btc = &rtwdev->btc;
8422 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
8423 	struct rtw89_btc_cx *cx = &btc->cx;
8424 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8425 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
8426 	u8 mode = btc->dm.tdd_bind.wl_link_mode;
8427 	u8 mode_v0 = BTC_WLINK_V0_OTHER;
8428 	bool has_2ghz;
8429 
8430 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
8431 
8432 	dm->run_reason = reason;
8433 	_update_dm_step(rtwdev, reason);
8434 
8435 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
8436 		    __func__, reason, mode);
8437 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
8438 		    __func__, dm->wl_only, dm->bt_only);
8439 
8440 	/* Be careful to change the following function sequence!! */
8441 	if (btc->manual_ctrl) {
8442 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8443 			    "[BTC], %s(): return for Manual CTRL!!\n",
8444 			    __func__);
8445 		return;
8446 	}
8447 
8448 	if (!wl->status.map.init_ok) {
8449 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8450 			    "[BTC], %s(): return for WL init fail!!\n",
8451 			    __func__);
8452 		return;
8453 	}
8454 
8455 	if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
8456 	    wl->status.map.lps_pre == wl->status.map.lps &&
8457 	    !dm->lps_ctrl_change && !dm->lps_ctrl_scbd) {
8458 		if (reason == BTC_RSN_NTFY_POWEROFF ||
8459 		    reason == BTC_RSN_NTFY_RADIO_STATE) {
8460 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
8461 				    "[BTC], %s(): return for WL rf off state no change!!\n",
8462 				    __func__);
8463 			return;
8464 		}
8465 		if (wl->status.map.rf_off == 1 ||
8466 		    wl->status.map.lps == BTC_LPS_RF_OFF) {
8467 			rtw89_debug(rtwdev, RTW89_DBG_BTC,
8468 				    "[BTC], %s(): return for WL rf off state!!\n",
8469 				    __func__);
8470 			return;
8471 		}
8472 	}
8473 
8474 	_update_run_ctrl_info(rtwdev);
8475 
8476 	if (reason == BTC_RSN_NTFY_INIT || reason == BTC_RSN_NTFY_RADIO_STATE)
8477 		_update_bt_scbd(rtwdev, false);
8478 
8479 	dm->freerun = false;
8480 	dm->cnt_dm[BTC_DCNT_RUN]++;
8481 	dm->fddt_train = BTC_FDDT_DISABLE;
8482 	bt->scan_rx_low_pri = false;
8483 
8484 	_set_coex_binding(btc);
8485 	_update_btc_state_map(rtwdev);
8486 
8487 	dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */
8488 
8489 	if (btc->ctrl.always_freerun) {
8490 		_action_freerun(rtwdev);
8491 		goto exit;
8492 	}
8493 
8494 	if (dm->wl_only) {
8495 		_action_wl_only(rtwdev);
8496 		goto exit;
8497 	}
8498 
8499 	if (wl->status.map.rf_off || dm->bt_only || wl->status.map.lps) {
8500 		_action_wl_off(rtwdev, mode);
8501 		goto exit;
8502 	}
8503 
8504 	if (reason == BTC_RSN_NTFY_INIT) {
8505 		_action_wl_init(rtwdev);
8506 		goto exit;
8507 	}
8508 
8509 	if (!cx->bt0.enable.now && !cx->bt_ext.func_type) {
8510 		_action_bt_off(rtwdev);
8511 		goto exit;
8512 	}
8513 
8514 	if (cx->bt0.whql_test) {
8515 		_action_bt_whql(rtwdev);
8516 		goto exit;
8517 	}
8518 
8519 	if (wl->rfk_info.state != BTC_WRFK_STOP) {
8520 		_action_wl_rfk(rtwdev);
8521 		goto exit;
8522 	}
8523 
8524 	if (wl->status.val & btc_scanning_map.val && !wl->rfk_info.con_rfk) {
8525 		_action_wl_scan(rtwdev);
8526 		bt->scan_rx_low_pri = true;
8527 		goto exit;
8528 	}
8529 
8530 	if (mode == BTC_WLINK_NOLINK) {
8531 		mode_v0 = BTC_WLINK_V0_NOLINK;
8532 	} else if (btc->dm.tdd_bind.rf_band == BIT(RTW89_BAND_5G)) {
8533 		mode_v0 = BTC_WLINK_V0_5G;
8534 	} else if (btc->dm.tdd_bind.rf_band & BIT(RTW89_BAND_5G) &&
8535 		   btc->dm.tdd_bind.rf_band & BIT(RTW89_BAND_2G)) {
8536 		mode_v0 = BTC_WLINK_V0_25G_MCC;
8537 	} else if (btc->dm.tdd_bind.rf_band == BIT(RTW89_BAND_2G)) {
8538 		switch (mode) {
8539 		case BTC_WLINK_STA:
8540 			mode_v0 = BTC_WLINK_V0_2G_STA;
8541 			break;
8542 		case BTC_WLINK_AP:
8543 			mode_v0 = BTC_WLINK_V0_2G_AP;
8544 			break;
8545 		case BTC_WLINK_GO:
8546 			mode_v0 = BTC_WLINK_V0_2G_GO;
8547 			break;
8548 		case BTC_WLINK_GC:
8549 			mode_v0 = BTC_WLINK_V0_2G_GC;
8550 			break;
8551 		case BTC_WLINK_SCC:
8552 			mode_v0 = BTC_WLINK_V0_2G_SCC;
8553 			break;
8554 		case BTC_WLINK_SB_MCC:
8555 			mode_v0 = BTC_WLINK_V0_2G_MCC;
8556 			break;
8557 		default:
8558 			mode_v0 = BTC_WLINK_V0_OTHER;
8559 			break;
8560 		}
8561 	} else {
8562 		/* No binding (out_of_band): derive mode_v0 from link_mode + rf_band_map */
8563 		has_2ghz = wl->rf_band_map[RTW89_MAC_0] & BIT(RTW89_BAND_2G) ||
8564 			   wl->rf_band_map[RTW89_MAC_1] & BIT(RTW89_BAND_2G);
8565 
8566 		if (!has_2ghz) {
8567 			mode_v0 = BTC_WLINK_V0_5G;
8568 		} else if (mode == BTC_WLINK_DB_MCC) {
8569 			mode_v0 = BTC_WLINK_V0_25G_MCC;
8570 		} else {
8571 			switch (mode) {
8572 			case BTC_WLINK_STA:
8573 				mode_v0 = BTC_WLINK_V0_2G_STA;
8574 				break;
8575 			case BTC_WLINK_AP:
8576 				mode_v0 = BTC_WLINK_V0_2G_AP;
8577 				break;
8578 			case BTC_WLINK_GO:
8579 				mode_v0 = BTC_WLINK_V0_2G_GO;
8580 				break;
8581 			case BTC_WLINK_GC:
8582 				mode_v0 = BTC_WLINK_V0_2G_GC;
8583 				break;
8584 			case BTC_WLINK_SCC:
8585 				mode_v0 = BTC_WLINK_V0_2G_SCC;
8586 				break;
8587 			case BTC_WLINK_SB_MCC:
8588 				mode_v0 = BTC_WLINK_V0_2G_MCC;
8589 				break;
8590 			default:
8591 				mode_v0 = BTC_WLINK_V0_OTHER;
8592 				break;
8593 			}
8594 		}
8595 	}
8596 
8597 	switch (mode_v0) {
8598 	case BTC_WLINK_NOLINK:
8599 		_action_wl_nc(rtwdev);
8600 		break;
8601 	case BTC_WLINK_V0_2G_STA:
8602 		if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
8603 			bt->scan_rx_low_pri = true;
8604 		_action_wl_2g_sta(rtwdev);
8605 		break;
8606 	case BTC_WLINK_V0_2G_AP:
8607 		bt->scan_rx_low_pri = true;
8608 		_action_wl_2g_ap(rtwdev);
8609 		break;
8610 	case BTC_WLINK_V0_2G_GO:
8611 		bt->scan_rx_low_pri = true;
8612 		_action_wl_2g_go(rtwdev);
8613 		break;
8614 	case BTC_WLINK_V0_2G_GC:
8615 		bt->scan_rx_low_pri = true;
8616 		_action_wl_2g_gc(rtwdev);
8617 		break;
8618 	case BTC_WLINK_V0_2G_SCC:
8619 		bt->scan_rx_low_pri = true;
8620 		_action_wl_2g_scc(rtwdev);
8621 		break;
8622 	case BTC_WLINK_V0_2G_MCC:
8623 		bt->scan_rx_low_pri = true;
8624 		_action_wl_2g_mcc(rtwdev);
8625 		break;
8626 	case BTC_WLINK_V0_25G_MCC:
8627 		bt->scan_rx_low_pri = true;
8628 		_action_wl_25g_mcc(rtwdev);
8629 		break;
8630 	case BTC_WLINK_V0_5G:
8631 		_action_wl_5g(rtwdev);
8632 		break;
8633 	case BTC_WLINK_V0_2G_NAN:
8634 		_action_wl_2g_nan(rtwdev);
8635 		break;
8636 	default:
8637 		_action_wl_other(rtwdev);
8638 		break;
8639 	}
8640 
8641 exit:
8642 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__);
8643 	_action_common(rtwdev);
8644 }
8645 
rtw89_btc_init(struct rtw89_dev * rtwdev)8646 void rtw89_btc_init(struct rtw89_dev *rtwdev)
8647 {
8648 	const struct rtw89_chip_info *chip = rtwdev->chip;
8649 	struct rtw89_btc *btc = &rtwdev->btc;
8650 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8651 
8652 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
8653 		    "[BTC], %s(): Init %s !!\n", __func__,
8654 		    chip_id_str(chip->chip_id));
8655 
8656 	_reset_btc_var(rtwdev, BTC_RESET_ALL);
8657 
8658 	btc->dm.run_reason = BTC_RSN_NONE;
8659 	btc->dm.run_action = BTC_ACT_NONE;
8660 	wl->status.map.init_ok = true;
8661 }
8662 
rtw89_btc_ntfy_poweron(struct rtw89_dev * rtwdev)8663 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
8664 {
8665 	struct rtw89_btc *btc = &rtwdev->btc;
8666 
8667 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
8668 	btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++;
8669 }
8670 
rtw89_btc_ntfy_poweroff(struct rtw89_dev * rtwdev)8671 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
8672 {
8673 	struct rtw89_btc *btc = &rtwdev->btc;
8674 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8675 
8676 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
8677 	btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
8678 
8679 	btc->cx.wl.status.map.rf_off = 1;
8680 	btc->cx.wl.status.map.busy = 0;
8681 	wl->status.map.lps = BTC_LPS_OFF;
8682 
8683 	_write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ALL, false);
8684 	_run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
8685 
8686 	btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
8687 }
8688 
8689 #define BTC_PLATFORM_LITTLE_ENDIAN 0
_set_init_info(struct rtw89_dev * rtwdev)8690 static void _set_init_info(struct rtw89_dev *rtwdev)
8691 {
8692 	const struct rtw89_chip_info *chip = rtwdev->chip;
8693 	struct rtw89_btc *btc = &rtwdev->btc;
8694 	struct rtw89_btc_dm *dm = &btc->dm;
8695 	struct rtw89_btc_cx *cx = &btc->cx;
8696 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8697 
8698 	dm->init_info.init_mode = wl->coex_mode;
8699 	dm->init_info.wl_init_ok = wl->status.map.init_ok;
8700 	dm->init_info.endian_type = BTC_PLATFORM_LITTLE_ENDIAN;
8701 	dm->init_info.bt0_function = cx->bt0.func_type;
8702 	dm->init_info.bt1_function = cx->bt1.func_type;
8703 	dm->init_info.bt2_function = cx->bt_ext.func_type;
8704 	dm->init_info.pta_mode = RTW89_MAC_AX_COEX_RTK_MODE;
8705 	dm->init_info.pta_direction = RTW89_MAC_AX_COEX_INNER;
8706 	dm->init_info.wl_only = dm->wl_only;
8707 	dm->init_info.bt_only = dm->bt_only;
8708 	dm->init_info.wl_init_ok = wl->status.map.init_ok;
8709 	dm->init_info.cx_other = btc->cx.bt_ext.func_type;
8710 	dm->init_info.wl_guard_ch = chip->afh_guard_ch;
8711 	dm->init_info.dbcc_en = rtwdev->dbcc_en;
8712 
8713 	dm->init_info.module = btc->mdinfo;
8714 
8715 	_fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
8716 	_fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
8717 	rtw89_btc_fw_set_slots(rtwdev);
8718 	btc_fw_set_monreg(rtwdev);
8719 	_set_ext_interface(rtwdev);
8720 	_set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR, RTW89_PHY_0);
8721 }
8722 
rtw89_btc_ntfy_init(struct rtw89_dev * rtwdev,u8 mode)8723 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
8724 {
8725 	struct rtw89_btc *btc = &rtwdev->btc;
8726 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
8727 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8728 	const struct rtw89_chip_info *chip = rtwdev->chip;
8729 
8730 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
8731 		    "[BTC], %s(): mode=%d\n", __func__, mode);
8732 
8733 	wl->coex_mode = mode;
8734 	dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
8735 	dm->wl_only = mode == BTC_MODE_WL ? 1 : 0;
8736 	dm->bt_only = mode == BTC_MODE_BT ? 1 : 0;
8737 	wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0;
8738 	dm->vid = rtwdev->custid;
8739 	btc->ctrl.always_freerun = mode == BTC_MODE_COTX;
8740 
8741 	if (!wl->status.map.init_ok) {
8742 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8743 			    "[BTC], %s(): return for WL init fail!!\n",
8744 			    __func__);
8745 		dm->error.map.init = true;
8746 		return;
8747 	}
8748 
8749 	btc->cx.bt0.enable.now = 1;
8750 	btc->cx.bt0.run_patch_code = 1;
8751 	if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) {
8752 		btc->cx.bt1.enable.now = 1;
8753 		btc->cx.bt1.run_patch_code = 1;
8754 	}
8755 
8756 	if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO)
8757 		btc->io_oflld_type = BTC_IO_OFLD_BTC_H2C;
8758 	else
8759 		btc->io_oflld_type = BTC_IO_OFLD_NO_SUPPORT;
8760 
8761 	chip->ops->btc_set_rfe(rtwdev);
8762 	chip->ops->btc_init_cfg(rtwdev);
8763 
8764 	_write_scbd(rtwdev, BTC_ALL_BT,
8765 		    BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
8766 
8767 	if (rtw89_mac_get_ctrl_path(rtwdev)) {
8768 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8769 			    "[BTC], %s(): PTA owner warning!!\n",
8770 			    __func__);
8771 		dm->error.map.pta_owner = true;
8772 	}
8773 
8774 	_set_init_info(rtwdev);
8775 	_set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR, RTW89_PHY_0);
8776 	btc_fw_set_monreg(rtwdev);
8777 	rtw89_btc_fw_set_slots(rtwdev);
8778 	_fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
8779 	_fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
8780 
8781 	_run_coex(rtwdev, BTC_RSN_NTFY_INIT);
8782 }
8783 
rtw89_btc_ntfy_scan_start(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)8784 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
8785 {
8786 	struct rtw89_btc *btc = &rtwdev->btc;
8787 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8788 
8789 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
8790 		    "[BTC], %s(): phy_idx=%d, band=%d\n",
8791 		    __func__, phy_idx, band);
8792 
8793 	if (phy_idx >= RTW89_PHY_NUM)
8794 		return;
8795 
8796 	btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
8797 	wl->status.map.scan = true;
8798 	wl->scan_info.band[phy_idx] = band;
8799 	wl->scan_info.phy_map |= BIT(phy_idx);
8800 	_fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
8801 
8802 	if (rtwdev->dbcc_en) {
8803 		wl->dbcc_info.scan_band[phy_idx] = band;
8804 		_update_dbcc_band(rtwdev, phy_idx);
8805 		_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
8806 	}
8807 
8808 	if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw))
8809 		btc->ctrl.wl_ctrl_info.fw_scan = 1;
8810 
8811 	_run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START);
8812 }
8813 
rtw89_btc_ntfy_scan_finish(struct rtw89_dev * rtwdev,u8 phy_idx)8814 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
8815 {
8816 	struct rtw89_btc *btc = &rtwdev->btc;
8817 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8818 
8819 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
8820 		    "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
8821 	btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
8822 
8823 	wl->status.map.scan = false;
8824 	wl->scan_info.phy_map &= ~BIT(phy_idx);
8825 	_fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
8826 
8827 	if (rtwdev->dbcc_en) {
8828 		_update_dbcc_band(rtwdev, phy_idx);
8829 		_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
8830 	}
8831 
8832 	btc->dm.tdma_instant_excute = 1;
8833 
8834 	_run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
8835 }
8836 
rtw89_btc_ntfy_switch_band(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)8837 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
8838 {
8839 	struct rtw89_btc *btc = &rtwdev->btc;
8840 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8841 
8842 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
8843 		    "[BTC], %s(): phy_idx=%d, band=%d\n",
8844 		    __func__, phy_idx, band);
8845 
8846 	if (phy_idx >= RTW89_PHY_NUM)
8847 		return;
8848 
8849 	btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
8850 
8851 	if (rtwdev->dbcc_en) {
8852 		wl->dbcc_info.scan_band[phy_idx] = band;
8853 		_update_dbcc_band(rtwdev, phy_idx);
8854 		_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
8855 	}
8856 	_run_coex(rtwdev, BTC_RSN_NTFY_SWBAND);
8857 }
8858 
rtw89_btc_ntfy_specific_packet(struct rtw89_dev * rtwdev,enum btc_pkt_type pkt_type)8859 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev,
8860 				    enum btc_pkt_type pkt_type)
8861 {
8862 	struct rtw89_btc *btc = &rtwdev->btc;
8863 	struct rtw89_btc_cx *cx = &btc->cx;
8864 	struct rtw89_btc_wl_info *wl = &cx->wl;
8865 	struct rtw89_btc_bt_link_info *b = &cx->bt0.link_info;
8866 	struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
8867 	struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
8868 	u32 cnt;
8869 	u32 delay = RTW89_COEX_ACT1_WORK_PERIOD;
8870 	bool delay_work = false;
8871 
8872 	switch (pkt_type) {
8873 	case PACKET_DHCP:
8874 		cnt = ++wl->wcnt[BTC_WCNT_DHCP];
8875 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8876 			    "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt);
8877 		wl->status.map.handshake = 0;
8878 		wl->status.map._4way = 0;
8879 		wl->status.map.dhcp = 1;
8880 		delay_work = true;
8881 		break;
8882 	case PACKET_EAPOL:
8883 		cnt = ++wl->wcnt[BTC_WCNT_EAPOL];
8884 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8885 			    "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt);
8886 		wl->status.map.handshake = 0;
8887 		wl->status.map._4way = 1;
8888 		wl->status.map.dhcp = 0;
8889 		delay_work = true;
8890 		if (hfp->exist || hid->exist)
8891 			delay /= 2;
8892 		break;
8893 	case PACKET_EAPOL_END:
8894 		cnt = ++wl->wcnt[BTC_WCNT_EAPOL];
8895 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8896 			    "[BTC], %s(): EAPOL_End cnt=%d\n",
8897 			    __func__, cnt);
8898 		wl->status.map._4way = 0;
8899 		wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work);
8900 		break;
8901 	case PACKET_ARP:
8902 		cnt = ++wl->wcnt[BTC_WCNT_ARP];
8903 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8904 			    "[BTC], %s(): ARP cnt=%d\n", __func__, cnt);
8905 		return;
8906 	case PACKET_ICMP:
8907 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8908 			    "[BTC], %s(): ICMP pkt\n", __func__);
8909 		return;
8910 	default:
8911 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
8912 			    "[BTC], %s(): unknown packet type %d\n",
8913 			    __func__, pkt_type);
8914 		return;
8915 	}
8916 
8917 	if (delay_work) {
8918 		wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work);
8919 		wiphy_delayed_work_queue(rtwdev->hw->wiphy,
8920 					 &rtwdev->coex_act1_work, delay);
8921 	}
8922 
8923 	btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
8924 	_run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET);
8925 }
8926 
rtw89_btc_ntfy_eapol_packet_work(struct wiphy * wiphy,struct wiphy_work * work)8927 void rtw89_btc_ntfy_eapol_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
8928 {
8929 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
8930 						btc.eapol_notify_work);
8931 
8932 	lockdep_assert_wiphy(wiphy);
8933 
8934 	rtw89_leave_ps_mode(rtwdev);
8935 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL);
8936 }
8937 
rtw89_btc_ntfy_arp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)8938 void rtw89_btc_ntfy_arp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
8939 {
8940 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
8941 						btc.arp_notify_work);
8942 
8943 	lockdep_assert_wiphy(wiphy);
8944 
8945 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP);
8946 }
8947 
rtw89_btc_ntfy_dhcp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)8948 void rtw89_btc_ntfy_dhcp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
8949 {
8950 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
8951 						btc.dhcp_notify_work);
8952 
8953 	lockdep_assert_wiphy(wiphy);
8954 
8955 	rtw89_leave_ps_mode(rtwdev);
8956 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP);
8957 }
8958 
rtw89_btc_ntfy_icmp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)8959 void rtw89_btc_ntfy_icmp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
8960 {
8961 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
8962 						btc.icmp_notify_work);
8963 
8964 	lockdep_assert_wiphy(wiphy);
8965 
8966 	rtw89_leave_ps_mode(rtwdev);
8967 	rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP);
8968 }
8969 
_update_bt_rssi_level(struct rtw89_dev * rtwdev,u8 rssi)8970 static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi)
8971 {
8972 	const struct rtw89_chip_info *chip = rtwdev->chip;
8973 	struct rtw89_btc *btc = &rtwdev->btc;
8974 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
8975 	u8 *rssi_st, rssi_th, rssi_level = 0;
8976 	u8 i;
8977 
8978 	/* for rssi locate in which {40, 36, 31, 28}
8979 	 * if rssi >= 40% (-60dBm) --> rssi_level = 4
8980 	 * if 36% <= rssi < 40%    --> rssi_level = 3
8981 	 * if 31% <= rssi < 36%    --> rssi_level = 2
8982 	 * if 28% <= rssi < 31%    --> rssi_level = 1
8983 	 * if rssi < 28%           --> rssi_level = 0
8984 	 */
8985 
8986 	/* check if rssi across bt_rssi_thres boundary */
8987 	for (i = 0; i < BTC_BT_RSSI_THMAX; i++) {
8988 		rssi_th = chip->bt_rssi_thres[i];
8989 		rssi_st = &bt->link_info.rssi_state[i];
8990 
8991 		*rssi_st = _update_rssi_state(rtwdev, *rssi_st, rssi, rssi_th);
8992 
8993 		if (BTC_RSSI_HIGH(*rssi_st)) {
8994 			rssi_level = BTC_BT_RSSI_THMAX - i;
8995 			break;
8996 		}
8997 	}
8998 	return rssi_level;
8999 }
9000 
9001 #define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4)
9002 
_update_bt_info(struct rtw89_dev * rtwdev,u8 bid,u8 * buf,u32 len)9003 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 bid, u8 *buf, u32 len)
9004 {
9005 	const struct rtw89_chip_info *chip = rtwdev->chip;
9006 	struct rtw89_btc *btc = &rtwdev->btc;
9007 	struct rtw89_btc_bt_a2dp_desc *a2dp;
9008 	struct rtw89_btc_cx *cx = &btc->cx;
9009 	struct rtw89_btc_bt_hfp_desc *hfp;
9010 	struct rtw89_btc_bt_hid_desc *hid;
9011 	struct rtw89_btc_bt_pan_desc *pan;
9012 	struct rtw89_btc_bt_link_info *b;
9013 	struct rtw89_btc_bt_info *bt;
9014 	union btc_btinfo btinfo;
9015 	u8 is_bt_56g = 0;
9016 	u8 *raw_info;
9017 
9018 	/* Bit7 is used for RF-band: 0:BT_2.4 GHz, 1:BT_5/6 GHz */
9019 	if ((buf[BTC_BTINFO_L1] & 0x7f) != 6)
9020 		return;
9021 
9022 	bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1;
9023 
9024 	if ((buf[BTC_BTINFO_L1] & BIT(7)) && bt->band_56G_support) {
9025 		b = &bt->link_info_56g;
9026 		is_bt_56g = 1;
9027 		if (b->status.map.connect)
9028 			bt->rf_band_map |= BIT(RTW89_BAND_5G);
9029 		else
9030 			bt->rf_band_map &= ~BIT(RTW89_BAND_5G);
9031 	} else {
9032 		b = &bt->link_info;
9033 		bt->rf_band_map |= BIT(RTW89_BAND_2G);
9034 	}
9035 
9036 	hfp = &b->hfp_desc;
9037 	hid = &b->hid_desc;
9038 	a2dp = &b->a2dp_desc;
9039 	pan = &b->pan_desc;
9040 	raw_info = is_bt_56g ? bt->raw_info_56g : bt->raw_info;
9041 
9042 	if (!memcmp(raw_info, buf, BTC_BTINFO_MAX)) {
9043 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
9044 			    "[BTC], %s(): return by bt-info duplicate!!\n",
9045 			    __func__);
9046 		bt->bcnt[BTC_BCNT_INFOSAME]++;
9047 		return;
9048 	}
9049 
9050 	memcpy(raw_info, buf, BTC_BTINFO_MAX);
9051 
9052 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
9053 		    "[BTC], %s(): bt_info[2]=0x%02x\n",
9054 		    __func__, raw_info[2]);
9055 
9056 	hid->type = 0;
9057 
9058 	/* parse raw info low-Byte2 */
9059 	btinfo.val = raw_info[BTC_BTINFO_L2];
9060 	b->status.map.connect = btinfo.lb2.connect;
9061 	b->status.map.sco_busy = btinfo.lb2.sco_busy;
9062 	b->status.map.acl_busy = btinfo.lb2.acl_busy;
9063 	b->status.map.inq_pag = btinfo.lb2.inq_pag;
9064 	bt->inq_pag.now = btinfo.lb2.inq_pag;
9065 	bt->bcnt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
9066 
9067 	hfp->exist = btinfo.lb2.hfp;
9068 	hid->exist = btinfo.lb2.hid;
9069 	a2dp->exist = btinfo.lb2.a2dp;
9070 	pan->exist = btinfo.lb2.pan;
9071 	_update_bt_link_cnt(rtwdev, bt, is_bt_56g);
9072 	btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK);
9073 
9074 	/* parse raw info low-Byte3 */
9075 	btinfo.val = raw_info[BTC_BTINFO_L3];
9076 	if (btinfo.lb3.retry != 0)
9077 		bt->bcnt[BTC_BCNT_RETRY]++;
9078 	b->cqddr = btinfo.lb3.cqddr;
9079 	bt->bcnt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
9080 	bt->inq = btinfo.lb3.inq;
9081 	bt->bcnt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
9082 	bt->pag = btinfo.lb3.pag;
9083 
9084 	b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
9085 	/* parse raw info high-Byte0 */
9086 	btinfo.val = raw_info[BTC_BTINFO_H0];
9087 	/* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/
9088 	b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi);
9089 	bt->rssi_level = _update_bt_rssi_level(rtwdev, b->rssi);
9090 	btc->dm.trx_info.bt_rssi = bt->rssi_level;
9091 
9092 	/* parse raw info high-Byte1 */
9093 	btinfo.val = raw_info[BTC_BTINFO_H1];
9094 	b->status.map.ble_connect = btinfo.hb1.ble_connect;
9095 	if (btinfo.hb1.ble_connect) {
9096 		if (hid->exist)
9097 			hid->type |= BTC_HID_BLE;
9098 		else if (btinfo.hb1.voice)
9099 			hid->type |= BTC_HID_RCU_VOICE;
9100 		else
9101 			hid->type |= BTC_HID_RCU;
9102 	}
9103 
9104 	bt->bcnt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
9105 	bt->reinit = btinfo.hb1.reinit;
9106 	bt->bcnt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
9107 	b->relink.now = btinfo.hb1.relink;
9108 	bt->bcnt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
9109 	bt->igno_wl = btinfo.hb1.igno_wl;
9110 
9111 	if (bt->igno_wl && !cx->wl.status.map.rf_off)
9112 		_set_bt_ignore_wlan_act(rtwdev, false);
9113 
9114 	bt->ble_scan_en = btinfo.hb1.ble_scan;
9115 
9116 	bt->bcnt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
9117 	b->role_sw = btinfo.hb1.role_sw;
9118 
9119 	b->multi_link.now = btinfo.hb1.multi_link;
9120 
9121 	/* parse raw info high-Byte2 */
9122 	btinfo.val = raw_info[BTC_BTINFO_H2];
9123 	pan->active = !!btinfo.hb2.pan_active;
9124 
9125 	bt->bcnt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
9126 	b->afh_update = btinfo.hb2.afh_update;
9127 	a2dp->active = btinfo.hb2.a2dp_active;
9128 	b->slave_role = btinfo.hb2.slave;
9129 	hid->slot_info = btinfo.hb2.hid_slot;
9130 	hid->pair_cnt = btinfo.hb2.hid_cnt;
9131 	if (!b->status.map.ble_connect || hid->pair_cnt > 1)
9132 		hid->type |= (hid->slot_info == BTC_HID_218 ?
9133 			      BTC_HID_218 : BTC_HID_418);
9134 	/* parse raw info high-Byte3 */
9135 	btinfo.val = raw_info[BTC_BTINFO_H3];
9136 	a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
9137 
9138 	if (b->tx_3m != (u32)btinfo.hb3.tx_3m)
9139 		bt->bcnt[BTC_BCNT_RATECHG]++;
9140 	b->tx_3m = (u32)btinfo.hb3.tx_3m;
9141 
9142 	a2dp->sink = btinfo.hb3.a2dp_sink;
9143 
9144 	if (!a2dp->exist_last && a2dp->exist) {
9145 		a2dp->vendor_id = 0;
9146 		a2dp->flush_time = 0;
9147 		a2dp->play_latency = 1;
9148 		wiphy_delayed_work_queue(rtwdev->hw->wiphy,
9149 					 &rtwdev->coex_bt_devinfo_work,
9150 					 RTW89_COEX_BT_DEVINFO_WORK_PERIOD);
9151 	}
9152 
9153 	_update_bt_ctrl_lps(rtwdev);
9154 	_run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
9155 }
9156 
_ntfy_role_info(struct rtw89_dev * rtwdev,u8 rid,struct rtw89_btc_wl_link_info * info,enum btc_role_state reason)9157 static void _ntfy_role_info(struct rtw89_dev *rtwdev, u8 rid,
9158 			    struct rtw89_btc_wl_link_info *info,
9159 			    enum btc_role_state reason)
9160 {
9161 	struct rtw89_btc *btc = &rtwdev->btc;
9162 	struct rtw89_btc_wl_link_info *wlinfo = NULL;
9163 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9164 	const struct rtw89_btc_ver *ver = btc->ver;
9165 	u8 rlink_id = info->phy; /* 1 role_id has 2 rlink_id(by HW_Band0/1) */
9166 	bool refresh_role = false;
9167 
9168 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
9169 		    "[BTC], %s(), role_id=%d, reason=%d\n",
9170 		    __func__, rid, reason);
9171 
9172 	if (rid >= ver->max_role_num || rlink_id >= RTW89_PHY_NUM)
9173 		return;
9174 
9175 	btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
9176 
9177 	wlinfo = &wl->rlink_info[rid][rlink_id];
9178 	memcpy(wlinfo, info, sizeof(struct rtw89_btc_wl_link_info));
9179 
9180 	switch (reason) {
9181 	case BTC_ROLE_START:
9182 		wlinfo->active = true;
9183 		return;
9184 	case BTC_ROLE_STOP:
9185 		wlinfo->active = false;
9186 		return;
9187 	case BTC_ROLE_MSTS_STA_CONN_START:
9188 		wl->status.map.transacting = 1;
9189 		wiphy_delayed_work_cancel(rtwdev->hw->wiphy,
9190 					  &rtwdev->coex_act1_work);
9191 		wiphy_delayed_work_queue(rtwdev->hw->wiphy,
9192 					 &rtwdev->coex_act1_work,
9193 					 RTW89_COEX_ACT1_WORK_PERIOD);
9194 		break;
9195 	case BTC_ROLE_MSTS_STA_CONN_END:
9196 		wl->status.map.transacting = 0;
9197 		refresh_role = true;
9198 		break;
9199 	case BTC_ROLE_MSTS_STA_DIS_CONN:
9200 		wl->status.map.transacting = 1;
9201 		refresh_role = false;
9202 		wiphy_delayed_work_cancel(rtwdev->hw->wiphy,
9203 					  &rtwdev->coex_act1_work);
9204 		wiphy_delayed_work_queue(rtwdev->hw->wiphy,
9205 					 &rtwdev->coex_act1_work,
9206 					 RTW89_COEX_ACT1_WORK_PERIOD);
9207 		break;
9208 	case BTC_ROLE_MSTS_AP_START:
9209 	case BTC_ROLE_MSTS_AP_STOP:
9210 		refresh_role = true;
9211 		break;
9212 	case BTC_ROLE_STATE_UNKNOWN:
9213 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
9214 			    "[BTC], %s(), role_id=%d, Unknown reason return!\n",
9215 			    __func__, rid);
9216 		return;
9217 	default:
9218 		return;
9219 	}
9220 
9221 	if (refresh_role) {
9222 		_update_wl_info(rtwdev, wlinfo);
9223 		_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
9224 	}
9225 
9226 	_run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
9227 }
9228 
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)9229 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev,
9230 			      struct rtw89_vif_link *rtwvif_link,
9231 			      struct rtw89_sta_link *rtwsta_link,
9232 			      enum btc_role_state state)
9233 {
9234 	const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
9235 						       rtwvif_link->chanctx_idx);
9236 	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
9237 	struct ieee80211_p2p_noa_attr *noa_attr;
9238 	struct ieee80211_p2p_noa_desc *noa_desc;
9239 	struct ieee80211_bss_conf *bss_conf;
9240 	struct ieee80211_link_sta *link_sta;
9241 	struct rtw89_btc_wl_link_info r = {0};
9242 	u8 i, role_id, mode = 0;
9243 
9244 	rcu_read_lock();
9245 
9246 	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
9247 
9248 	role_id = rtwvif_link->port;
9249 
9250 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
9251 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
9252 		    "[BTC], role is STA=%d\n",
9253 		    vif->type == NL80211_IFTYPE_STATION);
9254 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", role_id);
9255 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
9256 		    chan->band_type, chan->channel, chan->band_width);
9257 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
9258 		    state == BTC_ROLE_MSTS_STA_CONN_END);
9259 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
9260 		    "[BTC], bcn_period=%d dtim_period=%d\n",
9261 		    bss_conf->beacon_int, bss_conf->dtim_period);
9262 
9263 	if (rtwsta_link) {
9264 		link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
9265 
9266 		rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
9267 			    rtwsta_link->mac_id);
9268 
9269 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
9270 			    "[BTC], STA support HE=%d VHT=%d HT=%d\n",
9271 			    link_sta->he_cap.has_he,
9272 			    link_sta->vht_cap.vht_supported,
9273 			    link_sta->ht_cap.ht_supported);
9274 		if (link_sta->he_cap.has_he)
9275 			mode |= BIT(BTC_WL_MODE_HE);
9276 		if (link_sta->vht_cap.vht_supported)
9277 			mode |= BIT(BTC_WL_MODE_VHT);
9278 		if (link_sta->ht_cap.ht_supported)
9279 			mode |= BIT(BTC_WL_MODE_HT);
9280 
9281 		r.mode = mode;
9282 	}
9283 
9284 	if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) {
9285 		rcu_read_unlock();
9286 		return;
9287 	}
9288 
9289 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
9290 		    "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role);
9291 
9292 	if (vif->type == NL80211_IFTYPE_P2P_GO ||
9293 	    vif->type == NL80211_IFTYPE_P2P_CLIENT) {
9294 		noa_attr = &bss_conf->p2p_noa_attr;
9295 
9296 		for (i = 0; i < RTW89_P2P_MAX_NOA_NUM; i++) {
9297 			noa_desc = &noa_attr->desc[i];
9298 			if (noa_desc->count != 0) {
9299 				r.noa = 1;
9300 				r.noa_duration = le32_to_cpu(noa_desc->duration);
9301 				break;
9302 			}
9303 		}
9304 	}
9305 
9306 	r.mode = mode;
9307 	r.role = rtwvif_link->wifi_role;
9308 	r.phy = rtwvif_link->phy_idx;
9309 	r.pid = role_id;
9310 	r.active = true;
9311 	if (vif->active_links) {
9312 		if (rtwvif_link->link_id < 16)
9313 			r.active = !!(vif->active_links & BIT(rtwvif_link->link_id));
9314 	}
9315 	r.bcn_period = bss_conf->beacon_int;
9316 	r.dtim_period = bss_conf->dtim_period;
9317 	r.band = chan->band_type;
9318 	r.ch = chan->channel;
9319 	r.bw = chan->band_width;
9320 	r.chdef.band = chan->band_type;
9321 	r.chdef.center_ch = chan->channel;
9322 	r.chdef.bw = chan->band_width;
9323 	r.chdef.chan = chan->primary_channel;
9324 
9325 	if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION) {
9326 		r.mac_id = rtwsta_link->mac_id;
9327 		ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr);
9328 	}
9329 
9330 	switch (state) {
9331 	case BTC_ROLE_MSTS_STA_CONN_END:
9332 	case BTC_ROLE_MSTS_AP_START:
9333 		r.connected = MLME_LINKED;
9334 		break;
9335 	default:
9336 		r.connected = MLME_NO_LINK;
9337 		break;
9338 	}
9339 
9340 	rcu_read_unlock();
9341 
9342 	_ntfy_role_info(rtwdev, role_id, &r, state);
9343 }
9344 
rtw89_btc_ntfy_radio_state(struct rtw89_dev * rtwdev,enum btc_rfctrl rf_state)9345 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state)
9346 {
9347 	const struct rtw89_chip_info *chip = rtwdev->chip;
9348 	struct rtw89_btc *btc = &rtwdev->btc;
9349 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9350 	u32 val;
9351 
9352 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
9353 		    __func__, rf_state);
9354 	btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
9355 
9356 	switch (rf_state) {
9357 	case BTC_RFCTRL_WL_OFF:
9358 		wl->status.map.rf_off = 1;
9359 		wl->status.map.lps = BTC_LPS_OFF;
9360 		wl->status.map.busy = 0;
9361 		break;
9362 	case BTC_RFCTRL_FW_CTRL:
9363 		wl->status.map.rf_off = 0;
9364 		wl->status.map.lps = BTC_LPS_RF_OFF;
9365 		wl->status.map.busy = 0;
9366 		break;
9367 	case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */
9368 		wl->status.map.rf_off = 0;
9369 		wl->status.map.lps = BTC_LPS_RF_ON;
9370 		wl->status.map.busy = 0;
9371 		break;
9372 	case BTC_RFCTRL_WL_ON:
9373 	default:
9374 		wl->status.map.rf_off = 0;
9375 		wl->status.map.lps = BTC_LPS_OFF;
9376 		break;
9377 	}
9378 
9379 	if (rf_state == BTC_RFCTRL_WL_ON) {
9380 		val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG;
9381 		_write_scbd(rtwdev, BTC_ALL_BT, val, true);
9382 		chip->ops->btc_init_cfg(rtwdev);
9383 	} else {
9384 		if (rf_state == BTC_RFCTRL_FW_CTRL)
9385 			_write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ACTIVE, false);
9386 		else if (rf_state == BTC_RFCTRL_WL_OFF)
9387 			_write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ALL, false);
9388 		else
9389 			_write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ACTIVE, false);
9390 	}
9391 
9392 	btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
9393 	btc->dm.tdma_instant_excute = 1;
9394 
9395 	_run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
9396 	wl->status.map.rf_off_pre = wl->status.map.rf_off;
9397 	wl->status.map.lps_pre = wl->status.map.lps;
9398 }
9399 
_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_path,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)9400 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path,
9401 			 enum btc_wl_rfk_type type,
9402 			 enum btc_wl_rfk_state state)
9403 {
9404 	struct rtw89_btc *btc = &rtwdev->btc;
9405 	struct rtw89_btc_cx *cx = &btc->cx;
9406 	struct rtw89_btc_wl_info *wl = &cx->wl;
9407 	bool result = BTC_WRFK_REJECT;
9408 
9409 	wl->rfk_info.type = type;
9410 	wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path);
9411 	wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path);
9412 	wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path);
9413 
9414 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
9415 		    "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
9416 		    __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
9417 		    type, state);
9418 
9419 	switch (state) {
9420 	case BTC_WRFK_START:
9421 		result = BTC_WRFK_ALLOW;
9422 		wl->rfk_info.state = BTC_WRFK_START;
9423 
9424 		btc->cx.wl.wcnt[BTC_WCNT_RFK_REQ]++;
9425 		btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
9426 
9427 		_write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLRFK, true);
9428 		break;
9429 	case BTC_WRFK_ONESHOT_START:
9430 	case BTC_WRFK_ONESHOT_STOP:
9431 		btc->cx.wl.wcnt[BTC_WCNT_RFK_GO]++;
9432 		if (type != BTC_WRFKT_RXDCK)
9433 			return BTC_WRFK_ALLOW;
9434 		break;
9435 	case BTC_WRFK_STOP:
9436 		result = BTC_WRFK_ALLOW;
9437 		wl->rfk_info.state = BTC_WRFK_STOP;
9438 
9439 		_write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLRFK, false);
9440 		wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_rfk_chk_work);
9441 		break;
9442 	default:
9443 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
9444 			    "[BTC], %s() warning state=%d\n", __func__, state);
9445 		return result;
9446 	}
9447 
9448 	if (result == BTC_WRFK_ALLOW) {
9449 		if (wl->rfk_info.state == BTC_WRFK_START ||
9450 		    wl->rfk_info.state == BTC_WRFK_STOP)
9451 			_run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK);
9452 
9453 		if (wl->rfk_info.state == BTC_WRFK_START)
9454 			wiphy_delayed_work_queue(rtwdev->hw->wiphy,
9455 						 &rtwdev->coex_rfk_chk_work,
9456 						 RTW89_COEX_RFK_CHK_WORK_PERIOD);
9457 	}
9458 
9459 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
9460 		    "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
9461 		    __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
9462 
9463 	return result;
9464 }
9465 
rtw89_btc_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_map,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)9466 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
9467 			   enum btc_wl_rfk_type type,
9468 			   enum btc_wl_rfk_state state)
9469 {
9470 	u8 band;
9471 	bool allow;
9472 	int ret;
9473 
9474 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
9475 
9476 	band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map);
9477 
9478 	rtw89_debug(rtwdev, RTW89_DBG_RFK,
9479 		    "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n",
9480 		    band == RTW89_BAND_2G ? "2G" :
9481 		    band == RTW89_BAND_5G ? "5G" : "6G",
9482 		    !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)),
9483 		    type,
9484 		    FIELD_GET(BTC_RFK_PATH_MAP, phy_map),
9485 		    state == BTC_WRFK_STOP ? "RFK_STOP" :
9486 		    state == BTC_WRFK_START ? "RFK_START" :
9487 		    state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" :
9488 		    "ONE-SHOT_STOP");
9489 
9490 	if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) {
9491 		_ntfy_wl_rfk(rtwdev, phy_map, type, state);
9492 		return;
9493 	}
9494 
9495 	ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false,
9496 				rtwdev, phy_map, type, state);
9497 	if (ret) {
9498 		rtw89_warn(rtwdev, "RFK notify timeout\n");
9499 		rtwdev->is_bt_iqk_timeout = true;
9500 	}
9501 }
9502 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk);
9503 
9504 struct rtw89_btc_wl_sta_iter_data {
9505 	struct rtw89_dev *rtwdev;
9506 	u8 busy_all;
9507 	u8 dir_all;
9508 	u8 rssi_map_all;
9509 	bool is_sta_change;
9510 	bool is_traffic_change;
9511 };
9512 
9513 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)9514 void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link,
9515 				  struct rtw89_sta_link *rtwsta_link,
9516 				  struct rtw89_btc_wl_sta_iter_data *iter_data)
9517 {
9518 	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
9519 	struct rtw89_dev *rtwdev = iter_data->rtwdev;
9520 	struct rtw89_btc *btc = &rtwdev->btc;
9521 	struct rtw89_btc_dm *dm = &btc->dm;
9522 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9523 	struct rtw89_btc_wl_link_info *link_info = NULL;
9524 	struct rtw89_traffic_stats *link_info_t = NULL;
9525 	struct rtw89_traffic_stats *stats = &rtwvif->stats;
9526 	const struct rtw89_chip_info *chip = rtwdev->chip;
9527 	struct rtw89_btc_wl_role_info *r;
9528 	u32 last_tx_rate, last_rx_rate;
9529 	u8 link = rtwvif_link->phy_idx;
9530 	u16 last_tx_lvl, last_rx_lvl;
9531 	u8 port = rtwvif_link->port;
9532 	u8 rssi;
9533 	u8 busy = 0;
9534 	u8 dir = 0;
9535 	u8 rssi_map = 0;
9536 	u8 i = 0;
9537 	bool is_sta_change = false, is_traffic_change = false;
9538 
9539 	rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR;
9540 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
9541 
9542 	link_info = &wl->rlink_info[port][link];
9543 
9544 	link_info->stat.traffic = *stats;
9545 	link_info_t = &link_info->stat.traffic;
9546 
9547 	if (link_info->connected == MLME_NO_LINK) {
9548 		link_info->rx_rate_drop_cnt = 0;
9549 		return;
9550 	}
9551 
9552 	link_info->stat.rssi = rssi;
9553 	for (i = 0; i < BTC_WL_RSSI_THMAX; i++) {
9554 		link_info->rssi_state[i] =
9555 			_update_rssi_state(rtwdev,
9556 					   link_info->rssi_state[i],
9557 					   link_info->stat.rssi,
9558 					   chip->wl_rssi_thres[i]);
9559 		if (BTC_RSSI_LOW(link_info->rssi_state[i]))
9560 			rssi_map |= BIT(i);
9561 
9562 		if (btc->ant_type == BTC_ANT_DEDICATED &&
9563 		    BTC_RSSI_CHANGE(link_info->rssi_state[i]))
9564 			is_sta_change = true;
9565 	}
9566 	iter_data->rssi_map_all |= rssi_map;
9567 
9568 	last_tx_rate = link_info_t->tx_rate;
9569 	last_rx_rate = link_info_t->rx_rate;
9570 	last_tx_lvl = (u16)link_info_t->tx_tfc_lv;
9571 	last_rx_lvl = (u16)link_info_t->rx_tfc_lv;
9572 
9573 	if (stats->tx_tfc_lv != RTW89_TFC_IDLE ||
9574 	    stats->rx_tfc_lv != RTW89_TFC_IDLE)
9575 		busy = 1;
9576 
9577 	if (stats->tx_tfc_lv > stats->rx_tfc_lv)
9578 		dir = RTW89_TFC_UL;
9579 	else
9580 		dir = RTW89_TFC_DL;
9581 
9582 	if (link_info->busy != busy || link_info->dir != dir) {
9583 		is_sta_change = true;
9584 		link_info->busy = busy;
9585 		link_info->dir = dir;
9586 	}
9587 
9588 	iter_data->busy_all |= busy;
9589 	iter_data->dir_all |= BIT(dir);
9590 
9591 	if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
9592 	    last_rx_rate > RTW89_HW_RATE_CCK2 &&
9593 	    link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
9594 		link_info->rx_rate_drop_cnt++;
9595 
9596 	if (last_tx_rate != rtwsta_link->ra_report.hw_rate ||
9597 	    last_rx_rate != rtwsta_link->rx_hw_rate ||
9598 	    last_tx_lvl != link_info_t->tx_tfc_lv ||
9599 	    last_rx_lvl != link_info_t->rx_tfc_lv)
9600 		is_traffic_change = true;
9601 
9602 	link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate;
9603 	link_info_t->rx_rate = rtwsta_link->rx_hw_rate;
9604 
9605 	if (link_info->role == RTW89_WIFI_ROLE_STATION ||
9606 	    link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) {
9607 		dm->trx_info.tx_rate = link_info_t->tx_rate;
9608 		dm->trx_info.rx_rate = link_info_t->rx_rate;
9609 	}
9610 
9611 	r = &wl->role_info;
9612 	r->rlink[port][link].tx_lvl = stats->tx_tfc_lv;
9613 	r->rlink[port][link].rx_lvl = stats->rx_tfc_lv;
9614 	r->rlink[port][link].tx_rate = rtwsta_link->ra_report.hw_rate;
9615 	r->rlink[port][link].rx_rate = rtwsta_link->rx_hw_rate;
9616 
9617 	dm->trx_info.tx_lvl = stats->tx_tfc_lv;
9618 	dm->trx_info.rx_lvl = stats->rx_tfc_lv;
9619 	dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate;
9620 	dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate;
9621 	dm->trx_info.tx_tp = link_info_t->tx_throughput;
9622 	dm->trx_info.rx_tp = link_info_t->rx_throughput;
9623 
9624 	/* Trigger coex-run if 0x10980 reg-value is diff with coex setup */
9625 	if ((dm->wl_btg_rx_rb != dm->wl_btg_rx &&
9626 	     dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) ||
9627 	     (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
9628 	      dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND))
9629 		iter_data->is_sta_change = true;
9630 
9631 	if (is_sta_change)
9632 		iter_data->is_sta_change = true;
9633 
9634 	if (is_traffic_change)
9635 		iter_data->is_traffic_change = true;
9636 }
9637 
rtw89_btc_ntfy_wl_sta_iter(void * data,struct ieee80211_sta * sta)9638 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
9639 {
9640 	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
9641 	struct rtw89_btc_wl_sta_iter_data *iter_data =
9642 				(struct rtw89_btc_wl_sta_iter_data *)data;
9643 	struct rtw89_vif_link *rtwvif_link;
9644 	struct rtw89_sta_link *rtwsta_link;
9645 	unsigned int link_id;
9646 
9647 	rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
9648 		rtwvif_link = rtwsta_link->rtwvif_link;
9649 		__rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data);
9650 	}
9651 }
9652 
9653 #define BTC_NHM_CHK_INTVL 20
9654 
rtw89_btc_ntfy_wl_sta(struct rtw89_dev * rtwdev)9655 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
9656 {
9657 	struct rtw89_btc *btc = &rtwdev->btc;
9658 	struct rtw89_btc_dm *dm = &btc->dm;
9659 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9660 	struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev};
9661 	u8 i;
9662 
9663 	ieee80211_iterate_stations_atomic(rtwdev->hw,
9664 					  rtw89_btc_ntfy_wl_sta_iter,
9665 					  &data);
9666 
9667 	wl->rssi_level = 0;
9668 	btc->dm.cnt_notify[BTC_NCNT_WL_STA]++;
9669 	for (i = BTC_WL_RSSI_THMAX; i > 0; i--) {
9670 		/* set RSSI level 4 ~ 0 if rssi bit map match */
9671 		if (data.rssi_map_all & BIT(i - 1)) {
9672 			wl->rssi_level = i;
9673 			break;
9674 		}
9675 	}
9676 
9677 	if (dm->trx_info.wl_rssi != wl->rssi_level)
9678 		dm->trx_info.wl_rssi = wl->rssi_level;
9679 
9680 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n",
9681 		    __func__, !!wl->status.map.busy);
9682 
9683 	_write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLBUSY, (!!wl->status.map.busy));
9684 
9685 	if (data.is_traffic_change)
9686 		_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
9687 	if (data.is_sta_change) {
9688 		wl->status.map.busy = data.busy_all;
9689 		wl->status.map.traffic_dir = data.dir_all;
9690 		_run_coex(rtwdev, BTC_RSN_NTFY_WL_STA);
9691 	} else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >=
9692 		   btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) {
9693 		btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
9694 			btc->dm.cnt_notify[BTC_NCNT_WL_STA];
9695 	} else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] <
9696 		   btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) {
9697 		btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
9698 		btc->dm.cnt_notify[BTC_NCNT_WL_STA];
9699 	}
9700 }
9701 
rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev * rtwdev,u8 func)9702 static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func)
9703 {
9704 	struct rtw89_btc *btc = &rtwdev->btc;
9705 	const struct rtw89_btc_ver *ver = btc->ver;
9706 
9707 	switch (func) {
9708 	case BTF_EVNT_RPT:
9709 	case BTF_EVNT_BT_INFO:
9710 	case BTF_EVNT_BT_SCBD:
9711 	case BTF_EVNT_BT_REG:
9712 	case BTF_EVNT_CX_RUNINFO:
9713 	case BTF_EVNT_BT_PSD:
9714 		return func;
9715 	case BTF_EVNT_BT_DEV_INFO:
9716 		if (ver->fwc2hfunc == 0)
9717 			return BTF_EVNT_BUF_OVERFLOW;
9718 		else
9719 			return BTF_EVNT_BT_DEV_INFO;
9720 	case BTF_EVNT_BT_LEAUDIO_INFO:
9721 		if (ver->fwc2hfunc == 0)
9722 			return BTF_EVNT_C2H_LOOPBACK;
9723 		else if (ver->fwc2hfunc == 1)
9724 			return BTF_EVNT_BUF_OVERFLOW;
9725 		else if (ver->fwc2hfunc == 2)
9726 			return func;
9727 		else if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4)
9728 			return BTF_EVNT_BUF_OVERFLOW;
9729 		else
9730 			return BTF_EVNT_MAX;
9731 	case BTF_EVNT_BUF_OVERFLOW:
9732 		if (ver->fwc2hfunc == 0)
9733 			return BTF_EVNT_MAX;
9734 		else if (ver->fwc2hfunc == 1)
9735 			return BTF_EVNT_C2H_LOOPBACK;
9736 		else if (ver->fwc2hfunc == 2)
9737 			return func;
9738 		else if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4)
9739 			return BTF_EVNT_C2H_LOOPBACK;
9740 		else
9741 			return BTF_EVNT_MAX;
9742 	case BTF_EVNT_C2H_LOOPBACK:
9743 		if (ver->fwc2hfunc == 2)
9744 			return func;
9745 		else if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4)
9746 			return BTF_EVNT_BT_LEAUDIO_INFO;
9747 		else
9748 			return BTF_EVNT_MAX;
9749 	case BTF_EVNT_BT_QUERY_TXPWR:
9750 		if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4)
9751 			return func;
9752 		else
9753 			return BTF_EVNT_MAX;
9754 	case BTF_EVNT_ZB_INFO:
9755 	case BTF_EVNT_ZB_CH:
9756 	case BTF_EVNT_ZB_QUERY_TXPWR:
9757 		if (ver->fwc2hfunc == 4)
9758 			return func;
9759 		else
9760 			return BTF_EVNT_MAX;
9761 	case BTF_EVNT_MAX:
9762 	default:
9763 		return BTF_EVNT_MAX;
9764 	}
9765 }
9766 
rtw89_btc_c2h_handle(struct rtw89_dev * rtwdev,struct sk_buff * skb,u32 len,u8 class,u8 func)9767 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
9768 			  u32 len, u8 class, u8 func)
9769 {
9770 	struct rtw89_btc *btc = &rtwdev->btc;
9771 	struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt0;
9772 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9773 	u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN];
9774 	u8 bid = BTC_BT_1ST;
9775 
9776 	len -= RTW89_C2H_HEADER_LEN;
9777 
9778 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
9779 		    "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n",
9780 		    __func__, len, class, func);
9781 
9782 	if (class != BTFC_FW_EVENT)
9783 		return;
9784 
9785 	if (func & BT_C2H_FUNC_BT2ND) {
9786 		bid = BTC_BT_2ND;
9787 		func &= ~BT_C2H_FUNC_BT2ND;
9788 		bt = &btc->cx.bt1;
9789 	}
9790 
9791 	func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func);
9792 	pfwinfo->cnt_c2h++;
9793 
9794 	switch (func) {
9795 	case BTF_EVNT_BUF_OVERFLOW:
9796 		pfwinfo->event[func]++;
9797 		break;
9798 	case BTF_EVNT_RPT:
9799 		pfwinfo->event[func]++;
9800 		/* Don't need rtw89_leave_ps_mode() */
9801 		btc_fw_event(rtwdev, func, buf, len);
9802 		break;
9803 	case BTF_EVNT_BT_INFO:
9804 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
9805 			    "[BTC], handle C2H BT INFO with data %8ph\n", buf);
9806 		bt->bcnt[BTC_BCNT_INFOUPDATE]++;
9807 		_update_bt_info(rtwdev, bid, buf, len);
9808 		break;
9809 	case BTF_EVNT_BT_SCBD:
9810 		bt->bcnt[BTC_BCNT_SCBDUPDATE]++;
9811 		bt->scbd_c2h = ((buf[3] << 24) | (buf[2] << 16) |
9812 				(buf[1] << 8) | (buf[0]));
9813 		bt->scbd_rb = bt->scbd_c2h;
9814 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
9815 			    "[BTC], handle C2H BT%d SCBD with data 0x%08x\n",
9816 			    bid, bt->scbd_c2h);
9817 		_update_bt_scbd(rtwdev, bid);
9818 		_run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
9819 		break;
9820 	case BTF_EVNT_BT_PSD:
9821 		break;
9822 	case BTF_EVNT_BT_REG:
9823 		btc->dbg.rb_done = true;
9824 		btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf));
9825 
9826 		break;
9827 	case BTF_EVNT_C2H_LOOPBACK:
9828 		btc->dbg.rb_done = true;
9829 		btc->dbg.rb_val = buf[0];
9830 		break;
9831 	case BTF_EVNT_CX_RUNINFO:
9832 		btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
9833 		break;
9834 	case BTF_EVNT_BT_LEAUDIO_INFO:
9835 		bt->bcnt[BTC_BCNT_LEAUDIO_INFOUPDATE]++;
9836 		if (buf[BTC_BTINFO_L0] == BTC_BTINFO_BISTDMA)
9837 			_update_bt_bistdma_info(rtwdev, bid, buf, len);
9838 		else
9839 			_update_bt_leaudio_info(rtwdev, bid, buf, len);
9840 		_run_coex(rtwdev, BTC_RSN_UPDATE_BT_LEAUDINFO);
9841 		break;
9842 	case BTF_EVNT_BT_QUERY_TXPWR:
9843 		bt->bcnt[BTC_BCNT_TXPWR_UPDATE]++;
9844 		_update_bt_txpwr_info(rtwdev, buf, len);
9845 	}
9846 }
9847 
9848 #define BTC_CX_FW_OFFLOAD 0
9849 
_show_cx_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9850 static int _show_cx_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9851 {
9852 	struct rtw89_btc_module *md = &rtwdev->btc.mdinfo;
9853 	const struct rtw89_chip_info *chip = rtwdev->chip;
9854 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
9855 	struct rtw89_hal *hal = &rtwdev->hal;
9856 	struct rtw89_btc *btc = &rtwdev->btc;
9857 	struct rtw89_btc_dm *dm = &btc->dm;
9858 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
9859 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9860 	u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
9861 	char *p = buf, *end = buf + bufsz;
9862 
9863 	if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
9864 		return 0;
9865 
9866 	p += scnprintf(p, end - p,
9867 		       "\n========== [BTC COEX INFO (%s)] ==========\n",
9868 		       chip_id_str(chip->chip_id));
9869 
9870 	ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION);
9871 	ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION);
9872 	ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION);
9873 	id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION);
9874 	p += scnprintf(p, end - p, " %-15s : Coex:%d.%d.%d(branch:%d), ",
9875 		       "[coex_version]", ver_main, ver_sub, ver_hotfix,
9876 		       id_branch);
9877 
9878 	ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
9879 	ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex);
9880 	ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex);
9881 	id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex);
9882 	p += scnprintf(p, end - p, "WL_FW_coex:%d.%d.%d(branch:%d)",
9883 		       ver_main, ver_sub, ver_hotfix, id_branch);
9884 
9885 	ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired);
9886 	ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired);
9887 	ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
9888 	p += scnprintf(p, end - p, "(%s, desired:%d.%d.%d), ",
9889 		       (wl->ver_info.fw_coex >= chip->wlcx_desired ?
9890 			"Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
9891 
9892 	p += scnprintf(p, end - p, "BT_FW_coex:%d(%s, desired:%d)\n",
9893 		       bt->ver_info.fw_coex,
9894 		       (bt->ver_info.fw_coex >= ver->bt_desired ?
9895 			"Match" : "Mismatch"), ver->bt_desired);
9896 
9897 	ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw);
9898 	ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw);
9899 	ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw);
9900 	id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw);
9901 	p += scnprintf(p, end - p,
9902 		       " %-15s : WL_FW:%d.%d.%d.%d(built:%.12s-%.12s), BT_FW:0x%x(%s)\n",
9903 		       "[sub_module]",
9904 		       ver_main, ver_sub, ver_hotfix, id_branch,
9905 		       wl->ver_info.build_time, wl->ver_info.build_date,
9906 		       bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM");
9907 
9908 	p += scnprintf(p, end - p,
9909 		       " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s",
9910 		       "[hw_info]",
9911 		       md->kt_ver, md->rfe_type, md->ant.isolation,
9912 		       md->ant.num, md->ant.num > 1 ? "" :
9913 		       md->ant.single_pos ? "1Ant_Pos:S1, " : "1Ant_Pos:S0, ");
9914 
9915 	p += scnprintf(p, end - p,
9916 		       "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n",
9917 		       btc->cx.bt_ext.func_type, rtwdev->dbcc_en, hal->tx_nss,
9918 		       hal->rx_nss);
9919 
9920 	return p - buf;
9921 }
9922 
_show_wl_role_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9923 static int _show_wl_role_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9924 {
9925 	struct rtw89_btc *btc = &rtwdev->btc;
9926 	struct rtw89_btc_wl_link_info *plink = NULL;
9927 	struct rtw89_traffic_stats *t;
9928 	char *p = buf, *end = buf + bufsz;
9929 	u8 i, j;
9930 
9931 	for (i = 0; i < btc->ver->max_role_num; i++) {
9932 		for (j = 0; j < RTW89_MAC_NUM; j++) {
9933 			plink = &btc->cx.wl.rlink_info[i][j];
9934 
9935 			if (!plink->active)
9936 				continue;
9937 
9938 			p += scnprintf(p, end - p,
9939 				       " [port_%d]        : role=%d(phy-%d), connect=%s(client_cnt=%d), mode=%d, center_ch=%d, bw=%d",
9940 				       plink->pid, plink->role, plink->phy,
9941 				       id_to_mlme_state(plink->connected),
9942 				       plink->client_cnt - 1, plink->mode,
9943 				       plink->ch, plink->bw);
9944 
9945 			if (plink->connected == MLME_NO_LINK) {
9946 				p += scnprintf(p, end - p, "\n");
9947 				continue;
9948 			}
9949 
9950 			p += scnprintf(p, end - p,
9951 				       ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n",
9952 				       plink->mac_id, plink->tx_time, plink->tx_retry);
9953 
9954 			p += scnprintf(p, end - p,
9955 				       " [port_%d]        : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
9956 				       plink->pid, 110 - plink->stat.rssi,
9957 				       plink->stat.rssi, plink->busy,
9958 				       plink->dir == RTW89_TFC_UL ? "UL" : "DL");
9959 
9960 			t = &plink->stat.traffic;
9961 
9962 			p += scnprintf(p, end - p,
9963 				       "tx[rate:%d/busy_level:%d], ",
9964 				       t->tx_rate, t->tx_tfc_lv);
9965 
9966 			p += scnprintf(p, end - p,
9967 				       "rx[rate:%d/busy_level:%d/drop:%d]\n",
9968 				       t->rx_rate,
9969 				       t->rx_tfc_lv, plink->rx_rate_drop_cnt);
9970 		}
9971 	}
9972 	return p - buf;
9973 }
9974 
_show_wl_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9975 static int _show_wl_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9976 {
9977 	struct rtw89_btc *btc = &rtwdev->btc;
9978 	struct rtw89_btc_cx *cx = &btc->cx;
9979 	struct rtw89_btc_wl_info *wl = &cx->wl;
9980 	struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
9981 	char *p = buf, *end = buf + bufsz;
9982 	u8 mode;
9983 
9984 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
9985 		return 0;
9986 
9987 	p += scnprintf(p, end - p, "========== [WL Status] ==========\n");
9988 
9989 	mode = wl_rinfo->link_mode;
9990 
9991 	p += scnprintf(p, end - p, " %-15s : link_mode:%s, ", "[status]",
9992 		       id_to_linkmode(mode));
9993 
9994 	p += scnprintf(p, end - p,
9995 		       "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ",
9996 		       wl->status.map.rf_off, wl->status.map.lps,
9997 		       wl->status.map.scan ? "Y" : "N",
9998 		       wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
9999 
10000 	p += scnprintf(p, end - p,
10001 		       "handshake:%s, roam:%s, 4way:%s, init_ok:%s\n",
10002 		       wl->status.map.handshake ? "Y" : "N",
10003 		       wl->status.map.roaming ?  "Y" : "N",
10004 		       wl->status.map._4way ? "Y" : "N",
10005 		       wl->status.map.init_ok ? "Y" : "N");
10006 
10007 	p += _show_wl_role_info(rtwdev, p, end - p);
10008 
10009 	return p - buf;
10010 }
10011 
10012 enum btc_bt_a2dp_type {
10013 	BTC_A2DP_LEGACY = 0,
10014 	BTC_A2DP_TWS_SNIFF = 1,
10015 	BTC_A2DP_TWS_RELAY = 2,
10016 };
10017 
_show_bt_profile_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz,u8 bid)10018 static int _show_bt_profile_info(struct rtw89_dev *rtwdev, char *buf,
10019 				 size_t bufsz, u8 bid)
10020 {
10021 	struct rtw89_btc *btc = &rtwdev->btc;
10022 	struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ?
10023 				       &btc->cx.bt0 : &btc->cx.bt1;
10024 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
10025 	struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
10026 	struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
10027 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
10028 	struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
10029 	char *p = buf, *end = buf + bufsz;
10030 
10031 	if (hfp.exist) {
10032 		p += scnprintf(p, end - p,
10033 			       " %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
10034 			       "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"),
10035 			       bt_linfo->sut_pwr_level[0],
10036 			       bt_linfo->golden_rx_shift[0]);
10037 	}
10038 
10039 	if (hid.exist) {
10040 		p += scnprintf(p, end - p,
10041 			       "\n %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n",
10042 			       "[HID]",
10043 			       hid.type & BTC_HID_218 ? "2/18," : "",
10044 			       hid.type & BTC_HID_418 ? "4/18," : "",
10045 			       hid.type & BTC_HID_BLE ? "BLE," : "",
10046 			       hid.type & BTC_HID_RCU ? "RCU," : "",
10047 			       hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "",
10048 			       hid.pair_cnt, bt_linfo->sut_pwr_level[1],
10049 			       bt_linfo->golden_rx_shift[1]);
10050 	}
10051 
10052 	if (a2dp.exist) {
10053 		p += scnprintf(p, end - p,
10054 			       " %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
10055 			       "[A2DP]",
10056 			       a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS",
10057 			       a2dp.bitpool, a2dp.flush_time);
10058 
10059 		p += scnprintf(p, end - p,
10060 			       "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n",
10061 			       a2dp.vendor_id, a2dp.device_name,
10062 			       bt_linfo->sut_pwr_level[2],
10063 			       bt_linfo->golden_rx_shift[2]);
10064 	}
10065 
10066 	if (pan.exist) {
10067 		p += scnprintf(p, end - p,
10068 			       " %-15s : sut_pwr:%d, golden-rx:%d\n",
10069 			       "[PAN]",
10070 			       bt_linfo->sut_pwr_level[3],
10071 			       bt_linfo->golden_rx_shift[3]);
10072 	}
10073 
10074 	return p - buf;
10075 }
10076 
_show_bt_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz,u8 bid)10077 static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz, u8 bid)
10078 {
10079 	struct rtw89_btc *btc = &rtwdev->btc;
10080 	const struct rtw89_btc_ver *ver = btc->ver;
10081 	struct rtw89_btc_cx *cx = &btc->cx;
10082 	struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1;
10083 	struct rtw89_btc_wl_info *wl = &cx->wl;
10084 	struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
10085 	struct rtw89_btc_module *md = &btc->mdinfo;
10086 	u8 bt_pos = (bid == BTC_BT_1ST) ? md->bt0_pos : md->bt1_pos;
10087 	s8 br_dbm = bt->link_info.bt_txpwr_desc.br_dbm;
10088 	s8 le_dbm = bt->link_info.bt_txpwr_desc.le_dbm;
10089 	u8 hw_band = wl->role_info.pta_req_band;
10090 	struct rtw89_btc_wl_afh_info *wl_afh;
10091 	char *p = buf, *end = buf + bufsz;
10092 	u8 *afh = bt_linfo->afh_map;
10093 	u8 *afh_le = bt_linfo->afh_map_le;
10094 
10095 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
10096 		return 0;
10097 
10098 	if (bid == BTC_BT_2ND) {
10099 		if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))
10100 			return 0;
10101 		if (!bt->enable.now)
10102 			return 0;
10103 	}
10104 
10105 	p += scnprintf(p, end - p, "========== [BT_%s Status] ==========\n",
10106 		       bid == BTC_BT_1ST ? "1ST" : "2ND");
10107 
10108 	p += scnprintf(p, end - p,
10109 		       " %-15s : enable:%s, btg:%s%s, connect:%s, ",
10110 		       "[status]", bt->enable.now ? "Y" : "N",
10111 		       bt->btg_type ? "Y" : "N",
10112 		       (bt->enable.now && (bt->btg_type != bt_pos) ?
10113 			"(efuse-mismatch!!)" : ""),
10114 		       (bt_linfo->status.map.connect ? "Y" : "N"));
10115 
10116 	p += scnprintf(p, end - p,
10117 		       "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n",
10118 		       bt->igno_wl ? "Y" : "N",
10119 		       bt->mbx_avl ? "Y" : "N", bt->rfk_info.val);
10120 
10121 	p += scnprintf(p, end - p, " %-15s : profile:%s%s%s%s%s ",
10122 		       "[profile]",
10123 		       (bt_linfo->link_cnt.now == 0) ? "None," : "",
10124 		       bt_linfo->hfp_desc.exist ? "HFP," : "",
10125 		       bt_linfo->hid_desc.exist ? "HID," : "",
10126 		       bt_linfo->a2dp_desc.exist ?
10127 		       (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "",
10128 		       bt_linfo->pan_desc.exist ? "PAN," : "");
10129 
10130 	p += scnprintf(p, end - p,
10131 		       "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n",
10132 		       bt_linfo->multi_link.now ? "Y" : "N",
10133 		       bt_linfo->slave_role ? "Slave" : "Master",
10134 		       bt_linfo->status.map.ble_connect ? "Y" : "N",
10135 		       bt_linfo->cqddr ? "Y" : "N",
10136 		       bt_linfo->a2dp_desc.active ? "Y" : "N",
10137 		       bt_linfo->pan_desc.active ? "Y" : "N");
10138 
10139 	p += scnprintf(p, end - p,
10140 		       " %-15s : rssi:%ddBm(lvl:%d), tx_rate:%dM, %s%s%s",
10141 		       "[link]", bt_linfo->rssi - 100,
10142 		       bt->rssi_level,
10143 		       bt_linfo->tx_3m ? 3 : 2,
10144 		       bt_linfo->status.map.inq_pag ? " inq-page!!" : "",
10145 		       bt_linfo->status.map.acl_busy ? " acl_busy!!" : "",
10146 		       bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : "");
10147 
10148 	p += scnprintf(p, end - p,
10149 		       "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
10150 		       bt_linfo->relink.now ? " ReLink!!" : "",
10151 		       afh[0], afh[1], afh[2], afh[3], afh[4],
10152 		       afh[5], afh[6], afh[7], afh[8], afh[9]);
10153 
10154 	if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
10155 		p += scnprintf(p, end - p,
10156 			       "LE[%02x%02x_%02x_%02x%02x]",
10157 			       afh_le[0], afh_le[1], afh_le[2],
10158 			       afh_le[3], afh_le[4]);
10159 
10160 	wl_afh = &wl->afh_info[hw_band][RTW89_BAND_2G];
10161 	p += scnprintf(p, end - p, "wl_ch_map[hwb:%d/en:%d/ch:%d/bw:%d/rf_band:%d]\n",
10162 		       hw_band, wl_afh->en, wl_afh->ch, wl_afh->bw, wl_afh->band);
10163 
10164 	p += scnprintf(p, end - p,
10165 		       " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
10166 		       "[stat_cnt]", bt->bcnt[BTC_BCNT_RETRY],
10167 		       bt->bcnt[BTC_BCNT_RELINK],
10168 		       bt->bcnt[BTC_BCNT_RATECHG],
10169 		       bt->bcnt[BTC_BCNT_REINIT],
10170 		       bt->bcnt[BTC_BCNT_REENABLE]);
10171 
10172 	p += scnprintf(p, end - p,
10173 		       "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n",
10174 		       bt->bcnt[BTC_BCNT_ROLESW], bt->bcnt[BTC_BCNT_AFH],
10175 		       bt->bcnt[BTC_BCNT_INQPAG], bt->bcnt[BTC_BCNT_INQ],
10176 		       bt->bcnt[BTC_BCNT_PAGE], bt->bcnt[BTC_BCNT_IGNOWL]);
10177 
10178 	p += _show_bt_profile_info(rtwdev, p, end - p, bid);
10179 
10180 	p += scnprintf(p, end - p,
10181 		       " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n",
10182 		       "[bt_info]", bt->raw_info[2], bt->raw_info[3],
10183 		       bt->raw_info[4], bt->raw_info[5], bt->raw_info[6],
10184 		       bt->raw_info[7],
10185 		       bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
10186 		       bt->bcnt[BTC_BCNT_INFOUPDATE],
10187 		       bt->bcnt[BTC_BCNT_INFOSAME]);
10188 
10189 	p += scnprintf(p, end - p,
10190 		       " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)",
10191 		       "[trx_req_cnt]", bt->bcnt[BTC_BCNT_HIPRI_RX],
10192 		       bt->bcnt[BTC_BCNT_HIPRI_TX],
10193 		       bt->bcnt[BTC_BCNT_LOPRI_RX],
10194 		       bt->bcnt[BTC_BCNT_LOPRI_TX],
10195 		       bt->bcnt[BTC_BCNT_POLLUTED]);
10196 
10197 	if (ver->fcxbtscan == 1) {
10198 		p += scnprintf(p, end - p,
10199 			       "(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)",
10200 			       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win),
10201 			       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl),
10202 			       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win),
10203 			       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl),
10204 			       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win),
10205 			       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl),
10206 			       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win),
10207 			       le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl));
10208 	} else if (ver->fcxbtscan == 2) {
10209 		p += scnprintf(p, end - p,
10210 			       "(BG:%d-%d/INIT:%d-%d/LE:%d-%d)",
10211 			       le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win),
10212 			       le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl),
10213 			       le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win),
10214 			       le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl),
10215 			       le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win),
10216 			       le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl));
10217 	}
10218 	p += scnprintf(p, end - p, "\n");
10219 
10220 	if (bt->bcnt[BTC_BCNT_TXPWR_UPDATE]) {
10221 		p += scnprintf(p, end - p,
10222 			       " %-15s : br_index:0x%x, le_index:0x%x",
10223 			       "[bt_txpwr_lvl]",
10224 			       bt->link_info.bt_txpwr_desc.br_gain_index,
10225 			       bt->link_info.bt_txpwr_desc.le_gain_index);
10226 		p += scnprintf(p, end - p, ", br_dbm:%d dBm", br_dbm);
10227 		p += scnprintf(p, end - p, ", le_dbm:%d dBm", le_dbm);
10228 	} else {
10229 		p += scnprintf(p, end - p,
10230 			       " %-15s : br_index:NA, le_index:NA, br_dbm:%d dBm[def], le_dbm:%d dBm[def]",
10231 			       "[bt_txpwr_lvl]",
10232 			       bt->link_info.bt_txpwr_desc.br_dbm,
10233 			       bt->link_info.bt_txpwr_desc.le_dbm);
10234 	}
10235 	p += scnprintf(p, end - p, "\n");
10236 
10237 	return p - buf;
10238 }
10239 
10240 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e
10241 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
10242 #define CASE_BTC_POLICY_STR(e) \
10243 	case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
10244 #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e
10245 #define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e
10246 #define CASE_BTC_INIT(e) case BTC_MODE_## e: return #e
10247 #define CASE_BTC_ANTPATH_STR(e) case BTC_ANT_##e: return #e
10248 #define CASE_BTC_POLUT_STR(e) case BTC_PLT_## e: return #e
10249 #define CASE_BTC_REGTYPE_STR(e) case REG_## e: return #e
10250 #define CASE_BTC_GDBG_STR(e) case BTC_DBG_## e: return #e
10251 #define CASE_BTC_H2CCMD(e) case SET_##e: return #e
10252 
id_to_polut(u32 id)10253 static const char *id_to_polut(u32 id)
10254 {
10255 	switch (id) {
10256 	CASE_BTC_POLUT_STR(NONE);
10257 	CASE_BTC_POLUT_STR(GNT_BT_TX);
10258 	CASE_BTC_POLUT_STR(GNT_BT_RX);
10259 	CASE_BTC_POLUT_STR(GNT_WL);
10260 	CASE_BTC_POLUT_STR(BT);
10261 	CASE_BTC_POLUT_STR(ALL);
10262 	default:
10263 		return "unknown";
10264 	}
10265 }
10266 
id_to_regtype(u32 id)10267 static const char *id_to_regtype(u32 id)
10268 {
10269 	switch (id) {
10270 	CASE_BTC_REGTYPE_STR(MAC);
10271 	CASE_BTC_REGTYPE_STR(BB);
10272 	CASE_BTC_REGTYPE_STR(RF);
10273 	CASE_BTC_REGTYPE_STR(BT_RF);
10274 	CASE_BTC_REGTYPE_STR(BT_MODEM);
10275 	CASE_BTC_REGTYPE_STR(BT_BLUEWIZE);
10276 	CASE_BTC_REGTYPE_STR(BT_VENDOR);
10277 	CASE_BTC_REGTYPE_STR(BT_LE);
10278 	default:
10279 		return "unknown";
10280 	}
10281 }
10282 
id_to_gdbg(u32 id)10283 static const char *id_to_gdbg(u32 id)
10284 {
10285 	switch (id) {
10286 	CASE_BTC_GDBG_STR(GNT_BT);
10287 	CASE_BTC_GDBG_STR(GNT_WL);
10288 	CASE_BTC_GDBG_STR(GNT_BT1);
10289 	CASE_BTC_GDBG_STR(GNT_WL1);
10290 	CASE_BTC_GDBG_STR(BCN_EARLY);
10291 	CASE_BTC_GDBG_STR(WL_NULL0);
10292 	CASE_BTC_GDBG_STR(WL_NULL1);
10293 	CASE_BTC_GDBG_STR(WL_RXISR);
10294 	CASE_BTC_GDBG_STR(TDMA_ENTRY);
10295 	CASE_BTC_GDBG_STR(A2DP_EMPTY);
10296 	CASE_BTC_GDBG_STR(BT_RETRY);
10297 	CASE_BTC_GDBG_STR(BT_RELINK);
10298 	CASE_BTC_GDBG_STR(SLOT_WL);
10299 	CASE_BTC_GDBG_STR(SLOT_BT);
10300 	CASE_BTC_GDBG_STR(WL_ERR);
10301 	CASE_BTC_GDBG_STR(WL_OK);
10302 	CASE_BTC_GDBG_STR(SLOT_B2W);
10303 	CASE_BTC_GDBG_STR(SLOT_W1);
10304 	CASE_BTC_GDBG_STR(SLOT_W2);
10305 	CASE_BTC_GDBG_STR(SLOT_W2B);
10306 	CASE_BTC_GDBG_STR(SLOT_B1);
10307 	CASE_BTC_GDBG_STR(SLOT_B2);
10308 	CASE_BTC_GDBG_STR(SLOT_B3);
10309 	CASE_BTC_GDBG_STR(SLOT_B4);
10310 	CASE_BTC_GDBG_STR(SLOT_LK);
10311 	CASE_BTC_GDBG_STR(SLOT_E2G);
10312 	CASE_BTC_GDBG_STR(SLOT_E5G);
10313 	CASE_BTC_GDBG_STR(SLOT_EBT);
10314 	CASE_BTC_GDBG_STR(SLOT_WLK);
10315 	CASE_BTC_GDBG_STR(SLOT_B1FDD);
10316 	CASE_BTC_GDBG_STR(BT_CHANGE);
10317 	CASE_BTC_GDBG_STR(WL_CCA);
10318 	default:
10319 		return "unknown";
10320 	}
10321 }
10322 
steps_to_str(u16 step)10323 static const char *steps_to_str(u16 step)
10324 {
10325 	switch (step) {
10326 	CASE_BTC_RSN_STR(NONE);
10327 	CASE_BTC_RSN_STR(NTFY_INIT);
10328 	CASE_BTC_RSN_STR(NTFY_SWBAND);
10329 	CASE_BTC_RSN_STR(NTFY_WL_STA);
10330 	CASE_BTC_RSN_STR(NTFY_RADIO_STATE);
10331 	CASE_BTC_RSN_STR(UPDATE_BT_SCBD);
10332 	CASE_BTC_RSN_STR(NTFY_WL_RFK);
10333 	CASE_BTC_RSN_STR(UPDATE_BT_INFO);
10334 	CASE_BTC_RSN_STR(NTFY_SCAN_START);
10335 	CASE_BTC_RSN_STR(NTFY_SCAN_FINISH);
10336 	CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET);
10337 	CASE_BTC_RSN_STR(NTFY_POWEROFF);
10338 	CASE_BTC_RSN_STR(NTFY_ROLE_INFO);
10339 	CASE_BTC_RSN_STR(CMD_SET_COEX);
10340 	CASE_BTC_RSN_STR(ACT1_WORK);
10341 	CASE_BTC_RSN_STR(BT_DEVINFO_WORK);
10342 	CASE_BTC_RSN_STR(RFK_CHK_WORK);
10343 	CASE_BTC_RSN_STR(UPDATE_BT_LEAUDINFO);
10344 
10345 	CASE_BTC_ACT_STR(NONE);
10346 	CASE_BTC_ACT_STR(WL_ONLY);
10347 	CASE_BTC_ACT_STR(WL_5G);
10348 	CASE_BTC_ACT_STR(WL_OTHER);
10349 	CASE_BTC_ACT_STR(WL_IDLE);
10350 	CASE_BTC_ACT_STR(WL_NC);
10351 	CASE_BTC_ACT_STR(WL_RFK);
10352 	CASE_BTC_ACT_STR(WL_INIT);
10353 	CASE_BTC_ACT_STR(WL_OFF);
10354 	CASE_BTC_ACT_STR(FREERUN);
10355 	CASE_BTC_ACT_STR(BT_WHQL);
10356 	CASE_BTC_ACT_STR(BT_RFK);
10357 	CASE_BTC_ACT_STR(BT_OFF);
10358 	CASE_BTC_ACT_STR(BT_IDLE);
10359 	CASE_BTC_ACT_STR(BT_HFP);
10360 	CASE_BTC_ACT_STR(BT_HID);
10361 	CASE_BTC_ACT_STR(BT_A2DP);
10362 	CASE_BTC_ACT_STR(BT_A2DPSINK);
10363 	CASE_BTC_ACT_STR(BT_PAN);
10364 	CASE_BTC_ACT_STR(BT_A2DP_HID);
10365 	CASE_BTC_ACT_STR(BT_A2DP_PAN);
10366 	CASE_BTC_ACT_STR(BT_PAN_HID);
10367 	CASE_BTC_ACT_STR(BT_A2DP_PAN_HID);
10368 	CASE_BTC_ACT_STR(BT_BIS);
10369 	CASE_BTC_ACT_STR(BT_CIS);
10370 	CASE_BTC_ACT_STR(WL_25G_MCC);
10371 	CASE_BTC_ACT_STR(WL_2G_MCC);
10372 	CASE_BTC_ACT_STR(WL_2G_SCC);
10373 	CASE_BTC_ACT_STR(WL_2G_AP);
10374 	CASE_BTC_ACT_STR(WL_2G_GO);
10375 	CASE_BTC_ACT_STR(WL_2G_GC);
10376 	CASE_BTC_ACT_STR(WL_2G_NAN);
10377 
10378 	CASE_BTC_POLICY_STR(OFF_BT);
10379 	CASE_BTC_POLICY_STR(OFF_WL);
10380 	CASE_BTC_POLICY_STR(OFF_EQ0);
10381 	CASE_BTC_POLICY_STR(OFF_EQ1);
10382 	CASE_BTC_POLICY_STR(OFF_EQ2);
10383 	CASE_BTC_POLICY_STR(OFF_EQ3);
10384 	CASE_BTC_POLICY_STR(OFF_EQ4);
10385 	CASE_BTC_POLICY_STR(OFF_EQ5);
10386 	CASE_BTC_POLICY_STR(OFF_BWB0);
10387 	CASE_BTC_POLICY_STR(OFF_BWB1);
10388 	CASE_BTC_POLICY_STR(OFF_BWB2);
10389 	CASE_BTC_POLICY_STR(OFF_BWB3);
10390 	CASE_BTC_POLICY_STR(OFF_WL2);
10391 	CASE_BTC_POLICY_STR(OFFB_BWB0);
10392 	CASE_BTC_POLICY_STR(OFFE_DEF);
10393 	CASE_BTC_POLICY_STR(OFFE_DEF2);
10394 	CASE_BTC_POLICY_STR(OFFE_2GBWISOB);
10395 	CASE_BTC_POLICY_STR(OFFE_2GISOB);
10396 	CASE_BTC_POLICY_STR(OFFE_2GBWMIXB);
10397 	CASE_BTC_POLICY_STR(OFFE_WL);
10398 	CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2);
10399 	CASE_BTC_POLICY_STR(FIX_TD3030);
10400 	CASE_BTC_POLICY_STR(FIX_TD5050);
10401 	CASE_BTC_POLICY_STR(FIX_TD2030);
10402 	CASE_BTC_POLICY_STR(FIX_TD4010);
10403 	CASE_BTC_POLICY_STR(FIX_TD7010);
10404 	CASE_BTC_POLICY_STR(FIX_TD2060);
10405 	CASE_BTC_POLICY_STR(FIX_TD3060);
10406 	CASE_BTC_POLICY_STR(FIX_TD2080);
10407 	CASE_BTC_POLICY_STR(FIX_TDW1B1);
10408 	CASE_BTC_POLICY_STR(FIX_TD4010ISO);
10409 	CASE_BTC_POLICY_STR(FIX_TD4010ISO_DL);
10410 	CASE_BTC_POLICY_STR(FIX_TD4010ISO_UL);
10411 	CASE_BTC_POLICY_STR(PFIX_TD3030);
10412 	CASE_BTC_POLICY_STR(PFIX_TD5050);
10413 	CASE_BTC_POLICY_STR(PFIX_TD2030);
10414 	CASE_BTC_POLICY_STR(PFIX_TD2060);
10415 	CASE_BTC_POLICY_STR(PFIX_TD3070);
10416 	CASE_BTC_POLICY_STR(PFIX_TD2080);
10417 	CASE_BTC_POLICY_STR(PFIX_TDW1B1);
10418 	CASE_BTC_POLICY_STR(AUTO_TD50B1);
10419 	CASE_BTC_POLICY_STR(AUTO_TD60B1);
10420 	CASE_BTC_POLICY_STR(AUTO_TD20B1);
10421 	CASE_BTC_POLICY_STR(AUTO_TDW1B1);
10422 	CASE_BTC_POLICY_STR(PAUTO_TD50B1);
10423 	CASE_BTC_POLICY_STR(PAUTO_TD60B1);
10424 	CASE_BTC_POLICY_STR(PAUTO_TD20B1);
10425 	CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
10426 	CASE_BTC_POLICY_STR(AUTO2_TD3050);
10427 	CASE_BTC_POLICY_STR(AUTO2_TD3070);
10428 	CASE_BTC_POLICY_STR(AUTO2_TD5050);
10429 	CASE_BTC_POLICY_STR(AUTO2_TD6060);
10430 	CASE_BTC_POLICY_STR(AUTO2_TD2080);
10431 	CASE_BTC_POLICY_STR(AUTO2_TDW1B4);
10432 	CASE_BTC_POLICY_STR(PAUTO2_TD3050);
10433 	CASE_BTC_POLICY_STR(PAUTO2_TD3070);
10434 	CASE_BTC_POLICY_STR(PAUTO2_TD5050);
10435 	CASE_BTC_POLICY_STR(PAUTO2_TD6060);
10436 	CASE_BTC_POLICY_STR(PAUTO2_TD2080);
10437 	CASE_BTC_POLICY_STR(PAUTO2_TDW1B4);
10438 	default:
10439 		return "unknown step";
10440 	}
10441 }
10442 
id_to_slot(u32 id)10443 static const char *id_to_slot(u32 id)
10444 {
10445 	switch (id) {
10446 	CASE_BTC_SLOT_STR(OFF);
10447 	CASE_BTC_SLOT_STR(B2W);
10448 	CASE_BTC_SLOT_STR(W1);
10449 	CASE_BTC_SLOT_STR(W2);
10450 	CASE_BTC_SLOT_STR(W2B);
10451 	CASE_BTC_SLOT_STR(B1);
10452 	CASE_BTC_SLOT_STR(B2);
10453 	CASE_BTC_SLOT_STR(B3);
10454 	CASE_BTC_SLOT_STR(B4);
10455 	CASE_BTC_SLOT_STR(LK);
10456 	CASE_BTC_SLOT_STR(BLK);
10457 	CASE_BTC_SLOT_STR(E2G);
10458 	CASE_BTC_SLOT_STR(E5G);
10459 	CASE_BTC_SLOT_STR(EBT);
10460 	CASE_BTC_SLOT_STR(ENULL);
10461 	CASE_BTC_SLOT_STR(WLK);
10462 	CASE_BTC_SLOT_STR(W1FDD);
10463 	CASE_BTC_SLOT_STR(B1FDD);
10464 	default:
10465 		return "unknown";
10466 	}
10467 }
10468 
id_to_evt(u32 id)10469 static const char *id_to_evt(u32 id)
10470 {
10471 	switch (id) {
10472 	CASE_BTC_EVT_STR(TDMA_ENTRY);
10473 	CASE_BTC_EVT_STR(WL_TMR);
10474 	CASE_BTC_EVT_STR(B1_TMR);
10475 	CASE_BTC_EVT_STR(B2_TMR);
10476 	CASE_BTC_EVT_STR(B3_TMR);
10477 	CASE_BTC_EVT_STR(B4_TMR);
10478 	CASE_BTC_EVT_STR(W2B_TMR);
10479 	CASE_BTC_EVT_STR(B2W_TMR);
10480 	CASE_BTC_EVT_STR(BCN_EARLY);
10481 	CASE_BTC_EVT_STR(A2DP_EMPTY);
10482 	CASE_BTC_EVT_STR(LK_END);
10483 	CASE_BTC_EVT_STR(RX_ISR);
10484 	CASE_BTC_EVT_STR(RX_FC0);
10485 	CASE_BTC_EVT_STR(RX_FC1);
10486 	CASE_BTC_EVT_STR(BT_RELINK);
10487 	CASE_BTC_EVT_STR(BT_RETRY);
10488 	CASE_BTC_EVT_STR(E2G);
10489 	CASE_BTC_EVT_STR(E5G);
10490 	CASE_BTC_EVT_STR(EBT);
10491 	CASE_BTC_EVT_STR(ENULL);
10492 	CASE_BTC_EVT_STR(DRV_WLK);
10493 	CASE_BTC_EVT_STR(BCN_OK);
10494 	CASE_BTC_EVT_STR(BT_CHANGE);
10495 	CASE_BTC_EVT_STR(EBT_EXTEND);
10496 	CASE_BTC_EVT_STR(E2G_NULL1);
10497 	CASE_BTC_EVT_STR(B1FDD_TMR);
10498 	default:
10499 		return "unknown";
10500 	}
10501 }
10502 
id_to_mode(u8 id)10503 static const char *id_to_mode(u8 id)
10504 {
10505 	switch (id) {
10506 	CASE_BTC_INIT(NORMAL);
10507 	CASE_BTC_INIT(WL);
10508 	CASE_BTC_INIT(BT);
10509 	CASE_BTC_INIT(WLOFF);
10510 	default:
10511 		return "unknown";
10512 	}
10513 }
10514 
id_to_ant(u32 id)10515 static const char *id_to_ant(u32 id)
10516 {
10517 	switch (id) {
10518 	CASE_BTC_ANTPATH_STR(WPOWERON);
10519 	CASE_BTC_ANTPATH_STR(WINIT);
10520 	CASE_BTC_ANTPATH_STR(WONLY);
10521 	CASE_BTC_ANTPATH_STR(WOFF);
10522 	CASE_BTC_ANTPATH_STR(W2G);
10523 	CASE_BTC_ANTPATH_STR(FDD);
10524 	CASE_BTC_ANTPATH_STR(W25G);
10525 	CASE_BTC_ANTPATH_STR(FREERUN);
10526 	CASE_BTC_ANTPATH_STR(WRFK);
10527 	CASE_BTC_ANTPATH_STR(WRFK2);
10528 	CASE_BTC_ANTPATH_STR(PTA);
10529 	CASE_BTC_ANTPATH_STR(MAX);
10530 	default:
10531 		return "unknown";
10532 	}
10533 }
10534 
id_to_h2c(u32 id)10535 static const char *id_to_h2c(u32 id)
10536 {
10537 	switch (id) {
10538 	CASE_BTC_H2CCMD(REPORT_EN);
10539 	CASE_BTC_H2CCMD(SLOT_TABLE);
10540 	CASE_BTC_H2CCMD(MREG_TABLE);
10541 	CASE_BTC_H2CCMD(CX_POLICY);
10542 	CASE_BTC_H2CCMD(GPIO_DBG);
10543 	CASE_BTC_H2CCMD(DRV_INFO);
10544 	CASE_BTC_H2CCMD(DRV_EVENT);
10545 	CASE_BTC_H2CCMD(BT_WREG_ADDR);
10546 	CASE_BTC_H2CCMD(BT_WREG_VAL);
10547 	CASE_BTC_H2CCMD(BT_RREG_ADDR);
10548 	CASE_BTC_H2CCMD(BT_WL_CH_INFO);
10549 	CASE_BTC_H2CCMD(BT_INFO_REPORT);
10550 	CASE_BTC_H2CCMD(BT_IGNORE_WLAN_ACT);
10551 	CASE_BTC_H2CCMD(BT_TX_PWR);
10552 	CASE_BTC_H2CCMD(BT_LNA_CONSTRAIN);
10553 	CASE_BTC_H2CCMD(BT_QUERY_DEV_LIST);
10554 	CASE_BTC_H2CCMD(BT_QUERY_DEV_INFO);
10555 	CASE_BTC_H2CCMD(BT_PSD_REPORT);
10556 	CASE_BTC_H2CCMD(H2C_TEST);
10557 	CASE_BTC_H2CCMD(IOFLD_RF);
10558 	CASE_BTC_H2CCMD(IOFLD_BB);
10559 	CASE_BTC_H2CCMD(IOFLD_MAC);
10560 	CASE_BTC_H2CCMD(IOFLD_SCBD);
10561 	CASE_BTC_H2CCMD(H2C_MACRO);
10562 	default:
10563 		return "unknown";
10564 	}
10565 }
10566 
10567 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)10568 int scnprintf_segment(char *buf, size_t bufsz, const char *prefix, const u16 *data,
10569 		      u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
10570 {
10571 	char *p = buf, *end = buf + bufsz;
10572 	u8 cur_index;
10573 	u8 i;
10574 
10575 	for (i = 0; i < len ; i++) {
10576 		if ((i % seg_len) == 0)
10577 			p += scnprintf(p, end - p, " %-15s : ", prefix);
10578 		cur_index = (start_idx + i) % ring_len;
10579 		if (i % 3 == 0)
10580 			p += scnprintf(p, end - p, "-> %-20s",
10581 				       steps_to_str(*(data + cur_index)));
10582 		else if (i % 3 == 1)
10583 			p += scnprintf(p, end - p, "-> %-15s",
10584 				       steps_to_str(*(data + cur_index)));
10585 		else
10586 			p += scnprintf(p, end - p, "-> %-13s",
10587 				       steps_to_str(*(data + cur_index)));
10588 		if (i == (len - 1) || (i % seg_len) == (seg_len - 1))
10589 			p += scnprintf(p, end - p, "\n");
10590 	}
10591 
10592 	return p - buf;
10593 }
10594 
_show_dm_step(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10595 static int _show_dm_step(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10596 {
10597 	struct rtw89_btc *btc = &rtwdev->btc;
10598 	struct rtw89_btc_dm *dm = &btc->dm;
10599 	char *p = buf, *end = buf + bufsz;
10600 	u8 start_idx;
10601 	u8 len;
10602 
10603 	len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos;
10604 	start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0;
10605 
10606 	p += scnprintf_segment(p, end - p, "[dm_steps]", dm->dm_step.step, len,
10607 			       6, start_idx, ARRAY_SIZE(dm->dm_step.step));
10608 
10609 	return p - buf;
10610 }
10611 
_show_dm_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10612 static int _show_dm_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10613 {
10614 	struct rtw89_btc *btc = &rtwdev->btc;
10615 	struct rtw89_btc_dm *dm = &btc->dm;
10616 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
10617 	struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
10618 	char *p = buf, *end = buf + bufsz;
10619 
10620 	if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
10621 		return 0;
10622 
10623 	p += scnprintf(p, end - p,
10624 		       "========== [Mechanism Status %s] ==========\n",
10625 		       (btc->manual_ctrl ? "(Manual)" : "(Auto)"));
10626 
10627 	p += scnprintf(p, end - p,
10628 		       " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, init_mode:%s, run_cnt:%d\n",
10629 		       "[status]",
10630 		       btc->ant_type == BTC_ANT_SHARED ? "shared" : "dedicated",
10631 		       steps_to_str(dm->run_reason),
10632 		       steps_to_str(dm->run_action | BTC_ACT_EXT_BIT),
10633 		       id_to_ant(FIELD_GET(GENMASK(7, 0), dm->set_ant_path)),
10634 		       id_to_mode(wl->coex_mode),
10635 		       dm->cnt_dm[BTC_DCNT_RUN]);
10636 
10637 	p += _show_dm_step(rtwdev, p, end - p);
10638 
10639 	p += scnprintf(p, end - p,
10640 		       " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ",
10641 		       "[dm_flag]", dm->wl_only, dm->bt_only, btc->ctrl.igno_bt,
10642 		       dm->freerun, btc->btc_ctrl_lps, dm->wl_mimo_ps);
10643 
10644 	p += scnprintf(p, end - p, "leak_ap:%d, fw_offload:%s%s\n",
10645 		       dm->leak_ap,
10646 		       (BTC_CX_FW_OFFLOAD ? "Y" : "N"),
10647 		       (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
10648 			"" : "(Mismatch!!)"));
10649 
10650 	p += scnprintf(p, end - p,
10651 		       " %-15s : wl[rssi_lvl:%d/para:%d/tx_pwr:[%d %d]/rx_lvl:[%d %d]/lna2:%d/stb_chg:%d]\n",
10652 		       "[dm_rf_ctrl]",
10653 		       wl->rssi_level, dm->trx_para_level,
10654 		       dm->rf_trx_para.wl_tx_power[RTW89_PHY_0],
10655 		       dm->rf_trx_para.wl_tx_power[RTW89_PHY_1],
10656 		       dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0],
10657 		       dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1],
10658 		       dm->wl_lna2, dm->wl_stb_chg);
10659 
10660 	p += scnprintf(p, end - p,
10661 		       " %-15s : pre_agc:%d, btg_rx:%d\n",
10662 		       "[dm_bb_ctrl]", dm->wl_pre_agc, dm->wl_btg_rx);
10663 
10664 	p += scnprintf(p, end - p,
10665 		       " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n",
10666 		       "[dm_ctrl]", dm->wl_tx_limit.enable,
10667 		       dm->wl_tx_limit.tx_time,
10668 		       dm->wl_tx_limit.tx_retry, btc->bt_req_len[RTW89_PHY_0],
10669 		       bt->scan_rx_low_pri);
10670 
10671 	return p - buf;
10672 }
10673 
_show_error(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10674 static int _show_error(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10675 {
10676 	struct rtw89_btc *btc = &rtwdev->btc;
10677 	const struct rtw89_btc_ver *ver = btc->ver;
10678 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10679 	union rtw89_btc_fbtc_cysta_info *pcysta;
10680 	char *p = buf, *end = buf + bufsz;
10681 	u32 except_cnt, exception_map;
10682 
10683 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
10684 	if (ver->fcxcysta == 2) {
10685 		pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
10686 		except_cnt = le32_to_cpu(pcysta->v2.except_cnt);
10687 		exception_map = le32_to_cpu(pcysta->v2.exception);
10688 	} else if (ver->fcxcysta == 3) {
10689 		pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
10690 		except_cnt = le32_to_cpu(pcysta->v3.except_cnt);
10691 		exception_map = le32_to_cpu(pcysta->v3.except_map);
10692 	} else if (ver->fcxcysta == 4) {
10693 		pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
10694 		except_cnt = pcysta->v4.except_cnt;
10695 		exception_map = le32_to_cpu(pcysta->v4.except_map);
10696 	} else if (ver->fcxcysta == 5) {
10697 		pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
10698 		except_cnt = pcysta->v5.except_cnt;
10699 		exception_map = le32_to_cpu(pcysta->v5.except_map);
10700 	} else if (ver->fcxcysta == 7) {
10701 		pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
10702 		except_cnt = pcysta->v7.except_cnt;
10703 		exception_map = le32_to_cpu(pcysta->v7.except_map);
10704 	} else {
10705 		return 0;
10706 	}
10707 
10708 	if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 &&
10709 	    !pfwinfo->len_mismch && !pfwinfo->fver_mismch)
10710 		return 0;
10711 
10712 	p += scnprintf(p, end - p, " %-15s : ", "[error]");
10713 
10714 	if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
10715 		p += scnprintf(p, end - p,
10716 			       "overflow-cnt: %d, ",
10717 			       pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
10718 	}
10719 
10720 	if (pfwinfo->len_mismch) {
10721 		p += scnprintf(p, end - p,
10722 			       "len-mismatch: 0x%x, ",
10723 			       pfwinfo->len_mismch);
10724 	}
10725 
10726 	if (pfwinfo->fver_mismch) {
10727 		p += scnprintf(p, end - p,
10728 			       "fver-mismatch: 0x%x, ",
10729 			       pfwinfo->fver_mismch);
10730 	}
10731 
10732 	/* cycle statistics exceptions */
10733 	if (exception_map || except_cnt) {
10734 		p += scnprintf(p, end - p,
10735 			       "exception-type: 0x%x, exception-cnt = %d",
10736 			       exception_map, except_cnt);
10737 	}
10738 	p += scnprintf(p, end - p, "\n");
10739 
10740 	return p - buf;
10741 }
10742 
_show_fbtc_tdma(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10743 static int _show_fbtc_tdma(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10744 {
10745 	struct rtw89_btc *btc = &rtwdev->btc;
10746 	const struct rtw89_btc_ver *ver = btc->ver;
10747 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10748 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10749 	struct rtw89_btc_fbtc_tdma *t = NULL;
10750 	char *p = buf, *end = buf + bufsz;
10751 
10752 	pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
10753 	if (!pcinfo->valid)
10754 		return 0;
10755 
10756 	if (ver->fcxtdma == 1)
10757 		t = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
10758 	else
10759 		t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma;
10760 
10761 	p += scnprintf(p, end - p,
10762 		       " %-15s : ", "[tdma_policy]");
10763 	p += scnprintf(p, end - p,
10764 		       "type:%d, rx_flow_ctrl:%d, txflctrl:%d, ",
10765 		       (u32)t->type,
10766 		       t->rxflctrl, t->txflctrl);
10767 
10768 	p += scnprintf(p, end - p,
10769 		       "bind:%d, leak_n:%d, ext_ctrl:%d, ",
10770 		       t->bind, t->leak_n, t->ext_ctrl);
10771 
10772 	p += scnprintf(p, end - p,
10773 		       "policy_type:%d\n",
10774 		       (u32)btc->policy_type);
10775 
10776 	return p - buf;
10777 }
10778 
_show_fbtc_slots(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10779 static int _show_fbtc_slots(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10780 {
10781 	struct rtw89_btc *btc = &rtwdev->btc;
10782 	const struct rtw89_btc_ver *ver = btc->ver;
10783 	struct rtw89_btc_dm *dm = &btc->dm;
10784 	char *p = buf, *end = buf + bufsz;
10785 	u16 dur, cxtype;
10786 	u32 tbl;
10787 	u8 i = 0;
10788 
10789 	for (i = 0; i < CXST_MAX; i++) {
10790 		if (ver->fcxslots == 1) {
10791 			dur = le16_to_cpu(dm->slot_now.v1[i].dur);
10792 			tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl);
10793 			cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype);
10794 		} else if (ver->fcxslots == 2 || ver->fcxslots == 7) {
10795 			dur = le16_to_cpu(dm->slot_now.v7[i].dur);
10796 			tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl);
10797 			cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype);
10798 		} else {
10799 			return 0;
10800 		}
10801 
10802 		if (i % 5 == 0)
10803 			p += scnprintf(p, end - p,
10804 				       " %-15s : %5s[%03d/0x%x/%d]",
10805 				       "[slot_list]",
10806 				       id_to_slot((u32)i),
10807 				       dur, tbl, cxtype);
10808 		else
10809 			p += scnprintf(p, end - p,
10810 				       ", %5s[%03d/0x%x/%d]",
10811 				       id_to_slot((u32)i),
10812 				       dur, tbl, cxtype);
10813 
10814 		if (i % 5 == 4)
10815 			p += scnprintf(p, end - p, "\n");
10816 	}
10817 
10818 	return p - buf;
10819 }
10820 
_show_fbtc_cysta_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10821 static int _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10822 {
10823 	struct rtw89_btc *btc = &rtwdev->btc;
10824 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10825 	struct rtw89_btc_dm *dm = &btc->dm;
10826 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc;
10827 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10828 	struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL;
10829 	union rtw89_btc_fbtc_rxflct r;
10830 	u16 cycle, c_begin, c_end, store_index;
10831 	char *p = buf, *end = buf + bufsz;
10832 	u8 i, cnt = 0, slot_pair;
10833 
10834 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10835 	if (!pcinfo->valid)
10836 		return 0;
10837 
10838 	pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
10839 	p += scnprintf(p, end - p,
10840 		       " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
10841 		       "[cycle_cnt]",
10842 		       le16_to_cpu(pcysta_le32->cycles),
10843 		       le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]),
10844 		       le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]),
10845 		       le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]),
10846 		       le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK]));
10847 
10848 	for (i = 0; i < CXST_MAX; i++) {
10849 		if (!le32_to_cpu(pcysta_le32->slot_cnt[i]))
10850 			continue;
10851 		p += scnprintf(p, end - p, ", %s:%d", id_to_slot((u32)i),
10852 			       le32_to_cpu(pcysta_le32->slot_cnt[i]));
10853 	}
10854 
10855 	if (dm->tdma_now.rxflctrl) {
10856 		p += scnprintf(p, end - p, ", leak_rx:%d",
10857 			       le32_to_cpu(pcysta_le32->leakrx_cnt));
10858 	}
10859 
10860 	if (le32_to_cpu(pcysta_le32->collision_cnt)) {
10861 		p += scnprintf(p, end - p, ", collision:%d",
10862 			       le32_to_cpu(pcysta_le32->collision_cnt));
10863 	}
10864 
10865 	if (le32_to_cpu(pcysta_le32->skip_cnt)) {
10866 		p += scnprintf(p, end - p, ", skip:%d",
10867 			       le32_to_cpu(pcysta_le32->skip_cnt));
10868 	}
10869 	p += scnprintf(p, end - p, "\n");
10870 
10871 	p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
10872 		       "[cycle_time]",
10873 		       le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]),
10874 		       le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]),
10875 		       le16_to_cpu(pcysta_le32->tavg_lk) / 1000,
10876 		       le16_to_cpu(pcysta_le32->tavg_lk) % 1000);
10877 	p += scnprintf(p, end - p, ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
10878 		       le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]),
10879 		       le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]),
10880 		       le16_to_cpu(pcysta_le32->tmax_lk) / 1000,
10881 		       le16_to_cpu(pcysta_le32->tmax_lk) % 1000);
10882 	p += scnprintf(p, end - p, ", maxdiff_t[wl:%d/bt:%d]\n",
10883 		       le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]),
10884 		       le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT]));
10885 
10886 	if (le16_to_cpu(pcysta_le32->cycles) <= 1)
10887 		goto out;
10888 
10889 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
10890 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10891 
10892 	if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair)
10893 		c_begin = 1;
10894 	else
10895 		c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1;
10896 
10897 	c_end = le16_to_cpu(pcysta_le32->cycles);
10898 
10899 	for (cycle = c_begin; cycle <= c_end; cycle++) {
10900 		cnt++;
10901 		store_index = ((cycle - 1) % slot_pair) * 2;
10902 
10903 		if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1)
10904 			p += scnprintf(p, end - p,
10905 				       " %-15s : ->b%02d->w%02d",
10906 				       "[cycle_step]",
10907 				       le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
10908 				       le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
10909 		else
10910 			p += scnprintf(p, end - p,
10911 				       "->b%02d->w%02d",
10912 				       le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
10913 				       le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
10914 		if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
10915 			p += scnprintf(p, end - p, "\n");
10916 	}
10917 
10918 	if (a2dp->exist) {
10919 		p += scnprintf(p, end - p,
10920 			       " %-15s : a2dp_ept:%d, a2dp_late:%d",
10921 			       "[a2dp_t_sta]",
10922 			       le16_to_cpu(pcysta_le32->a2dpept),
10923 			       le16_to_cpu(pcysta_le32->a2dpeptto));
10924 
10925 		p += scnprintf(p, end - p,
10926 			       ", avg_t:%d, max_t:%d",
10927 			       le16_to_cpu(pcysta_le32->tavg_a2dpept),
10928 			       le16_to_cpu(pcysta_le32->tmax_a2dpept));
10929 		r.val = dm->tdma_now.rxflctrl;
10930 
10931 		if (r.type && r.tgln_n) {
10932 			p += scnprintf(p, end - p,
10933 				       ", cycle[PSTDMA:%d/TDMA:%d], ",
10934 				       le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]),
10935 				       le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF]));
10936 
10937 			p += scnprintf(p, end - p,
10938 				       "avg_t[PSTDMA:%d/TDMA:%d], ",
10939 				       le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]),
10940 				       le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF]));
10941 
10942 			p += scnprintf(p, end - p,
10943 				       "max_t[PSTDMA:%d/TDMA:%d]",
10944 				       le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]),
10945 				       le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF]));
10946 		}
10947 		p += scnprintf(p, end - p, "\n");
10948 	}
10949 
10950 out:
10951 	return p - buf;
10952 }
10953 
_show_fbtc_cysta_v3(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10954 static int _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10955 {
10956 	struct rtw89_btc *btc = &rtwdev->btc;
10957 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc;
10958 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10959 	struct rtw89_btc_dm *dm = &btc->dm;
10960 	struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx;
10961 	struct rtw89_btc_fbtc_cysta_v3 *pcysta;
10962 	struct rtw89_btc_rpt_cmn_info *pcinfo;
10963 	u8 i, cnt = 0, slot_pair, divide_cnt;
10964 	u16 cycle, c_begin, c_end, store_index;
10965 	char *p = buf, *end = buf + bufsz;
10966 
10967 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10968 	if (!pcinfo->valid)
10969 		return 0;
10970 
10971 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
10972 	p += scnprintf(p, end - p,
10973 		       " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
10974 		       "[cycle_cnt]",
10975 		       le16_to_cpu(pcysta->cycles),
10976 		       le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
10977 		       le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
10978 		       le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
10979 		       le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
10980 
10981 	for (i = 0; i < CXST_MAX; i++) {
10982 		if (!le32_to_cpu(pcysta->slot_cnt[i]))
10983 			continue;
10984 
10985 		p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
10986 			       le32_to_cpu(pcysta->slot_cnt[i]));
10987 	}
10988 
10989 	if (dm->tdma_now.rxflctrl)
10990 		p += scnprintf(p, end - p, ", leak_rx:%d",
10991 			       le32_to_cpu(pcysta->leak_slot.cnt_rximr));
10992 
10993 	if (le32_to_cpu(pcysta->collision_cnt))
10994 		p += scnprintf(p, end - p, ", collision:%d",
10995 			       le32_to_cpu(pcysta->collision_cnt));
10996 
10997 	if (le32_to_cpu(pcysta->skip_cnt))
10998 		p += scnprintf(p, end - p, ", skip:%d",
10999 			       le32_to_cpu(pcysta->skip_cnt));
11000 
11001 	p += scnprintf(p, end - p, "\n");
11002 
11003 	p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
11004 		       "[cycle_time]",
11005 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
11006 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
11007 		       le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
11008 		       le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
11009 	p += scnprintf(p, end - p,
11010 		       ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
11011 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
11012 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
11013 		       le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
11014 		       le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
11015 	p += scnprintf(p, end - p,
11016 		       ", maxdiff_t[wl:%d/bt:%d]\n",
11017 		       le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
11018 		       le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
11019 
11020 	cycle = le16_to_cpu(pcysta->cycles);
11021 	if (cycle <= 1)
11022 		goto out;
11023 
11024 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
11025 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
11026 
11027 	if (cycle <= slot_pair)
11028 		c_begin = 1;
11029 	else
11030 		c_begin = cycle - slot_pair + 1;
11031 
11032 	c_end = cycle;
11033 
11034 	if (a2dp->exist)
11035 		divide_cnt = 3;
11036 	else
11037 		divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
11038 
11039 	for (cycle = c_begin; cycle <= c_end; cycle++) {
11040 		cnt++;
11041 		store_index = ((cycle - 1) % slot_pair) * 2;
11042 
11043 		if (cnt % divide_cnt == 1)
11044 			p += scnprintf(p, end - p, " %-15s : ",
11045 				       "[cycle_step]");
11046 
11047 		p += scnprintf(p, end - p, "->b%02d",
11048 			       le16_to_cpu(pcysta->slot_step_time[store_index]));
11049 		if (a2dp->exist) {
11050 			a2dp_trx = &pcysta->a2dp_trx[store_index];
11051 			p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11052 				       a2dp_trx->empty_cnt,
11053 				       a2dp_trx->retry_cnt,
11054 				       a2dp_trx->tx_rate ? 3 : 2,
11055 				       a2dp_trx->tx_cnt,
11056 				       a2dp_trx->ack_cnt,
11057 				       a2dp_trx->nack_cnt);
11058 		}
11059 		p += scnprintf(p, end - p, "->w%02d",
11060 			       le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
11061 		if (a2dp->exist) {
11062 			a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
11063 			p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11064 				       a2dp_trx->empty_cnt,
11065 				       a2dp_trx->retry_cnt,
11066 				       a2dp_trx->tx_rate ? 3 : 2,
11067 				       a2dp_trx->tx_cnt,
11068 				       a2dp_trx->ack_cnt,
11069 				       a2dp_trx->nack_cnt);
11070 		}
11071 		if (cnt % divide_cnt == 0 || cnt == c_end)
11072 			p += scnprintf(p, end - p, "\n");
11073 	}
11074 
11075 	if (a2dp->exist) {
11076 		p += scnprintf(p, end - p,
11077 			       " %-15s : a2dp_ept:%d, a2dp_late:%d",
11078 			       "[a2dp_t_sta]",
11079 			       le16_to_cpu(pcysta->a2dp_ept.cnt),
11080 			       le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
11081 
11082 		p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n",
11083 			       le16_to_cpu(pcysta->a2dp_ept.tavg),
11084 			       le16_to_cpu(pcysta->a2dp_ept.tmax));
11085 	}
11086 
11087 out:
11088 	return p - buf;
11089 }
11090 
_show_fbtc_cysta_v4(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11091 static int _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11092 {
11093 	struct rtw89_btc *btc = &rtwdev->btc;
11094 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc;
11095 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11096 	struct rtw89_btc_dm *dm = &btc->dm;
11097 	struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
11098 	struct rtw89_btc_fbtc_cysta_v4 *pcysta;
11099 	struct rtw89_btc_rpt_cmn_info *pcinfo;
11100 	u8 i, cnt = 0, slot_pair, divide_cnt;
11101 	u16 cycle, c_begin, c_end, store_index;
11102 	char *p = buf, *end = buf + bufsz;
11103 
11104 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
11105 	if (!pcinfo->valid)
11106 		return 0;
11107 
11108 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
11109 	p += scnprintf(p, end - p,
11110 		       " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
11111 		       "[cycle_cnt]",
11112 		       le16_to_cpu(pcysta->cycles),
11113 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
11114 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
11115 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
11116 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
11117 
11118 	for (i = 0; i < CXST_MAX; i++) {
11119 		if (!le16_to_cpu(pcysta->slot_cnt[i]))
11120 			continue;
11121 
11122 		p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
11123 			       le16_to_cpu(pcysta->slot_cnt[i]));
11124 	}
11125 
11126 	if (dm->tdma_now.rxflctrl)
11127 		p += scnprintf(p, end - p, ", leak_rx:%d",
11128 			       le32_to_cpu(pcysta->leak_slot.cnt_rximr));
11129 
11130 	if (pcysta->collision_cnt)
11131 		p += scnprintf(p, end - p, ", collision:%d",
11132 			       pcysta->collision_cnt);
11133 
11134 	if (le16_to_cpu(pcysta->skip_cnt))
11135 		p += scnprintf(p, end - p, ", skip:%d",
11136 			       le16_to_cpu(pcysta->skip_cnt));
11137 
11138 	p += scnprintf(p, end - p, "\n");
11139 
11140 	p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
11141 		       "[cycle_time]",
11142 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
11143 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
11144 		       le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
11145 		       le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
11146 	p += scnprintf(p, end - p,
11147 		       ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
11148 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
11149 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
11150 		       le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
11151 		       le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
11152 	p += scnprintf(p, end - p,
11153 		       ", maxdiff_t[wl:%d/bt:%d]\n",
11154 		       le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
11155 		       le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
11156 
11157 	cycle = le16_to_cpu(pcysta->cycles);
11158 	if (cycle <= 1)
11159 		goto out;
11160 
11161 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
11162 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
11163 
11164 	if (cycle <= slot_pair)
11165 		c_begin = 1;
11166 	else
11167 		c_begin = cycle - slot_pair + 1;
11168 
11169 	c_end = cycle;
11170 
11171 	if (a2dp->exist)
11172 		divide_cnt = 3;
11173 	else
11174 		divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
11175 
11176 	for (cycle = c_begin; cycle <= c_end; cycle++) {
11177 		cnt++;
11178 		store_index = ((cycle - 1) % slot_pair) * 2;
11179 
11180 		if (cnt % divide_cnt == 1)
11181 			p += scnprintf(p, end - p, " %-15s : ",
11182 				       "[cycle_step]");
11183 
11184 		p += scnprintf(p, end - p, "->b%02d",
11185 			       le16_to_cpu(pcysta->slot_step_time[store_index]));
11186 		if (a2dp->exist) {
11187 			a2dp_trx = &pcysta->a2dp_trx[store_index];
11188 			p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11189 				       a2dp_trx->empty_cnt,
11190 				       a2dp_trx->retry_cnt,
11191 				       a2dp_trx->tx_rate ? 3 : 2,
11192 				       a2dp_trx->tx_cnt,
11193 				       a2dp_trx->ack_cnt,
11194 				       a2dp_trx->nack_cnt);
11195 		}
11196 		p += scnprintf(p, end - p, "->w%02d",
11197 			       le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
11198 		if (a2dp->exist) {
11199 			a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
11200 			p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11201 				       a2dp_trx->empty_cnt,
11202 				       a2dp_trx->retry_cnt,
11203 				       a2dp_trx->tx_rate ? 3 : 2,
11204 				       a2dp_trx->tx_cnt,
11205 				       a2dp_trx->ack_cnt,
11206 				       a2dp_trx->nack_cnt);
11207 		}
11208 		if (cnt % divide_cnt == 0 || cnt == c_end)
11209 			p += scnprintf(p, end - p, "\n");
11210 	}
11211 
11212 	if (a2dp->exist) {
11213 		p += scnprintf(p, end - p,
11214 			       " %-15s : a2dp_ept:%d, a2dp_late:%d",
11215 			       "[a2dp_t_sta]",
11216 			       le16_to_cpu(pcysta->a2dp_ept.cnt),
11217 			       le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
11218 
11219 		p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n",
11220 			       le16_to_cpu(pcysta->a2dp_ept.tavg),
11221 			       le16_to_cpu(pcysta->a2dp_ept.tmax));
11222 	}
11223 
11224 out:
11225 	return p - buf;
11226 }
11227 
_show_fbtc_cysta_v5(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11228 static int _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11229 {
11230 	struct rtw89_btc *btc = &rtwdev->btc;
11231 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc;
11232 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11233 	struct rtw89_btc_dm *dm = &btc->dm;
11234 	struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
11235 	struct rtw89_btc_fbtc_cysta_v5 *pcysta;
11236 	struct rtw89_btc_rpt_cmn_info *pcinfo;
11237 	u8 i, cnt = 0, slot_pair, divide_cnt;
11238 	u16 cycle, c_begin, c_end, store_index;
11239 	char *p = buf, *end = buf + bufsz;
11240 
11241 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
11242 	if (!pcinfo->valid)
11243 		return 0;
11244 
11245 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
11246 	p += scnprintf(p, end - p,
11247 		       " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
11248 		       "[cycle_cnt]",
11249 		       le16_to_cpu(pcysta->cycles),
11250 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
11251 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
11252 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
11253 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
11254 
11255 	for (i = 0; i < CXST_MAX; i++) {
11256 		if (!le16_to_cpu(pcysta->slot_cnt[i]))
11257 			continue;
11258 
11259 		p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
11260 			       le16_to_cpu(pcysta->slot_cnt[i]));
11261 	}
11262 
11263 	if (dm->tdma_now.rxflctrl)
11264 		p += scnprintf(p, end - p, ", leak_rx:%d",
11265 			       le32_to_cpu(pcysta->leak_slot.cnt_rximr));
11266 
11267 	if (pcysta->collision_cnt)
11268 		p += scnprintf(p, end - p, ", collision:%d",
11269 			       pcysta->collision_cnt);
11270 
11271 	if (le16_to_cpu(pcysta->skip_cnt))
11272 		p += scnprintf(p, end - p, ", skip:%d",
11273 			       le16_to_cpu(pcysta->skip_cnt));
11274 
11275 	p += scnprintf(p, end - p, "\n");
11276 
11277 	p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
11278 		       "[cycle_time]",
11279 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
11280 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
11281 		       le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
11282 		       le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
11283 	p += scnprintf(p, end - p,
11284 		       ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n",
11285 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
11286 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
11287 		       le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
11288 		       le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
11289 
11290 	cycle = le16_to_cpu(pcysta->cycles);
11291 	if (cycle <= 1)
11292 		goto out;
11293 
11294 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
11295 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
11296 
11297 	if (cycle <= slot_pair)
11298 		c_begin = 1;
11299 	else
11300 		c_begin = cycle - slot_pair + 1;
11301 
11302 	c_end = cycle;
11303 
11304 	if (a2dp->exist)
11305 		divide_cnt = 3;
11306 	else
11307 		divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
11308 
11309 	if (c_begin > c_end)
11310 		goto out;
11311 
11312 	for (cycle = c_begin; cycle <= c_end; cycle++) {
11313 		cnt++;
11314 		store_index = ((cycle - 1) % slot_pair) * 2;
11315 
11316 		if (cnt % divide_cnt == 1)
11317 			p += scnprintf(p, end - p, " %-15s : ",
11318 				       "[cycle_step]");
11319 
11320 		p += scnprintf(p, end - p, "->b%02d",
11321 			       le16_to_cpu(pcysta->slot_step_time[store_index]));
11322 		if (a2dp->exist) {
11323 			a2dp_trx = &pcysta->a2dp_trx[store_index];
11324 			p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11325 				       a2dp_trx->empty_cnt,
11326 				       a2dp_trx->retry_cnt,
11327 				       a2dp_trx->tx_rate ? 3 : 2,
11328 				       a2dp_trx->tx_cnt,
11329 				       a2dp_trx->ack_cnt,
11330 				       a2dp_trx->nack_cnt);
11331 		}
11332 		p += scnprintf(p, end - p, "->w%02d",
11333 			       le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
11334 		if (a2dp->exist) {
11335 			a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
11336 			p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11337 				       a2dp_trx->empty_cnt,
11338 				       a2dp_trx->retry_cnt,
11339 				       a2dp_trx->tx_rate ? 3 : 2,
11340 				       a2dp_trx->tx_cnt,
11341 				       a2dp_trx->ack_cnt,
11342 				       a2dp_trx->nack_cnt);
11343 		}
11344 		if (cnt % divide_cnt == 0 || cnt == c_end)
11345 			p += scnprintf(p, end - p, "\n");
11346 	}
11347 
11348 	if (a2dp->exist) {
11349 		p += scnprintf(p, end - p,
11350 			       " %-15s : a2dp_ept:%d, a2dp_late:%d",
11351 			       "[a2dp_t_sta]",
11352 			       le16_to_cpu(pcysta->a2dp_ept.cnt),
11353 			       le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
11354 
11355 		p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n",
11356 			       le16_to_cpu(pcysta->a2dp_ept.tavg),
11357 			       le16_to_cpu(pcysta->a2dp_ept.tmax));
11358 	}
11359 
11360 out:
11361 	return p - buf;
11362 }
11363 
_show_fbtc_cysta_v105(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11364 static int _show_fbtc_cysta_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11365 {
11366 	struct rtw89_btc *btc = &rtwdev->btc;
11367 	struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc;
11368 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11369 	struct rtw89_btc_dm *dm = &btc->dm;
11370 	struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
11371 	struct rtw89_btc_fbtc_cysta_v105 *pcysta;
11372 	struct rtw89_btc_rpt_cmn_info *pcinfo;
11373 	u8 i, cnt = 0, slot_pair, divide_cnt;
11374 	u16 cycle, c_begin, c_end, store_index;
11375 	char *p = buf, *end = buf + bufsz;
11376 
11377 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
11378 	if (!pcinfo->valid)
11379 		return 0;
11380 
11381 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v105;
11382 	p += scnprintf(p, end - p,
11383 		       " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
11384 		       "[cycle_cnt]",
11385 		       le16_to_cpu(pcysta->cycles),
11386 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
11387 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
11388 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
11389 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
11390 
11391 	for (i = 0; i < CXST_MAX; i++) {
11392 		if (!le16_to_cpu(pcysta->slot_cnt[i]))
11393 			continue;
11394 
11395 		p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
11396 			       le16_to_cpu(pcysta->slot_cnt[i]));
11397 	}
11398 
11399 	if (dm->tdma_now.rxflctrl)
11400 		p += scnprintf(p, end - p, ", leak_rx:%d",
11401 			       le32_to_cpu(pcysta->leak_slot.cnt_rximr));
11402 
11403 	if (pcysta->collision_cnt)
11404 		p += scnprintf(p, end - p, ", collision:%d",
11405 			       pcysta->collision_cnt);
11406 
11407 	if (le16_to_cpu(pcysta->skip_cnt))
11408 		p += scnprintf(p, end - p, ", skip:%d",
11409 			       le16_to_cpu(pcysta->skip_cnt));
11410 
11411 	p += scnprintf(p, end - p, "\n");
11412 
11413 	p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
11414 		       "[cycle_time]",
11415 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
11416 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
11417 		       le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
11418 		       le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
11419 	p += scnprintf(p, end - p,
11420 		       ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n",
11421 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
11422 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
11423 		       le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
11424 		       le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
11425 
11426 	cycle = le16_to_cpu(pcysta->cycles);
11427 	if (cycle <= 1)
11428 		goto out;
11429 
11430 	/* 1 cycle record 1 wl-slot and 1 bt-slot */
11431 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
11432 
11433 	if (cycle <= slot_pair)
11434 		c_begin = 1;
11435 	else
11436 		c_begin = cycle - slot_pair + 1;
11437 
11438 	c_end = cycle;
11439 
11440 	if (a2dp->exist)
11441 		divide_cnt = 3;
11442 	else
11443 		divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
11444 
11445 	if (c_begin > c_end)
11446 		goto out;
11447 
11448 	for (cycle = c_begin; cycle <= c_end; cycle++) {
11449 		cnt++;
11450 		store_index = ((cycle - 1) % slot_pair) * 2;
11451 
11452 		if (cnt % divide_cnt == 1)
11453 			p += scnprintf(p, end - p, " %-15s : ",
11454 				       "[cycle_step]");
11455 
11456 		p += scnprintf(p, end - p, "->b%02d",
11457 			       le16_to_cpu(pcysta->slot_step_time[store_index]));
11458 		if (a2dp->exist) {
11459 			a2dp_trx = &pcysta->a2dp_trx[store_index];
11460 			p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11461 				       a2dp_trx->empty_cnt,
11462 				       a2dp_trx->retry_cnt,
11463 				       a2dp_trx->tx_rate ? 3 : 2,
11464 				       a2dp_trx->tx_cnt,
11465 				       a2dp_trx->ack_cnt,
11466 				       a2dp_trx->nack_cnt);
11467 		}
11468 		p += scnprintf(p, end - p, "->w%02d",
11469 			       le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
11470 		if (a2dp->exist) {
11471 			a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
11472 			p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11473 				       a2dp_trx->empty_cnt,
11474 				       a2dp_trx->retry_cnt,
11475 				       a2dp_trx->tx_rate ? 3 : 2,
11476 				       a2dp_trx->tx_cnt,
11477 				       a2dp_trx->ack_cnt,
11478 				       a2dp_trx->nack_cnt);
11479 		}
11480 		if (cnt % divide_cnt == 0 || cnt == c_end)
11481 			p += scnprintf(p, end - p, "\n");
11482 	}
11483 
11484 	if (a2dp->exist) {
11485 		p += scnprintf(p, end - p,
11486 			       " %-15s : a2dp_ept:%d, a2dp_late:%d",
11487 			       "[a2dp_t_sta]",
11488 			       le16_to_cpu(pcysta->a2dp_ept.cnt),
11489 			       le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
11490 
11491 		p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n",
11492 			       le16_to_cpu(pcysta->a2dp_ept.tavg),
11493 			       le16_to_cpu(pcysta->a2dp_ept.tmax));
11494 	}
11495 
11496 out:
11497 	return p - buf;
11498 }
11499 
_show_fbtc_cysta_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11500 static int _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11501 {
11502 	struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt0;
11503 	struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc;
11504 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
11505 	struct rtw89_btc_fbtc_cysta_v7 *pcysta = NULL;
11506 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
11507 	struct rtw89_btc_rpt_cmn_info *pcinfo;
11508 	char *p = buf, *end = buf + bufsz;
11509 	u16 cycle, c_begin, c_end, s_id;
11510 	u8 i, cnt = 0, divide_cnt;
11511 	u8 slot_pair;
11512 
11513 	pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
11514 	if (!pcinfo->valid)
11515 		return 0;
11516 
11517 	pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
11518 	p += scnprintf(p, end - p, "\n %-15s : cycle:%d", "[slot_stat]",
11519 		       le16_to_cpu(pcysta->cycles));
11520 
11521 	for (i = 0; i < CXST_MAX; i++) {
11522 		if (!le16_to_cpu(pcysta->slot_cnt[i]))
11523 			continue;
11524 		p += scnprintf(p, end - p, ", %s:%d",
11525 			       id_to_slot(i),
11526 			       le16_to_cpu(pcysta->slot_cnt[i]));
11527 	}
11528 
11529 	if (dm->tdma_now.rxflctrl)
11530 		p += scnprintf(p, end - p, ", leak_rx:%d",
11531 			       le32_to_cpu(pcysta->leak_slot.cnt_rximr));
11532 
11533 	if (pcysta->collision_cnt)
11534 		p += scnprintf(p, end - p, ", collision:%d",
11535 			       pcysta->collision_cnt);
11536 
11537 	if (pcysta->skip_cnt)
11538 		p += scnprintf(p, end - p, ", skip:%d",
11539 			       le16_to_cpu(pcysta->skip_cnt));
11540 
11541 	p += scnprintf(p, end - p,
11542 		       "\n %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
11543 		       "[cycle_stat]",
11544 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
11545 		       le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
11546 		       le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
11547 		       le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
11548 	p += scnprintf(p, end - p,
11549 		       ", max_t[wl:%d/bt:%d(>%dms:%d)/lk:%d.%03d]",
11550 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
11551 		       le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
11552 		       dm->bt_slot_flood, dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD],
11553 		       le16_to_cpu(pcysta->leak_slot.tamx) / 1000,
11554 		       le16_to_cpu(pcysta->leak_slot.tamx) % 1000);
11555 	p += scnprintf(p, end - p, ", bcn[all:%d/ok:%d/in_bt:%d/in_bt_ok:%d]",
11556 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
11557 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
11558 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
11559 		       le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
11560 
11561 	if (a2dp->exist) {
11562 		p += scnprintf(p, end - p,
11563 			       "\n %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)",
11564 			       "[a2dp_stat]",
11565 			       le16_to_cpu(pcysta->a2dp_ept.cnt),
11566 			       le16_to_cpu(pcysta->a2dp_ept.cnt_timeout),
11567 			       a2dp->no_empty_streak_2s,
11568 			       a2dp->no_empty_streak_max);
11569 
11570 		p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
11571 			       le16_to_cpu(pcysta->a2dp_ept.tavg),
11572 			       le16_to_cpu(pcysta->a2dp_ept.tmax));
11573 	}
11574 
11575 	if (le16_to_cpu(pcysta->cycles) <= 1)
11576 		goto out;
11577 
11578 	/* 1 cycle = 1 wl-slot + 1 bt-slot */
11579 	slot_pair = BTC_CYCLE_SLOT_MAX / 2;
11580 
11581 	if (le16_to_cpu(pcysta->cycles) <= slot_pair)
11582 		c_begin = 1;
11583 	else
11584 		c_begin = le16_to_cpu(pcysta->cycles) - slot_pair + 1;
11585 
11586 	c_end = le16_to_cpu(pcysta->cycles);
11587 
11588 	if (a2dp->exist)
11589 		divide_cnt = 2;
11590 	else
11591 		divide_cnt = 6;
11592 
11593 	if (c_begin > c_end)
11594 		goto out;
11595 
11596 	for (cycle = c_begin; cycle <= c_end; cycle++) {
11597 		cnt++;
11598 		s_id = ((cycle - 1) % slot_pair) * 2;
11599 
11600 		if (cnt % divide_cnt == 1) {
11601 			if (a2dp->exist)
11602 				p += scnprintf(p, end - p, "\n %-15s : ",
11603 					       "[slotT_wermtan]");
11604 			else
11605 				p += scnprintf(p, end - p, "\n %-15s : ",
11606 					       "[slotT_rxerr]");
11607 		}
11608 
11609 		p += scnprintf(p, end - p, "->b%d",
11610 			       le16_to_cpu(pcysta->slot_step_time[s_id]));
11611 
11612 		if (a2dp->exist)
11613 			p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)",
11614 				       pcysta->wl_rx_err_ratio[s_id],
11615 				       pcysta->a2dp_trx[s_id].empty_cnt,
11616 				       pcysta->a2dp_trx[s_id].retry_cnt,
11617 				       (pcysta->a2dp_trx[s_id].tx_rate ? 3 : 2),
11618 				       pcysta->a2dp_trx[s_id].tx_cnt,
11619 				       pcysta->a2dp_trx[s_id].ack_cnt,
11620 				       pcysta->a2dp_trx[s_id].nack_cnt);
11621 		else
11622 			p += scnprintf(p, end - p, "(%d)",
11623 				       pcysta->wl_rx_err_ratio[s_id]);
11624 
11625 		p += scnprintf(p, end - p, "->w%d",
11626 			       le16_to_cpu(pcysta->slot_step_time[s_id + 1]));
11627 
11628 		if (a2dp->exist)
11629 			p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)",
11630 				       pcysta->wl_rx_err_ratio[s_id + 1],
11631 				       pcysta->a2dp_trx[s_id + 1].empty_cnt,
11632 				       pcysta->a2dp_trx[s_id + 1].retry_cnt,
11633 				       (pcysta->a2dp_trx[s_id + 1].tx_rate ? 3 : 2),
11634 				       pcysta->a2dp_trx[s_id + 1].tx_cnt,
11635 				       pcysta->a2dp_trx[s_id + 1].ack_cnt,
11636 				       pcysta->a2dp_trx[s_id + 1].nack_cnt);
11637 		else
11638 			p += scnprintf(p, end - p, "(%d)",
11639 				       pcysta->wl_rx_err_ratio[s_id + 1]);
11640 	}
11641 
11642 out:
11643 	return p - buf;
11644 }
11645 
_show_fbtc_nullsta(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11646 static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11647 {
11648 	struct rtw89_btc *btc = &rtwdev->btc;
11649 	const struct rtw89_btc_ver *ver = btc->ver;
11650 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11651 	struct rtw89_btc_rpt_cmn_info *pcinfo;
11652 	union rtw89_btc_fbtc_cynullsta_info *ns;
11653 	char *p = buf, *end = buf + bufsz;
11654 	u8 i = 0;
11655 
11656 	if (!btc->dm.tdma_now.rxflctrl)
11657 		return 0;
11658 
11659 	pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
11660 	if (!pcinfo->valid)
11661 		return 0;
11662 
11663 	ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
11664 	if (ver->fcxnullsta == 1) {
11665 		for (i = 0; i < 2; i++) {
11666 			p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]");
11667 			p += scnprintf(p, end - p, "null-%d", i);
11668 			p += scnprintf(p, end - p, "[ok:%d/",
11669 				       le32_to_cpu(ns->v1.result[i][1]));
11670 			p += scnprintf(p, end - p, "fail:%d/",
11671 				       le32_to_cpu(ns->v1.result[i][0]));
11672 			p += scnprintf(p, end - p, "on_time:%d/",
11673 				       le32_to_cpu(ns->v1.result[i][2]));
11674 			p += scnprintf(p, end - p, "retry:%d/",
11675 				       le32_to_cpu(ns->v1.result[i][3]));
11676 			p += scnprintf(p, end - p, "avg_t:%d.%03d/",
11677 				       le32_to_cpu(ns->v1.avg_t[i]) / 1000,
11678 				       le32_to_cpu(ns->v1.avg_t[i]) % 1000);
11679 			p += scnprintf(p, end - p, "max_t:%d.%03d]",
11680 				       le32_to_cpu(ns->v1.max_t[i]) / 1000,
11681 				       le32_to_cpu(ns->v1.max_t[i]) % 1000);
11682 		}
11683 	} else if (ver->fcxnullsta == 7) {
11684 		for (i = 0; i < 2; i++) {
11685 			p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]");
11686 			p += scnprintf(p, end - p, "null-%d", i);
11687 			p += scnprintf(p, end - p, "[Tx:%d/",
11688 				       le32_to_cpu(ns->v7.result[i][4]));
11689 			p += scnprintf(p, end - p, "[ok:%d/",
11690 				       le32_to_cpu(ns->v7.result[i][1]));
11691 			p += scnprintf(p, end - p, "fail:%d/",
11692 				       le32_to_cpu(ns->v7.result[i][0]));
11693 			p += scnprintf(p, end - p, "on_time:%d/",
11694 				       le32_to_cpu(ns->v7.result[i][2]));
11695 			p += scnprintf(p, end - p, "retry:%d/",
11696 				       le32_to_cpu(ns->v7.result[i][3]));
11697 			p += scnprintf(p, end - p, "avg_t:%d.%03d/",
11698 				       le32_to_cpu(ns->v7.tavg[i]) / 1000,
11699 				       le32_to_cpu(ns->v7.tavg[i]) % 1000);
11700 			p += scnprintf(p, end - p, "max_t:%d.%03d]",
11701 				       le32_to_cpu(ns->v7.tmax[i]) / 1000,
11702 				       le32_to_cpu(ns->v7.tmax[i]) % 1000);
11703 		}
11704 	} else {
11705 		for (i = 0; i < 2; i++) {
11706 			p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]");
11707 			p += scnprintf(p, end - p, "null-%d", i);
11708 			p += scnprintf(p, end - p, "[Tx:%d/",
11709 				       le32_to_cpu(ns->v2.result[i][4]));
11710 			p += scnprintf(p, end - p, "[ok:%d/",
11711 				       le32_to_cpu(ns->v2.result[i][1]));
11712 			p += scnprintf(p, end - p, "fail:%d/",
11713 				       le32_to_cpu(ns->v2.result[i][0]));
11714 			p += scnprintf(p, end - p, "on_time:%d/",
11715 				       le32_to_cpu(ns->v2.result[i][2]));
11716 			p += scnprintf(p, end - p, "retry:%d/",
11717 				       le32_to_cpu(ns->v2.result[i][3]));
11718 			p += scnprintf(p, end - p, "avg_t:%d.%03d/",
11719 				       le32_to_cpu(ns->v2.avg_t[i]) / 1000,
11720 				       le32_to_cpu(ns->v2.avg_t[i]) % 1000);
11721 			p += scnprintf(p, end - p, "max_t:%d.%03d]",
11722 				       le32_to_cpu(ns->v2.max_t[i]) / 1000,
11723 				       le32_to_cpu(ns->v2.max_t[i]) % 1000);
11724 		}
11725 	}
11726 
11727 	return p - buf;
11728 }
11729 
_show_fbtc_step_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11730 static int _show_fbtc_step_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11731 {
11732 	struct rtw89_btc *btc = &rtwdev->btc;
11733 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11734 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11735 	struct rtw89_btc_fbtc_steps_v2 *pstep = NULL;
11736 	const struct rtw89_btc_ver *ver = btc->ver;
11737 	char *p = buf, *end = buf + bufsz;
11738 	u8 type, val, cnt = 0, state = 0;
11739 	bool outloop = false;
11740 	u16 i, diff_t, n_start = 0, n_stop = 0;
11741 	u16 pos_old, pos_new, trace_step;
11742 
11743 	pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
11744 	if (!pcinfo->valid)
11745 		return 0;
11746 
11747 	pstep = &pfwinfo->rpt_fbtc_step.finfo.v2;
11748 	pos_old = le16_to_cpu(pstep->pos_old);
11749 	pos_new = le16_to_cpu(pstep->pos_new);
11750 
11751 	if (pcinfo->req_fver != pstep->fver)
11752 		return 0;
11753 
11754 	/* store step info by using ring instead of FIFO*/
11755 	do {
11756 		switch (state) {
11757 		case 0:
11758 			if (ver->fcxctrl == 7 || ver->fcxctrl == 1)
11759 				trace_step = 50;
11760 			else
11761 				trace_step = btc->ctrl.trace_step;
11762 
11763 			n_start = pos_old;
11764 			if (pos_new >=  pos_old)
11765 				n_stop = pos_new;
11766 			else
11767 				n_stop = trace_step - 1;
11768 
11769 			state = 1;
11770 			break;
11771 		case 1:
11772 			for (i = n_start; i <= n_stop; i++) {
11773 				type = pstep->step[i].type;
11774 				val = pstep->step[i].val;
11775 				diff_t = le16_to_cpu(pstep->step[i].difft);
11776 
11777 				if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
11778 					continue;
11779 
11780 				if (cnt % 10 == 0)
11781 					p += scnprintf(p, end - p,
11782 						       " %-15s : ", "[steps]");
11783 
11784 				p += scnprintf(p, end - p,
11785 					       "-> %s(%02d)(%02d)",
11786 					       (type == CXSTEP_SLOT ? "SLT" :
11787 						"EVT"), (u32)val, diff_t);
11788 				if (cnt % 10 == 9)
11789 					p += scnprintf(p, end - p, "\n");
11790 				cnt++;
11791 			}
11792 
11793 			state = 2;
11794 			break;
11795 		case 2:
11796 			if (pos_new <  pos_old && n_start != 0) {
11797 				n_start = 0;
11798 				n_stop = pos_new;
11799 				state = 1;
11800 			} else {
11801 				outloop = true;
11802 			}
11803 			break;
11804 		}
11805 	} while (!outloop);
11806 
11807 	return p - buf;
11808 }
11809 
_show_fbtc_step_v3(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11810 static int _show_fbtc_step_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11811 {
11812 	struct rtw89_btc *btc = &rtwdev->btc;
11813 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11814 	struct rtw89_btc_rpt_cmn_info *pcinfo;
11815 	struct rtw89_btc_fbtc_steps_v3 *pstep;
11816 	u32 i, n_begin, n_end, array_idx, cnt = 0;
11817 	char *p = buf, *end = buf + bufsz;
11818 	u8 type, val;
11819 	u16 diff_t;
11820 
11821 	if ((pfwinfo->rpt_en_map &
11822 	     rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0)
11823 		return 0;
11824 
11825 	pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
11826 	if (!pcinfo->valid)
11827 		return 0;
11828 
11829 	pstep = &pfwinfo->rpt_fbtc_step.finfo.v3;
11830 	if (pcinfo->req_fver != pstep->fver)
11831 		return 0;
11832 
11833 	if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP)
11834 		n_begin = 1;
11835 	else
11836 		n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1;
11837 
11838 	n_end = le32_to_cpu(pstep->cnt);
11839 
11840 	if (n_begin > n_end)
11841 		return 0;
11842 
11843 	/* restore step info by using ring instead of FIFO */
11844 	for (i = n_begin; i <= n_end; i++) {
11845 		array_idx = (i - 1) % FCXDEF_STEP;
11846 		type = pstep->step[array_idx].type;
11847 		val = pstep->step[array_idx].val;
11848 		diff_t = le16_to_cpu(pstep->step[array_idx].difft);
11849 
11850 		if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
11851 			continue;
11852 
11853 		if (cnt % 10 == 0)
11854 			p += scnprintf(p, end - p, " %-15s : ", "[steps]");
11855 
11856 		p += scnprintf(p, end - p, "-> %s(%02d)",
11857 			       (type == CXSTEP_SLOT ?
11858 				id_to_slot((u32)val) :
11859 				id_to_evt((u32)val)), diff_t);
11860 
11861 		if (cnt % 10 == 9)
11862 			p += scnprintf(p, end - p, "\n");
11863 
11864 		cnt++;
11865 	}
11866 
11867 	return p - buf;
11868 }
11869 
_show_fw_dm_msg(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11870 static int _show_fw_dm_msg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11871 {
11872 	struct rtw89_btc *btc = &rtwdev->btc;
11873 	const struct rtw89_btc_ver *ver = btc->ver;
11874 	char *p = buf, *end = buf + bufsz;
11875 
11876 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
11877 		goto out;
11878 
11879 	p += _show_error(rtwdev, p, end - p);
11880 	p += _show_fbtc_tdma(rtwdev, p, end - p);
11881 	p += _show_fbtc_slots(rtwdev, p, end - p);
11882 
11883 	if (ver->fcxcysta == 2)
11884 		p += _show_fbtc_cysta_v2(rtwdev, p, end - p);
11885 	else if (ver->fcxcysta == 3)
11886 		p += _show_fbtc_cysta_v3(rtwdev, p, end - p);
11887 	else if (ver->fcxcysta == 4)
11888 		p += _show_fbtc_cysta_v4(rtwdev, p, end - p);
11889 	else if (ver->fcxcysta == 5)
11890 		p += _show_fbtc_cysta_v5(rtwdev, p, end - p);
11891 	else if (ver->fcxcysta == 105)
11892 		p += _show_fbtc_cysta_v105(rtwdev, p, end - p);
11893 	else if (ver->fcxcysta == 7)
11894 		p += _show_fbtc_cysta_v7(rtwdev, p, end - p);
11895 
11896 	p += _show_fbtc_nullsta(rtwdev, p, end - p);
11897 
11898 	if (ver->fcxstep == 2)
11899 		p += _show_fbtc_step_v2(rtwdev, p, end - p);
11900 	else if (ver->fcxstep == 3)
11901 		p += _show_fbtc_step_v3(rtwdev, p, end - p);
11902 
11903 out:
11904 	return p - buf;
11905 }
11906 
_get_gnt(struct rtw89_dev * rtwdev,struct rtw89_mac_ax_coex_gnt * gnt_cfg)11907 static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg)
11908 {
11909 	const struct rtw89_chip_info *chip = rtwdev->chip;
11910 	struct rtw89_mac_ax_wl_act *bt;
11911 	struct rtw89_mac_ax_gnt *gnt;
11912 	u32 val, status;
11913 
11914 	if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B ||
11915 	    chip->chip_id == RTL8851B || chip->chip_id == RTL8852BT) {
11916 		rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
11917 		rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status);
11918 
11919 		gnt = &gnt_cfg->band[0];
11920 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL);
11921 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA);
11922 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL);
11923 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA);
11924 
11925 		gnt = &gnt_cfg->band[1];
11926 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL);
11927 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA);
11928 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL);
11929 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA);
11930 	} else if (chip->chip_id == RTL8852C) {
11931 		val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL);
11932 		status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1);
11933 
11934 		gnt = &gnt_cfg->band[0];
11935 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL);
11936 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0);
11937 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL);
11938 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0);
11939 
11940 		gnt = &gnt_cfg->band[1];
11941 		gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL);
11942 		gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1);
11943 		gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL);
11944 		gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1);
11945 
11946 		bt = &gnt_cfg->bt[0];
11947 		bt->wlan_act_en = !!(val & B_BE_WL_ACT_SWCTRL);
11948 		bt->wlan_act = !!(status & B_BE_WL_ACT_VAL);
11949 
11950 		bt = &gnt_cfg->bt[1];
11951 		bt->wlan_act_en = !!(val & B_BE_WL_ACT2_SWCTRL);
11952 		bt->wlan_act = !!(status & B_BE_WL_ACT2_VAL);
11953 	} else if (chip->chip_id == RTL8922A) {
11954 		val = rtw89_read32(rtwdev, R_BE_GNT_SW_CTRL);
11955 		status = rtw89_read32(rtwdev, R_BE_PTA_GNT_VAL);
11956 
11957 		gnt = &gnt_cfg->band[0];
11958 		gnt->gnt_bt_sw_en = !!(val & B_BE_GNT_BT_BB0_SWCTRL);
11959 		gnt->gnt_bt = !!(status & B_BE_GNT_BT_BB0_VAL);
11960 		gnt->gnt_wl_sw_en = !!(val & B_BE_GNT_WL_BB0_SWCTRL);
11961 		gnt->gnt_wl = !!(status & B_BE_GNT_WL_BB0_VAL);
11962 
11963 		gnt = &gnt_cfg->band[1];
11964 		gnt->gnt_bt_sw_en = !!(val & B_BE_GNT_BT_BB1_SWCTRL);
11965 		gnt->gnt_bt = !!(status & B_BE_GNT_BT_BB1_VAL);
11966 		gnt->gnt_wl_sw_en = !!(val & B_BE_GNT_WL_BB1_SWCTRL);
11967 		gnt->gnt_wl = !!(status & B_BE_GNT_WL_BB1_VAL);
11968 
11969 		bt = &gnt_cfg->bt[0];
11970 		bt->wlan_act_en = !!(val & B_BE_WL_ACT_SWCTRL);
11971 		bt->wlan_act = !!(status & B_BE_WL_ACT_VAL);
11972 
11973 		bt = &gnt_cfg->bt[1];
11974 		bt->wlan_act_en = !!(val & B_BE_WL_ACT2_SWCTRL);
11975 		bt->wlan_act = !!(status & B_BE_WL_ACT2_VAL);
11976 	} else if (chip->chip_id == RTL8922D) {
11977 		/* Get from firmware */
11978 		return;
11979 	}
11980 }
11981 
_show_gpio_dbg(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11982 static int _show_gpio_dbg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11983 {
11984 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
11985 	const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
11986 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11987 	union rtw89_btc_fbtc_gpio_dbg *gdbg = NULL;
11988 	char *p = buf, *end = buf + bufsz;
11989 	u32 en_map_raw, en_map;
11990 	u8 *gpio_map, i, sig;
11991 
11992 	pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
11993 	gdbg = &rtwdev->btc.fwinfo.rpt_fbtc_gpio_dbg.finfo;
11994 	if (!pcinfo->valid) {
11995 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
11996 			    "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n",
11997 			    __func__);
11998 		goto out;
11999 	}
12000 
12001 	if (ver->fcxgpiodbg == 7 || ver->fcxgpiodbg == 8) {
12002 		en_map_raw = le32_to_cpu(gdbg->v7.en_map);
12003 		gpio_map = gdbg->v7.gpio_map;
12004 	} else {
12005 		en_map_raw = le32_to_cpu(gdbg->v1.en_map);
12006 		gpio_map = gdbg->v1.gpio_map;
12007 	}
12008 
12009 	en_map = _convert_gpio_enmap_from_ver(rtwdev, en_map_raw);
12010 	if (!en_map)
12011 		goto out;
12012 
12013 	p += scnprintf(p, end - p, "\n %-15s : enable_map:0x%08x",
12014 		       "[gpio_dbg]", en_map);
12015 
12016 	for (i = 0; i < BTC_DBG_NUM; i++) {
12017 		if (!(en_map & BIT(i)))
12018 			continue;
12019 
12020 		sig = ver->fcxgpiodbg >= 8 ? i : _get_gpiosig_for_ver(rtwdev, i);
12021 		if (sig >= BTC_DBG_NUM)
12022 			continue;
12023 
12024 		p += scnprintf(p, end - p, ", %s->GPIO%d", id_to_gdbg(i),
12025 			       gpio_map[sig]);
12026 	}
12027 
12028 out:
12029 	return p - buf;
12030 }
12031 
_show_mreg_v1(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12032 static int _show_mreg_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12033 {
12034 	const struct rtw89_chip_info *chip = rtwdev->chip;
12035 	struct rtw89_btc *btc = &rtwdev->btc;
12036 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
12037 	struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL;
12038 	struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0;
12039 	struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1;
12040 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
12041 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
12042 	struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
12043 	struct rtw89_mac_ax_gnt gnt;
12044 	char *p = buf, *end = buf + bufsz;
12045 	u8 i = 0, type = 0, cnt = 0;
12046 	u32 val, offset;
12047 
12048 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
12049 		return 0;
12050 
12051 	p += scnprintf(p, end - p, "========== [HW Status] ==========\n");
12052 
12053 	p += scnprintf(p, end - p,
12054 		       " %-15s : WL->BT0:0x%08x(cnt:%d), BT0->WL:0x%08x(total:%d, bt_update:%d)\n",
12055 		       "[scoreboard]", wl->scbd[BTC_BT_1ST],
12056 		       wl->wcnt[BTC_WCNT_SCBDUPDATE],
12057 		       bt0->scbd, bt0->bcnt[BTC_BCNT_SCBDREAD],
12058 		       bt0->bcnt[BTC_BCNT_SCBDUPDATE]);
12059 
12060 	if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) {
12061 		p += scnprintf(p, end - p,
12062 			       " %-15s : WL->BT1:0x%08x(cnt:%d), BT1->WL:0x%08x(total:%d, bt_update:%d)\n",
12063 			       "[scoreboard]", wl->scbd[BTC_BT_2ND],
12064 			       wl->wcnt[BTC_WCNT_SCBDUPDATE2],
12065 			       bt1->scbd, bt1->bcnt[BTC_BCNT_SCBDREAD],
12066 			       bt1->bcnt[BTC_BCNT_SCBDUPDATE]);
12067 	}
12068 
12069 	btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
12070 	_get_gnt(rtwdev, &gnt_cfg);
12071 
12072 	gnt = gnt_cfg.band[0];
12073 	p += scnprintf(p, end - p,
12074 		       " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
12075 		       "[gnt_status]",
12076 		       chip->chip_id == RTL8852C ? "HW" :
12077 		       btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
12078 		       gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
12079 		       gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt);
12080 
12081 	gnt = gnt_cfg.band[1];
12082 	p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
12083 		       gnt.gnt_wl_sw_en ? "SW" : "HW",
12084 		       gnt.gnt_wl,
12085 		       gnt.gnt_bt_sw_en ? "SW" : "HW",
12086 		       gnt.gnt_bt);
12087 
12088 	pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
12089 	if (!pcinfo->valid) {
12090 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
12091 			    "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
12092 			    __func__);
12093 		goto out;
12094 	}
12095 
12096 	pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
12097 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
12098 		    "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
12099 		    __func__, pmreg->reg_num);
12100 
12101 	for (i = 0; i < pmreg->reg_num; i++) {
12102 		type = (u8)le16_to_cpu(chip->mon_reg[i].type);
12103 		offset = le32_to_cpu(chip->mon_reg[i].offset);
12104 		val = le32_to_cpu(pmreg->mreg_val[i]);
12105 
12106 		if (cnt % 6 == 0)
12107 			p += scnprintf(p, end - p,
12108 				       " %-15s : %d_0x%04x=0x%08x",
12109 				       "[reg]", (u32)type, offset, val);
12110 		else
12111 			p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x",
12112 				       (u32)type,
12113 				       offset, val);
12114 		if (cnt % 6 == 5)
12115 			p += scnprintf(p, end - p, "\n");
12116 		cnt++;
12117 
12118 		if (i >= pmreg->reg_num)
12119 			p += scnprintf(p, end - p, "\n");
12120 	}
12121 
12122 out:
12123 	return p - buf;
12124 }
12125 
_show_mreg_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12126 static int _show_mreg_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12127 {
12128 	const struct rtw89_chip_info *chip = rtwdev->chip;
12129 	struct rtw89_btc *btc = &rtwdev->btc;
12130 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
12131 	struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL;
12132 	struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0;
12133 	struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1;
12134 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
12135 	struct rtw89_btc_wl_info *wl = &btc->cx.wl;
12136 	struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
12137 	struct rtw89_mac_ax_gnt gnt;
12138 	char *p = buf, *end = buf + bufsz;
12139 	u8 i = 0, type = 0, cnt = 0;
12140 	u32 val, offset;
12141 
12142 	if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
12143 		return 0;
12144 
12145 	p += scnprintf(p, end - p, "========== [HW Status] ==========\n");
12146 
12147 	p += scnprintf(p, end - p,
12148 		       " %-15s : WL->BT0:0x%08x(cnt:%d), BT0->WL:0x%08x(total:%d, bt_update:%d)\n",
12149 		       "[scoreboard]", wl->scbd[BTC_BT_1ST],
12150 		       wl->wcnt[BTC_WCNT_SCBDUPDATE],
12151 		       bt0->scbd, bt0->bcnt[BTC_BCNT_SCBDREAD],
12152 		       bt0->bcnt[BTC_BCNT_SCBDUPDATE]);
12153 
12154 	if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) {
12155 		p += scnprintf(p, end - p,
12156 			       " %-15s : WL->BT1:0x%08x(cnt:%d), BT1->WL:0x%08x(total:%d, bt_update:%d)\n",
12157 			       "[scoreboard]", wl->scbd[BTC_BT_2ND],
12158 			       wl->wcnt[BTC_WCNT_SCBDUPDATE2],
12159 			       bt1->scbd, bt1->bcnt[BTC_BCNT_SCBDREAD],
12160 			       bt1->bcnt[BTC_BCNT_SCBDUPDATE]);
12161 	}
12162 
12163 	btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
12164 	_get_gnt(rtwdev, &gnt_cfg);
12165 
12166 	gnt = gnt_cfg.band[0];
12167 	p += scnprintf(p, end - p,
12168 		       " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], polut_type:%s",
12169 		       "[gnt_status]",
12170 		       chip->chip_id == RTL8852C ? "HW" :
12171 		       btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
12172 		       gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
12173 		       gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt,
12174 		       id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
12175 
12176 	gnt = gnt_cfg.band[1];
12177 	p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
12178 		       gnt.gnt_wl_sw_en ? "SW" : "HW",
12179 		       gnt.gnt_wl,
12180 		       gnt.gnt_bt_sw_en ? "SW" : "HW",
12181 		       gnt.gnt_bt);
12182 
12183 	pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
12184 	if (!pcinfo->valid) {
12185 		rtw89_debug(rtwdev, RTW89_DBG_BTC,
12186 			    "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
12187 			    __func__);
12188 		goto out;
12189 	}
12190 
12191 	pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
12192 	rtw89_debug(rtwdev, RTW89_DBG_BTC,
12193 		    "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
12194 		    __func__, pmreg->reg_num);
12195 
12196 	for (i = 0; i < pmreg->reg_num; i++) {
12197 		type = (u8)le16_to_cpu(chip->mon_reg[i].type);
12198 		offset = le32_to_cpu(chip->mon_reg[i].offset);
12199 		val = le32_to_cpu(pmreg->mreg_val[i]);
12200 
12201 		if (cnt % 6 == 0)
12202 			p += scnprintf(p, end - p,
12203 				       " %-15s : %d_0x%04x=0x%08x",
12204 				       "[reg]", (u32)type, offset, val);
12205 		else
12206 			p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x",
12207 				       (u32)type,
12208 				       offset, val);
12209 		if (cnt % 6 == 5)
12210 			p += scnprintf(p, end - p, "\n");
12211 		cnt++;
12212 
12213 		if (i >= pmreg->reg_num)
12214 			p += scnprintf(p, end - p, "\n");
12215 	}
12216 
12217 out:
12218 	return p - buf;
12219 }
12220 
_show_mreg_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12221 static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12222 {
12223 	struct rtw89_btc *btc = &rtwdev->btc;
12224 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
12225 	struct rtw89_btc_fbtc_mreg_val_v7 *pmreg = NULL;
12226 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
12227 	struct rtw89_btc_cx *cx = &btc->cx;
12228 	struct rtw89_btc_bt_info *bt0 = &cx->bt0;
12229 	struct rtw89_btc_bt_info *bt1 = &cx->bt1;
12230 	struct rtw89_btc_wl_info *wl = &cx->wl;
12231 	struct rtw89_btc_dm *dm = &btc->dm;
12232 	char *p = buf, *end = buf + bufsz;
12233 	u8 i, type, cnt = 0;
12234 	u32 val, offset;
12235 
12236 	if (!(dm->coex_info_map & BTC_COEX_INFO_MREG))
12237 		return 0;
12238 
12239 	p += scnprintf(p, end - p, "\n========== [HW Status] ==========\n");
12240 
12241 	p += scnprintf(p, end - p,
12242 		       " %-15s : WL->BT0:0x%08x(cnt:%d), BT0->WL:0x%08x(total:%d, bt_update:%d)\n",
12243 		       "[scoreboard]", wl->scbd[BTC_BT_1ST],
12244 		       wl->wcnt[BTC_WCNT_SCBDUPDATE],
12245 		       bt0->scbd, bt0->bcnt[BTC_BCNT_SCBDREAD],
12246 		       bt0->bcnt[BTC_BCNT_SCBDUPDATE]);
12247 
12248 	if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) {
12249 		p += scnprintf(p, end - p,
12250 			       " %-15s : WL->BT1:0x%08x(cnt:%d), BT1->WL:0x%08x(total:%d, bt_update:%d)\n",
12251 			       "[scoreboard]", wl->scbd[BTC_BT_2ND],
12252 			       wl->wcnt[BTC_WCNT_SCBDUPDATE2],
12253 			       bt1->scbd, bt1->bcnt[BTC_BCNT_SCBDREAD],
12254 			       bt1->bcnt[BTC_BCNT_SCBDUPDATE]);
12255 	}
12256 
12257 	/* To avoid I/O if WL LPS or power-off  */
12258 	dm->pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
12259 
12260 	p += scnprintf(p, end - p,
12261 		       " %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s\n",
12262 		       "[gnt_status]",
12263 		       rtwdev->chip->para_ver & BTC_FEAT_PTA_ONOFF_CTRL ? "HW" :
12264 		       dm->pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
12265 		       wl->pta_req_mac,
12266 		       id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
12267 
12268 	if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)
12269 		p += scnprintf(p, end - p,
12270 			       " %-15s : phy-0[gnt_wl:%s-%d/gnt_bt0:%s-%d/gnt_bt1:%s-%d]",
12271 			       "[gnt_status]",
12272 			       dm->gnt_set[RTW89_PHY_0].gnt_wl_sw_en ? "SW" : "HW",
12273 			       dm->gnt_set[RTW89_PHY_0].gnt_wl,
12274 			       dm->gnt_set[RTW89_PHY_0].gnt_bt0_sw_en ? "SW" : "HW",
12275 			       dm->gnt_set[RTW89_PHY_0].gnt_bt0,
12276 			       dm->gnt_set[RTW89_PHY_0].gnt_bt1_sw_en ? "SW" : "HW",
12277 			       dm->gnt_set[RTW89_PHY_0].gnt_bt1);
12278 	else
12279 		p += scnprintf(p, end - p,
12280 			       " %-15s : phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]",
12281 			       "[gnt_status]",
12282 			       dm->gnt_set[RTW89_PHY_0].gnt_wl_sw_en ? "SW" : "HW",
12283 			       dm->gnt_set[RTW89_PHY_0].gnt_wl,
12284 			       dm->gnt_set[RTW89_PHY_0].gnt_bt0_sw_en ? "SW" : "HW",
12285 			       dm->gnt_set[RTW89_PHY_0].gnt_bt0);
12286 
12287 	if (rtwdev->dbcc_en) {
12288 		if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)
12289 			p += scnprintf(p, end - p,
12290 				       ", phy-1[gnt_wl:%s-%d/gnt_bt0:%s-%d/gnt_bt1:%s-%d]",
12291 				       dm->gnt_set[RTW89_PHY_1].gnt_wl_sw_en ? "SW" : "HW",
12292 				       dm->gnt_set[RTW89_PHY_1].gnt_wl,
12293 				       dm->gnt_set[RTW89_PHY_1].gnt_bt0_sw_en ? "SW" : "HW",
12294 				       dm->gnt_set[RTW89_PHY_1].gnt_bt0,
12295 				       dm->gnt_set[RTW89_PHY_1].gnt_bt1_sw_en ? "SW" : "HW",
12296 				       dm->gnt_set[RTW89_PHY_1].gnt_bt1);
12297 		else
12298 			p += scnprintf(p, end - p,
12299 				       ", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]",
12300 				       dm->gnt_set[RTW89_PHY_1].gnt_wl_sw_en ? "SW" : "HW",
12301 				       dm->gnt_set[RTW89_PHY_1].gnt_wl,
12302 				       dm->gnt_set[RTW89_PHY_1].gnt_bt0_sw_en ? "SW" : "HW",
12303 				       dm->gnt_set[RTW89_PHY_1].gnt_bt0);
12304 	}
12305 
12306 	pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
12307 	if (!pcinfo->valid)
12308 		goto out;
12309 
12310 	pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
12311 
12312 	for (i = 0; i < pmreg->reg_num; i++) {
12313 		type = (u8)le16_to_cpu(rtwdev->chip->mon_reg[i].type);
12314 		offset = le32_to_cpu(rtwdev->chip->mon_reg[i].offset);
12315 		val = le32_to_cpu(pmreg->mreg_val[i]);
12316 
12317 		if (cnt % 6 == 0)
12318 			p += scnprintf(p, end - p,
12319 				       "\n %-15s : %s_0x%x=0x%x", "[reg]",
12320 				       id_to_regtype(type), offset, val);
12321 		else
12322 			p += scnprintf(p, end - p, ", %s_0x%x=0x%x",
12323 				       id_to_regtype(type), offset, val);
12324 		cnt++;
12325 	}
12326 
12327 out:
12328 	return p - buf;
12329 }
12330 
_show_summary_v1(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12331 static int _show_summary_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12332 {
12333 	struct rtw89_btc *btc = &rtwdev->btc;
12334 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
12335 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
12336 	struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL;
12337 	struct rtw89_btc_cx *cx = &btc->cx;
12338 	struct rtw89_btc_dm *dm = &btc->dm;
12339 	struct rtw89_btc_wl_info *wl = &cx->wl;
12340 	struct rtw89_btc_bt_info *bt = &cx->bt0;
12341 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
12342 	char *p = buf, *end = buf + bufsz;
12343 	u8 i;
12344 
12345 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
12346 		return 0;
12347 
12348 	p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
12349 
12350 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
12351 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
12352 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v1;
12353 
12354 		p += scnprintf(p, end - p,
12355 			       " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
12356 			       "[summary]", pfwinfo->cnt_h2c,
12357 			       pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt,
12358 			       pfwinfo->cnt_c2h, prptctrl->c2h_cnt);
12359 
12360 		p += scnprintf(p, end - p,
12361 			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
12362 			       pfwinfo->event[BTF_EVNT_RPT],
12363 			       prptctrl->rpt_cnt,
12364 			       prptctrl->rpt_enable, dm->error.val);
12365 
12366 		if (dm->error.map.wl_fw_hang)
12367 			p += scnprintf(p, end - p, " (WL FW Hang!!)");
12368 		p += scnprintf(p, end - p, "\n");
12369 		p += scnprintf(p, end - p,
12370 			       " %-15s : send_ok:%d, send_fail:%d, recv:%d",
12371 			       "[mailbox]", prptctrl->mb_send_ok_cnt,
12372 			       prptctrl->mb_send_fail_cnt,
12373 			       prptctrl->mb_recv_cnt);
12374 
12375 		p += scnprintf(p, end - p,
12376 			       "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n",
12377 			       prptctrl->mb_a2dp_empty_cnt,
12378 			       prptctrl->mb_a2dp_flct_cnt,
12379 			       prptctrl->mb_a2dp_full_cnt);
12380 
12381 		p += scnprintf(p, end - p,
12382 			       " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
12383 			       "[RFK]", wl->wcnt[BTC_WCNT_RFK_REQ],
12384 			       wl->wcnt[BTC_WCNT_RFK_GO],
12385 			       wl->wcnt[BTC_WCNT_RFK_REJECT],
12386 			       wl->wcnt[BTC_WCNT_RFK_TIMEOUT]);
12387 
12388 		p += scnprintf(p, end - p,
12389 			       ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
12390 			       prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
12391 			       prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
12392 			       prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
12393 			       prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
12394 			       prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
12395 
12396 		if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
12397 			bt->rfk_info.map.timeout = 1;
12398 		else
12399 			bt->rfk_info.map.timeout = 0;
12400 
12401 		dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
12402 	} else {
12403 		p += scnprintf(p, end - p,
12404 			       " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
12405 			       "[summary]", pfwinfo->cnt_h2c,
12406 			       pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
12407 			       pfwinfo->event[BTF_EVNT_RPT],
12408 			       btc->fwinfo.rpt_en_map);
12409 		p += scnprintf(p, end - p, " (WL FW report invalid!!)\n");
12410 	}
12411 
12412 	for (i = 0; i < BTC_NCNT_NUM; i++)
12413 		cnt_sum += dm->cnt_notify[i];
12414 
12415 	p += scnprintf(p, end - p,
12416 		       " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
12417 		       "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
12418 		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
12419 
12420 	p += scnprintf(p, end - p,
12421 		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
12422 		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
12423 		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
12424 		       cnt[BTC_NCNT_WL_STA]);
12425 
12426 	p += scnprintf(p, end - p,
12427 		       " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
12428 		       "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
12429 		       cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
12430 		       cnt[BTC_NCNT_SPECIAL_PACKET]);
12431 
12432 	p += scnprintf(p, end - p,
12433 		       "timer=%d, control=%d, customerize=%d\n",
12434 		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
12435 		       cnt[BTC_NCNT_CUSTOMERIZE]);
12436 
12437 	return p - buf;
12438 }
12439 
_show_summary_v4(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12440 static int _show_summary_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12441 {
12442 	struct rtw89_btc *btc = &rtwdev->btc;
12443 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
12444 	struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl;
12445 	struct rtw89_btc_rpt_cmn_info *pcinfo;
12446 	struct rtw89_btc_cx *cx = &btc->cx;
12447 	struct rtw89_btc_dm *dm = &btc->dm;
12448 	struct rtw89_btc_wl_info *wl = &cx->wl;
12449 	struct rtw89_btc_bt_info *bt = &cx->bt0;
12450 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
12451 	char *p = buf, *end = buf + bufsz;
12452 	u8 i;
12453 
12454 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
12455 		return 0;
12456 
12457 	p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
12458 
12459 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
12460 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
12461 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v4;
12462 
12463 		p += scnprintf(p, end - p,
12464 			       " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
12465 			       "[summary]", pfwinfo->cnt_h2c,
12466 			       pfwinfo->cnt_h2c_fail,
12467 			       le32_to_cpu(prptctrl->rpt_info.cnt_h2c),
12468 			       pfwinfo->cnt_c2h,
12469 			       le32_to_cpu(prptctrl->rpt_info.cnt_c2h));
12470 
12471 		p += scnprintf(p, end - p,
12472 			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
12473 			       pfwinfo->event[BTF_EVNT_RPT],
12474 			       le32_to_cpu(prptctrl->rpt_info.cnt),
12475 			       le32_to_cpu(prptctrl->rpt_info.en),
12476 			       dm->error.val);
12477 
12478 		if (dm->error.map.wl_fw_hang)
12479 			p += scnprintf(p, end - p, " (WL FW Hang!!)");
12480 		p += scnprintf(p, end - p, "\n");
12481 		p += scnprintf(p, end - p,
12482 			       " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
12483 			       "[mailbox]",
12484 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
12485 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
12486 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
12487 
12488 		p += scnprintf(p, end - p,
12489 			       "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
12490 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
12491 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
12492 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
12493 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
12494 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
12495 
12496 		p += scnprintf(p, end - p,
12497 			       " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
12498 			       "[RFK]", wl->wcnt[BTC_WCNT_RFK_REQ],
12499 			       wl->wcnt[BTC_WCNT_RFK_GO],
12500 			       wl->wcnt[BTC_WCNT_RFK_REJECT],
12501 			       wl->wcnt[BTC_WCNT_RFK_TIMEOUT]);
12502 
12503 		p += scnprintf(p, end - p,
12504 			       ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
12505 			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]),
12506 			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]),
12507 			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]),
12508 			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]),
12509 			       le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL]));
12510 
12511 		if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
12512 			bt->rfk_info.map.timeout = 1;
12513 		else
12514 			bt->rfk_info.map.timeout = 0;
12515 
12516 		dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
12517 	} else {
12518 		p += scnprintf(p, end - p,
12519 			       " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
12520 			       "[summary]", pfwinfo->cnt_h2c,
12521 			       pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
12522 			       pfwinfo->event[BTF_EVNT_RPT],
12523 			       btc->fwinfo.rpt_en_map);
12524 		p += scnprintf(p, end - p, " (WL FW report invalid!!)\n");
12525 	}
12526 
12527 	for (i = 0; i < BTC_NCNT_NUM; i++)
12528 		cnt_sum += dm->cnt_notify[i];
12529 
12530 	p += scnprintf(p, end - p,
12531 		       " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
12532 		       "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
12533 		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
12534 
12535 	p += scnprintf(p, end - p,
12536 		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
12537 		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
12538 		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
12539 		       cnt[BTC_NCNT_WL_STA]);
12540 
12541 	p += scnprintf(p, end - p,
12542 		       " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
12543 		       "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
12544 		       cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
12545 		       cnt[BTC_NCNT_SPECIAL_PACKET]);
12546 
12547 	p += scnprintf(p, end - p,
12548 		       "timer=%d, control=%d, customerize=%d\n",
12549 		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
12550 		       cnt[BTC_NCNT_CUSTOMERIZE]);
12551 
12552 	return p - buf;
12553 }
12554 
_show_summary_v5(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12555 static int _show_summary_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12556 {
12557 	struct rtw89_btc *btc = &rtwdev->btc;
12558 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
12559 	struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl;
12560 	struct rtw89_btc_rpt_cmn_info *pcinfo;
12561 	struct rtw89_btc_cx *cx = &btc->cx;
12562 	struct rtw89_btc_dm *dm = &btc->dm;
12563 	struct rtw89_btc_wl_info *wl = &cx->wl;
12564 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
12565 	char *p = buf, *end = buf + bufsz;
12566 	u8 i;
12567 
12568 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
12569 		return 0;
12570 
12571 	p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
12572 
12573 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
12574 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
12575 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v5;
12576 
12577 		p += scnprintf(p, end - p,
12578 			       " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
12579 			       "[summary]", pfwinfo->cnt_h2c,
12580 			       pfwinfo->cnt_h2c_fail,
12581 			       le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
12582 			       pfwinfo->cnt_c2h,
12583 			       le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
12584 			       le16_to_cpu(prptctrl->rpt_info.len_c2h));
12585 
12586 		p += scnprintf(p, end - p,
12587 			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
12588 			       pfwinfo->event[BTF_EVNT_RPT],
12589 			       le16_to_cpu(prptctrl->rpt_info.cnt),
12590 			       le32_to_cpu(prptctrl->rpt_info.en));
12591 
12592 		if (dm->error.map.wl_fw_hang)
12593 			p += scnprintf(p, end - p, " (WL FW Hang!!)");
12594 		p += scnprintf(p, end - p, "\n");
12595 		p += scnprintf(p, end - p,
12596 			       " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
12597 			       "[mailbox]",
12598 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
12599 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
12600 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
12601 
12602 		p += scnprintf(p, end - p,
12603 			       "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
12604 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
12605 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
12606 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
12607 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
12608 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
12609 
12610 		p += scnprintf(p, end - p,
12611 			       " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
12612 			       "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ],
12613 			       wl->wcnt[BTC_WCNT_RFK_GO],
12614 			       wl->wcnt[BTC_WCNT_RFK_REJECT],
12615 			       wl->wcnt[BTC_WCNT_RFK_TIMEOUT]);
12616 
12617 		p += scnprintf(p, end - p,
12618 			       ", bt_rfk[req:%d]",
12619 			       le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
12620 
12621 		p += scnprintf(p, end - p,
12622 			       ", AOAC[RF_on:%d/RF_off:%d]",
12623 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
12624 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
12625 	} else {
12626 		p += scnprintf(p, end - p,
12627 			       " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
12628 			       "[summary]", pfwinfo->cnt_h2c,
12629 			       pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
12630 	}
12631 
12632 	if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
12633 	    pfwinfo->err[BTFRE_EXCEPTION]) {
12634 		p += scnprintf(p, end - p, "\n");
12635 		p += scnprintf(p, end - p,
12636 			       " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
12637 			       "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
12638 			       "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
12639 			       pfwinfo->fver_mismch,
12640 			       pfwinfo->err[BTFRE_EXCEPTION],
12641 			       wl->status.map.lps, wl->status.map.rf_off);
12642 	}
12643 
12644 	for (i = 0; i < BTC_NCNT_NUM; i++)
12645 		cnt_sum += dm->cnt_notify[i];
12646 
12647 	p += scnprintf(p, end - p, "\n");
12648 	p += scnprintf(p, end - p,
12649 		       " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
12650 		       "[notify_cnt]",
12651 		       cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
12652 		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
12653 
12654 	p += scnprintf(p, end - p,
12655 		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
12656 		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
12657 		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
12658 		       cnt[BTC_NCNT_WL_STA]);
12659 
12660 	p += scnprintf(p, end - p,
12661 		       " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
12662 		       "[notify_cnt]",
12663 		       cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
12664 		       cnt[BTC_NCNT_SWITCH_BAND],
12665 		       cnt[BTC_NCNT_SPECIAL_PACKET]);
12666 
12667 	p += scnprintf(p, end - p,
12668 		       "timer=%d, control=%d, customerize=%d",
12669 		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
12670 		       cnt[BTC_NCNT_CUSTOMERIZE]);
12671 
12672 	return p - buf;
12673 }
12674 
_show_summary_v105(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12675 static int _show_summary_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12676 {
12677 	struct rtw89_btc *btc = &rtwdev->btc;
12678 	struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
12679 	struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl;
12680 	struct rtw89_btc_rpt_cmn_info *pcinfo;
12681 	struct rtw89_btc_cx *cx = &btc->cx;
12682 	struct rtw89_btc_dm *dm = &btc->dm;
12683 	struct rtw89_btc_wl_info *wl = &cx->wl;
12684 	u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
12685 	char *p = buf, *end = buf + bufsz;
12686 	u8 i;
12687 
12688 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
12689 		return 0;
12690 
12691 	p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
12692 
12693 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
12694 	if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
12695 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v105;
12696 
12697 		p += scnprintf(p, end - p,
12698 			       " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
12699 			       "[summary]", pfwinfo->cnt_h2c,
12700 			       pfwinfo->cnt_h2c_fail,
12701 			       le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
12702 			       pfwinfo->cnt_c2h,
12703 			       le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
12704 			       le16_to_cpu(prptctrl->rpt_info.len_c2h));
12705 
12706 		p += scnprintf(p, end - p,
12707 			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
12708 			       pfwinfo->event[BTF_EVNT_RPT],
12709 			       le16_to_cpu(prptctrl->rpt_info.cnt),
12710 			       le32_to_cpu(prptctrl->rpt_info.en));
12711 
12712 		if (dm->error.map.wl_fw_hang)
12713 			p += scnprintf(p, end - p, " (WL FW Hang!!)");
12714 		p += scnprintf(p, end - p, "\n");
12715 		p += scnprintf(p, end - p,
12716 			       " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
12717 			       "[mailbox]",
12718 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
12719 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
12720 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
12721 
12722 		p += scnprintf(p, end - p,
12723 			       "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
12724 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
12725 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
12726 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
12727 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
12728 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
12729 
12730 		p += scnprintf(p, end - p,
12731 			       " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
12732 			       "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ],
12733 			       wl->wcnt[BTC_WCNT_RFK_GO],
12734 			       wl->wcnt[BTC_WCNT_RFK_REJECT],
12735 			       wl->wcnt[BTC_WCNT_RFK_TIMEOUT]);
12736 
12737 		p += scnprintf(p, end - p,
12738 			       ", bt_rfk[req:%d]",
12739 			       le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
12740 
12741 		p += scnprintf(p, end - p,
12742 			       ", AOAC[RF_on:%d/RF_off:%d]",
12743 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
12744 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
12745 	} else {
12746 		p += scnprintf(p, end - p,
12747 			       " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
12748 			       "[summary]", pfwinfo->cnt_h2c,
12749 			       pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
12750 	}
12751 
12752 	if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
12753 	    pfwinfo->err[BTFRE_EXCEPTION]) {
12754 		p += scnprintf(p, end - p, "\n");
12755 		p += scnprintf(p, end - p,
12756 			       " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
12757 			       "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
12758 			       "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
12759 			       pfwinfo->fver_mismch,
12760 			       pfwinfo->err[BTFRE_EXCEPTION],
12761 			       wl->status.map.lps, wl->status.map.rf_off);
12762 	}
12763 
12764 	for (i = 0; i < BTC_NCNT_NUM; i++)
12765 		cnt_sum += dm->cnt_notify[i];
12766 
12767 	p += scnprintf(p, end - p, "\n");
12768 	p += scnprintf(p, end - p,
12769 		       " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
12770 		       "[notify_cnt]",
12771 		       cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
12772 		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
12773 
12774 	p += scnprintf(p, end - p,
12775 		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
12776 		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
12777 		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
12778 		       cnt[BTC_NCNT_WL_STA]);
12779 
12780 	p += scnprintf(p, end - p,
12781 		       " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
12782 		       "[notify_cnt]",
12783 		       cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
12784 		       cnt[BTC_NCNT_SWITCH_BAND],
12785 		       cnt[BTC_NCNT_SPECIAL_PACKET]);
12786 
12787 	p += scnprintf(p, end - p,
12788 		       "timer=%d, control=%d, customerize=%d",
12789 		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
12790 		       cnt[BTC_NCNT_CUSTOMERIZE]);
12791 
12792 	return p - buf;
12793 }
12794 
_show_summary_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12795 static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12796 {
12797 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
12798 	struct rtw89_btc_fbtc_rpt_ctrl_v7 *prptctrl = NULL;
12799 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
12800 	struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
12801 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
12802 	struct rtw89_btc_wl_info *wl = &cx->wl;
12803 	u32 *cnt = rtwdev->btc.dm.cnt_notify;
12804 	char *p = buf, *end = buf + bufsz;
12805 	u32 cnt_sum = 0;
12806 	u8 i;
12807 
12808 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
12809 		return 0;
12810 
12811 	p += scnprintf(p, end - p, "%s",
12812 		       "\n========== [Statistics] ==========\n");
12813 
12814 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
12815 	if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
12816 	    !wl->status.map.rf_off) {
12817 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v7;
12818 
12819 		p += scnprintf(p, end - p,
12820 			       " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d),"
12821 			       "c2h_cnt=%d(fw_send:%d, len:%d, max:%d), ",
12822 			       "[summary]", pfwinfo->cnt_h2c,
12823 			       pfwinfo->cnt_h2c_fail,
12824 			       le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
12825 			       pfwinfo->cnt_c2h,
12826 			       le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
12827 			       le16_to_cpu(prptctrl->rpt_info.len_c2h),
12828 			       rtwdev->btc.ver->info_buf);
12829 
12830 		p += scnprintf(p, end - p,
12831 			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
12832 			       pfwinfo->event[BTF_EVNT_RPT],
12833 			       le16_to_cpu(prptctrl->rpt_info.cnt),
12834 			       le32_to_cpu(prptctrl->rpt_info.en));
12835 
12836 		if (dm->error.map.wl_fw_hang)
12837 			p += scnprintf(p, end - p, " (WL FW Hang!!)");
12838 		p += scnprintf(p, end - p, "\n");
12839 
12840 		p += scnprintf(p, end - p,
12841 			       " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
12842 			       "[mailbox]",
12843 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
12844 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
12845 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
12846 
12847 		p += scnprintf(p, end - p,
12848 			       "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n",
12849 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
12850 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
12851 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
12852 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
12853 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
12854 
12855 		p += scnprintf(p, end - p,
12856 			       " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
12857 			       "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ],
12858 			       wl->wcnt[BTC_WCNT_RFK_GO],
12859 			       wl->wcnt[BTC_WCNT_RFK_REJECT],
12860 			       wl->wcnt[BTC_WCNT_RFK_TIMEOUT],
12861 			       wl->rfk_info.proc_time);
12862 
12863 		p += scnprintf(p, end - p, ", bt_rfk[req:%d]",
12864 			       le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
12865 
12866 		p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n",
12867 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
12868 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
12869 	} else {
12870 		p += scnprintf(p, end - p,
12871 			       " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n",
12872 			       "[summary]",
12873 			       pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
12874 			       pfwinfo->cnt_c2h,
12875 			       wl->status.map.lps, wl->status.map.rf_off);
12876 	}
12877 
12878 	for (i = 0; i < BTC_NCNT_NUM; i++)
12879 		cnt_sum += dm->cnt_notify[i];
12880 
12881 	p += scnprintf(p, end - p,
12882 		       " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
12883 		       "[notify_cnt]",
12884 		       cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
12885 		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
12886 
12887 	p += scnprintf(p, end - p,
12888 		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
12889 		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
12890 		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
12891 		       cnt[BTC_NCNT_WL_STA]);
12892 
12893 	p += scnprintf(p, end - p,
12894 		       " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
12895 		       "[notify_cnt]",
12896 		       cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
12897 		       cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
12898 		       cnt[BTC_NCNT_SPECIAL_PACKET]);
12899 
12900 	p += scnprintf(p, end - p,
12901 		       "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
12902 		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
12903 		       rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
12904 		       cnt[BTC_NCNT_COUNTRYCODE]);
12905 
12906 	return p - buf;
12907 }
12908 
_show_summary_v8(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12909 static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12910 {
12911 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
12912 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
12913 	struct rtw89_btc_fbtc_rpt_ctrl_v8 *prptctrl = NULL;
12914 	struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
12915 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
12916 	struct rtw89_btc_wl_info *wl = &cx->wl;
12917 	u32 *cnt = rtwdev->btc.dm.cnt_notify;
12918 	char *p = buf, *end = buf + bufsz;
12919 	u32 cnt_sum = 0;
12920 	u8 i;
12921 
12922 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
12923 		return 0;
12924 
12925 	p += scnprintf(p, end - p, "%s",
12926 		       "\n========== [Statistics] ==========\n");
12927 
12928 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
12929 	if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
12930 	    !wl->status.map.rf_off) {
12931 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v8;
12932 
12933 		p += scnprintf(p, end - p,
12934 			       " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ",
12935 			       "[summary]", pfwinfo->cnt_h2c,
12936 			       pfwinfo->cnt_h2c_fail,
12937 			       le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
12938 			       pfwinfo->cnt_c2h,
12939 			       le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
12940 			       le16_to_cpu(prptctrl->rpt_info.len_c2h),
12941 			       (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l,
12942 			       rtwdev->btc.ver->info_buf);
12943 
12944 		p += scnprintf(p, end - p,
12945 			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
12946 			       pfwinfo->event[BTF_EVNT_RPT],
12947 			       le16_to_cpu(prptctrl->rpt_info.cnt),
12948 			       le32_to_cpu(prptctrl->rpt_info.en));
12949 
12950 		if (dm->error.map.wl_fw_hang)
12951 			p += scnprintf(p, end - p, " (WL FW Hang!!)");
12952 		p += scnprintf(p, end - p, "\n");
12953 
12954 		p += scnprintf(p, end - p,
12955 			       " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
12956 			       "[mailbox]",
12957 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
12958 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
12959 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
12960 
12961 		p += scnprintf(p, end - p,
12962 			       "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n",
12963 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
12964 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
12965 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
12966 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
12967 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
12968 
12969 		p += scnprintf(p, end - p,
12970 			       " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
12971 			       "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ],
12972 			       wl->wcnt[BTC_WCNT_RFK_GO],
12973 			       wl->wcnt[BTC_WCNT_RFK_REJECT],
12974 			       wl->wcnt[BTC_WCNT_RFK_TIMEOUT],
12975 			       wl->rfk_info.proc_time);
12976 
12977 		p += scnprintf(p, end - p, ", bt_rfk[req:%d]",
12978 			       le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
12979 
12980 		p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n",
12981 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
12982 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
12983 	} else {
12984 		p += scnprintf(p, end - p,
12985 			       " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n",
12986 			       "[summary]",
12987 			       pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
12988 			       pfwinfo->cnt_c2h,
12989 			       wl->status.map.lps, wl->status.map.rf_off);
12990 	}
12991 
12992 	for (i = 0; i < BTC_NCNT_NUM; i++)
12993 		cnt_sum += dm->cnt_notify[i];
12994 
12995 	p += scnprintf(p, end - p,
12996 		       " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
12997 		       "[notify_cnt]",
12998 		       cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
12999 		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
13000 
13001 	p += scnprintf(p, end - p,
13002 		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
13003 		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
13004 		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
13005 		       cnt[BTC_NCNT_WL_STA]);
13006 
13007 	p += scnprintf(p, end - p,
13008 		       " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
13009 		       "[notify_cnt]",
13010 		       cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
13011 		       cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
13012 		       cnt[BTC_NCNT_SPECIAL_PACKET]);
13013 
13014 	p += scnprintf(p, end - p,
13015 		       "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
13016 		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
13017 		       rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
13018 		       cnt[BTC_NCNT_COUNTRYCODE]);
13019 
13020 	return p - buf;
13021 }
13022 
_show_summary_v9(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)13023 static int _show_summary_v9(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
13024 {
13025 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
13026 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
13027 	struct rtw89_btc_fbtc_rpt_ctrl_v9 *prptctrl = NULL;
13028 	struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
13029 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
13030 	struct rtw89_btc_wl_info *wl = &cx->wl;
13031 	u32 *cnt = rtwdev->btc.dm.cnt_notify;
13032 	char *p = buf, *end = buf + bufsz;
13033 	u32 cnt_sum = 0;
13034 	u8 i;
13035 
13036 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
13037 		return 0;
13038 
13039 	p += scnprintf(p, end - p, "%s",
13040 		       "\n========== [Statistics] ==========\n");
13041 
13042 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
13043 	if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
13044 	    !wl->status.map.rf_off) {
13045 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v9;
13046 
13047 		p += scnprintf(p, end - p,
13048 			       " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, ",
13049 			       "[summary]", pfwinfo->cnt_h2c,
13050 			       pfwinfo->cnt_h2c_fail,
13051 			       le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
13052 			       pfwinfo->cnt_c2h,
13053 			       le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
13054 			       le16_to_cpu(prptctrl->rpt_info.len_c2h));
13055 
13056 		p += scnprintf(p, end - p,
13057 			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
13058 			       pfwinfo->event[BTF_EVNT_RPT],
13059 			       le16_to_cpu(prptctrl->rpt_info.cnt),
13060 			       le32_to_cpu(prptctrl->rpt_info.en));
13061 
13062 		if (dm->error.map.wl_fw_hang)
13063 			p += scnprintf(p, end - p, " (WL FW Hang!!)");
13064 		p += scnprintf(p, end - p, "\n");
13065 
13066 		p += scnprintf(p, end - p,
13067 			       " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
13068 			       "[mailbox]",
13069 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
13070 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
13071 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
13072 
13073 		p += scnprintf(p, end - p,
13074 			       "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n",
13075 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
13076 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
13077 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
13078 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
13079 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
13080 
13081 		p += scnprintf(p, end - p,
13082 			       " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
13083 			       "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ],
13084 			       wl->wcnt[BTC_WCNT_RFK_GO],
13085 			       wl->wcnt[BTC_WCNT_RFK_REJECT],
13086 			       wl->wcnt[BTC_WCNT_RFK_TIMEOUT],
13087 			       wl->rfk_info.proc_time);
13088 
13089 		p += scnprintf(p, end - p, ", bt_rfk[req:%d]",
13090 			       le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
13091 
13092 		p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n",
13093 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
13094 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
13095 	} else {
13096 		p += scnprintf(p, end - p,
13097 			       " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n",
13098 			       "[summary]",
13099 			       pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
13100 			       pfwinfo->cnt_c2h,
13101 			       wl->status.map.lps, wl->status.map.rf_off);
13102 	}
13103 
13104 	for (i = 0; i < BTC_NCNT_NUM; i++)
13105 		cnt_sum += dm->cnt_notify[i];
13106 
13107 	p += scnprintf(p, end - p,
13108 		       " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
13109 		       "[notify_cnt]",
13110 		       cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
13111 		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
13112 
13113 	p += scnprintf(p, end - p,
13114 		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
13115 		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
13116 		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
13117 		       cnt[BTC_NCNT_WL_STA]);
13118 
13119 	p += scnprintf(p, end - p,
13120 		       " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
13121 		       "[notify_cnt]",
13122 		       cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
13123 		       cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
13124 		       cnt[BTC_NCNT_SPECIAL_PACKET]);
13125 
13126 	p += scnprintf(p, end - p,
13127 		       "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
13128 		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
13129 		       rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
13130 		       cnt[BTC_NCNT_COUNTRYCODE]);
13131 
13132 	return p - buf;
13133 }
13134 
_show_summary_v11(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)13135 static int _show_summary_v11(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
13136 {
13137 	struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
13138 	struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
13139 	struct rtw89_btc_fbtc_rpt_ctrl_v11 *prptctrl = NULL;
13140 	struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
13141 	struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
13142 	struct rtw89_btc_wl_info *wl = &cx->wl;
13143 	u32 *cnt = rtwdev->btc.dm.cnt_notify;
13144 	char *p = buf, *end = buf + bufsz;
13145 	u32 cnt_sum = 0;
13146 	u8 i;
13147 
13148 	if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
13149 		return 0;
13150 
13151 	p += scnprintf(p, end - p, "%s",
13152 		       "\n========== [Statistics] ==========\n");
13153 
13154 	pcinfo = &pfwinfo->rpt_ctrl.cinfo;
13155 	if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
13156 	    !wl->status.map.rf_off) {
13157 		prptctrl = &pfwinfo->rpt_ctrl.finfo.v11;
13158 
13159 		p += scnprintf(p, end - p,
13160 			       " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ",
13161 			       "[summary]", pfwinfo->cnt_h2c,
13162 			       pfwinfo->cnt_h2c_fail,
13163 			       le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
13164 			       pfwinfo->cnt_c2h,
13165 			       le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
13166 			       le16_to_cpu(prptctrl->rpt_info.len_c2h),
13167 			       (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l,
13168 			       rtwdev->btc.ver->info_buf);
13169 
13170 		p += scnprintf(p, end - p,
13171 			       "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
13172 			       pfwinfo->event[BTF_EVNT_RPT],
13173 			       le16_to_cpu(prptctrl->rpt_info.cnt),
13174 			       le32_to_cpu(prptctrl->rpt_info.en));
13175 
13176 		if (dm->error.map.wl_fw_hang)
13177 			p += scnprintf(p, end - p, " (WL FW Hang!!)");
13178 		p += scnprintf(p, end - p, "\n");
13179 
13180 		p += scnprintf(p, end - p,
13181 			       " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
13182 			       "[mailbox]",
13183 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
13184 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
13185 			       le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
13186 
13187 		p += scnprintf(p, end - p,
13188 			       "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n",
13189 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
13190 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
13191 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
13192 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
13193 			       le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
13194 
13195 		p += scnprintf(p, end - p,
13196 			       " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
13197 			       "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ],
13198 			       wl->wcnt[BTC_WCNT_RFK_GO],
13199 			       wl->wcnt[BTC_WCNT_RFK_REJECT],
13200 			       wl->wcnt[BTC_WCNT_RFK_TIMEOUT],
13201 			       wl->rfk_info.proc_time);
13202 
13203 		p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n",
13204 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
13205 			       le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
13206 	} else {
13207 		p += scnprintf(p, end - p,
13208 			       " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n",
13209 			       "[summary]",
13210 			       pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
13211 			       pfwinfo->cnt_c2h,
13212 			       wl->status.map.lps, wl->status.map.rf_off);
13213 	}
13214 
13215 	for (i = 0; i < BTC_NCNT_NUM; i++)
13216 		cnt_sum += dm->cnt_notify[i];
13217 
13218 	p += scnprintf(p, end - p,
13219 		       " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
13220 		       "[notify_cnt]",
13221 		       cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
13222 		       cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
13223 
13224 	p += scnprintf(p, end - p,
13225 		       "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
13226 		       cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
13227 		       cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
13228 		       cnt[BTC_NCNT_WL_STA]);
13229 
13230 	p += scnprintf(p, end - p,
13231 		       " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
13232 		       "[notify_cnt]",
13233 		       cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
13234 		       cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
13235 		       cnt[BTC_NCNT_SPECIAL_PACKET]);
13236 
13237 	p += scnprintf(p, end - p,
13238 		       "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
13239 		       cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
13240 		       rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
13241 		       cnt[BTC_NCNT_COUNTRYCODE]);
13242 
13243 	return p - buf;
13244 }
13245 
rtw89_btc_dump_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)13246 ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
13247 {
13248 	struct rtw89_btc *btc = &rtwdev->btc;
13249 	struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver;
13250 	const struct rtw89_btc_ver *ver = btc->ver;
13251 	struct rtw89_btc_dm *dm = &btc->dm;
13252 	char *p = buf, *end = buf + bufsz;
13253 
13254 	dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
13255 
13256 	p += scnprintf(p, end - p,
13257 		       "\n\n\n** Page:%3d/RunCNT:%3d **",
13258 		       dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO],
13259 		       dm->cnt_dm[BTC_DCNT_RUN]);
13260 	p += scnprintf(p, end - p,
13261 		       "\n========== [BTC FEATURE SUB VER] ==========");
13262 	p += scnprintf(p, end - p,
13263 		       "\n %-15s : fcxbtcrpt[%d/%d], fcxtdma[%d/%d], fcxslots[%d/%d], fcxcysta[%d/%d]",
13264 		       "[FW/DRV]", fwsubver->fcxbtcrpt, ver->fcxbtcrpt,
13265 		       fwsubver->fcxtdma, ver->fcxtdma, fwsubver->fcxslots,
13266 		       ver->fcxslots, fwsubver->fcxcysta, ver->fcxcysta);
13267 	p += scnprintf(p, end - p,
13268 		       "\n %-15s : fcxstep[%d/%d], fcxnullsta[%d/%d], fcxmreg[%d/%d], fcxgpiodbg[%d/%d]",
13269 		       "[FW/DRV]", fwsubver->fcxstep, ver->fcxstep,
13270 		       fwsubver->fcxnullsta, ver->fcxnullsta, fwsubver->fcxmreg,
13271 		       ver->fcxmreg, fwsubver->fcxgpiodbg, ver->fcxgpiodbg);
13272 	p += scnprintf(p, end - p,
13273 		       "\n %-15s : fcxbtver[%d/%d], fcxbtscan[%d/%d], fcxbtafh[%d/%d], fcxbtdevinfo[%d/%d]",
13274 		       "[FW/DRV]", fwsubver->fcxbtver, ver->fcxbtver,
13275 		       fwsubver->fcxbtscan, ver->fcxbtscan, fwsubver->fcxbtafh,
13276 		       ver->fcxbtafh, fwsubver->fcxbtdevinfo, ver->fcxbtdevinfo);
13277 	p += scnprintf(p, end - p,
13278 		       "\n %-15s : fcxosi[%d/%d], fcxmlo[%d/%d],",
13279 		       "[FW/DRV]", fwsubver->fcxosi, ver->fcxosi,
13280 		       fwsubver->fcxmlo, ver->fcxmlo);
13281 
13282 	p += _show_cx_info(rtwdev, p, end - p);
13283 	p += _show_wl_info(rtwdev, p, end - p);
13284 	p += _show_bt_info(rtwdev, p, end - p, BTC_BT_1ST);
13285 	p += _show_bt_info(rtwdev, p, end - p, BTC_BT_2ND);
13286 	p += _show_dm_info(rtwdev, p, end - p);
13287 	p += _show_fw_dm_msg(rtwdev, p, end - p);
13288 
13289 	if (ver->fcxmreg == 1)
13290 		p += _show_mreg_v1(rtwdev, p, end - p);
13291 	else if (ver->fcxmreg == 2)
13292 		p += _show_mreg_v2(rtwdev, p, end - p);
13293 	else if (ver->fcxmreg == 7)
13294 		p += _show_mreg_v7(rtwdev, p, end - p);
13295 
13296 	p += _show_gpio_dbg(rtwdev, p, end - p);
13297 
13298 	if (ver->fcxbtcrpt == 1)
13299 		p += _show_summary_v1(rtwdev, p, end - p);
13300 	else if (ver->fcxbtcrpt == 4)
13301 		p += _show_summary_v4(rtwdev, p, end - p);
13302 	else if (ver->fcxbtcrpt == 5)
13303 		p += _show_summary_v5(rtwdev, p, end - p);
13304 	else if (ver->fcxbtcrpt == 105)
13305 		p += _show_summary_v105(rtwdev, p, end - p);
13306 	else if (ver->fcxbtcrpt == 7)
13307 		p += _show_summary_v7(rtwdev, p, end - p);
13308 	else if (ver->fcxbtcrpt == 8)
13309 		p += _show_summary_v8(rtwdev, p, end - p);
13310 	else if (ver->fcxbtcrpt == 9)
13311 		p += _show_summary_v9(rtwdev, p, end - p);
13312 	else if (ver->fcxbtcrpt == 11)
13313 		p += _show_summary_v11(rtwdev, p, end - p);
13314 
13315 	p += scnprintf(p, end - p, "\n");
13316 
13317 	return p - buf;
13318 }
13319 
rtw89_coex_recognize_ver(struct rtw89_dev * rtwdev)13320 void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev)
13321 {
13322 	const struct rtw89_chip_info *chip = rtwdev->chip;
13323 	struct rtw89_btc *btc = &rtwdev->btc;
13324 	const struct rtw89_btc_ver *btc_ver_def;
13325 	const struct rtw89_fw_suit *fw_suit;
13326 	u32 suit_ver_code;
13327 	int i;
13328 
13329 	fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL);
13330 	suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit);
13331 
13332 	for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) {
13333 		btc_ver_def = &rtw89_btc_ver_defs[i];
13334 
13335 		if (chip->chip_id != btc_ver_def->chip_id)
13336 			continue;
13337 
13338 		if (suit_ver_code >= btc_ver_def->fw_ver_code) {
13339 			btc->ver = btc_ver_def;
13340 			goto out;
13341 		}
13342 	}
13343 
13344 	btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX];
13345 
13346 out:
13347 	rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n",
13348 		    (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code);
13349 }
13350 
rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev * rtwdev,u32 ms)13351 void rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev *rtwdev, u32 ms)
13352 {
13353 	struct rtw89_btc_bt_link_info *bt_linfo = &rtwdev->btc.cx.bt0.link_info;
13354 	struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
13355 
13356 	if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags))
13357 		return;
13358 
13359 	if (!a2dp.exist)
13360 		return;
13361 
13362 	fsleep(ms * 1000);
13363 }
13364 EXPORT_SYMBOL(rtw89_btc_ntfy_preserve_bt_time);
13365 
rtw89_btc_ntfy_conn_rfk(struct rtw89_dev * rtwdev,bool state)13366 void rtw89_btc_ntfy_conn_rfk(struct rtw89_dev *rtwdev, bool state)
13367 {
13368 	rtwdev->btc.cx.wl.rfk_info.con_rfk = state;
13369 }
13370 EXPORT_SYMBOL(rtw89_btc_ntfy_conn_rfk);
13371