1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2019-2020 Realtek Corporation
3 */
4
5 #include "chan.h"
6 #include "coex.h"
7 #include "debug.h"
8 #include "fw.h"
9 #include "mac.h"
10 #include "phy.h"
11 #include "ps.h"
12 #include "reg.h"
13
14 #define RTW89_COEX_VERSION 0x09000013
15 #define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/
16 #define BTC_E2G_LIMIT_DEF 80
17
18 enum btc_fbtc_tdma_template {
19 CXTD_OFF = 0x0,
20 CXTD_OFF_B2,
21 CXTD_OFF_EXT,
22 CXTD_FIX,
23 CXTD_PFIX,
24 CXTD_AUTO,
25 CXTD_PAUTO,
26 CXTD_AUTO2,
27 CXTD_PAUTO2,
28 CXTD_MAX,
29 };
30
31 enum btc_fbtc_tdma_type {
32 CXTDMA_OFF = 0x0,
33 CXTDMA_FIX = 0x1,
34 CXTDMA_AUTO = 0x2,
35 CXTDMA_AUTO2 = 0x3,
36 CXTDMA_MAX
37 };
38
39 enum btc_fbtc_tdma_rx_flow_ctrl {
40 CXFLC_OFF = 0x0,
41 CXFLC_NULLP = 0x1,
42 CXFLC_QOSNULL = 0x2,
43 CXFLC_CTS = 0x3,
44 CXFLC_MAX
45 };
46
47 enum btc_fbtc_tdma_wlan_tx_pause {
48 CXTPS_OFF = 0x0, /* no wl tx pause*/
49 CXTPS_ON = 0x1,
50 CXTPS_MAX
51 };
52
53 enum btc_mlme_state {
54 MLME_NO_LINK,
55 MLME_LINKING,
56 MLME_LINKED,
57 };
58
59 struct btc_fbtc_1slot {
60 u8 fver;
61 u8 sid; /* slot id */
62 struct rtw89_btc_fbtc_slot slot;
63 } __packed;
64
65 static const struct rtw89_btc_fbtc_tdma t_def[] = {
66 [CXTD_OFF] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
67 [CXTD_OFF_B2] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0},
68 [CXTD_OFF_EXT] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 2, 0, 0},
69 [CXTD_FIX] = { CXTDMA_FIX, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
70 [CXTD_PFIX] = { CXTDMA_FIX, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0},
71 [CXTD_AUTO] = { CXTDMA_AUTO, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
72 [CXTD_PAUTO] = { CXTDMA_AUTO, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0},
73 [CXTD_AUTO2] = {CXTDMA_AUTO2, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
74 [CXTD_PAUTO2] = {CXTDMA_AUTO2, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}
75 };
76
77 #define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \
78 { .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \
79 .cxtype = cpu_to_le16(__cxtype),}
80
81 static const struct rtw89_btc_fbtc_slot s_def[] = {
82 [CXST_OFF] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
83 [CXST_B2W] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_ISO),
84 [CXST_W1] = __DEF_FBTC_SLOT(70, 0xea5a5a5a, SLOT_ISO),
85 [CXST_W2] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO),
86 [CXST_W2B] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO),
87 [CXST_B1] = __DEF_FBTC_SLOT(250, 0xe5555555, SLOT_MIX),
88 [CXST_B2] = __DEF_FBTC_SLOT(7, 0xea5a5a5a, SLOT_MIX),
89 [CXST_B3] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX),
90 [CXST_B4] = __DEF_FBTC_SLOT(50, 0xe5555555, SLOT_MIX),
91 [CXST_LK] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_ISO),
92 [CXST_BLK] = __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX),
93 [CXST_E2G] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_MIX),
94 [CXST_E5G] = __DEF_FBTC_SLOT(5, 0xffffffff, SLOT_ISO),
95 [CXST_EBT] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX),
96 [CXST_ENULL] = __DEF_FBTC_SLOT(5, 0x55555555, SLOT_MIX),
97 [CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX),
98 [CXST_W1FDD] = __DEF_FBTC_SLOT(50, 0xffffffff, SLOT_ISO),
99 [CXST_B1FDD] = __DEF_FBTC_SLOT(50, 0xffffdfff, SLOT_ISO),
100 };
101
102 static const u32 cxtbl[] = {
103 0xffffffff, /* 0 */
104 0xaaaaaaaa, /* 1 */
105 0xe5555555, /* 2 */
106 0xee555555, /* 3 */
107 0xd5555555, /* 4 */
108 0x5a5a5a5a, /* 5 */
109 0xfa5a5a5a, /* 6 */
110 0xda5a5a5a, /* 7 */
111 0xea5a5a5a, /* 8 */
112 0x6a5a5aaa, /* 9 */
113 0x6a5a6a5a, /* 10 */
114 0x6a5a6aaa, /* 11 */
115 0x6afa5afa, /* 12 */
116 0xaaaa5aaa, /* 13 */
117 0xaaffffaa, /* 14 */
118 0xaa5555aa, /* 15 */
119 0xfafafafa, /* 16 */
120 0xffffddff, /* 17 */
121 0xdaffdaff, /* 18 */
122 0xfafadafa, /* 19 */
123 0xea6a6a6a, /* 20 */
124 0xea55556a, /* 21 */
125 0xaafafafa, /* 22 */
126 0xfafaaafa, /* 23 */
127 0xfafffaff, /* 24 */
128 0xea6a5a5a, /* 25 */
129 0xfaff5aff, /* 26 */
130 0xffffdfff, /* 27 */
131 0xe6555555, /* 28 */
132 };
133
134 static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
135 /* firmware version must be in decreasing order for each chip */
136 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 122, 0),
137 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
138 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
139 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
140 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
141 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
142 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
143 },
144 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 90, 0),
145 .fcxbtcrpt = 7, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
146 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
147 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
148 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
149 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
150 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
151 },
152 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 71, 0),
153 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
154 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
155 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
156 .fwlrole = 8, .frptmap = 4, .fcxctrl = 7, .fcxinit = 7,
157 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_type = 2, .info_buf = 1800,
158 .max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9,
159 },
160 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 63, 0),
161 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
162 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
163 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
164 .fwlrole = 8, .frptmap = 4, .fcxctrl = 7, .fcxinit = 7,
165 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_type = 2, .info_buf = 1800,
166 .max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9,
167 },
168 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0),
169 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
170 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
171 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
172 .fwlrole = 8, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
173 .fwevntrptl = 1, .fwc2hfunc = 1, .drvinfo_type = 1, .info_buf = 1800,
174 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
175 },
176 {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0),
177 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5,
178 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1,
179 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1,
180 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
181 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
182 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
183 },
184 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0),
185 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
186 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
187 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
188 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
189 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
190 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
191 },
192 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0),
193 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
194 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
195 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
196 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0,
197 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
198 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
199 },
200 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0),
201 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
202 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
203 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
204 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0,
205 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
206 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
207 },
208 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 122, 0),
209 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
210 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
211 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
212 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
213 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
214 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
215 },
216 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0),
217 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5,
218 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1,
219 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1,
220 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
221 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
222 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
223 },
224 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0),
225 .fcxbtcrpt = 5, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 4,
226 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
227 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
228 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
229 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
230 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
231 },
232 {RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0),
233 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
234 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
235 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
236 .fwlrole = 1, .frptmap = 1, .fcxctrl = 1, .fcxinit = 0,
237 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
238 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
239 },
240 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0),
241 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
242 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
243 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
244 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
245 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1280,
246 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
247 },
248 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0),
249 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2,
250 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1,
251 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
252 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0,
253 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1024,
254 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
255 },
256
257 /* keep it to be the last as default entry */
258 {0, RTW89_FW_VER_CODE(0, 0, 0, 0),
259 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2,
260 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1,
261 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
262 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0,
263 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1024,
264 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
265 },
266 };
267
268 #define RTW89_DEFAULT_BTC_VER_IDX (ARRAY_SIZE(rtw89_btc_ver_defs) - 1)
269
270 static const union rtw89_btc_wl_state_map btc_scanning_map = {
271 .map = {
272 .scan = 1,
273 .connecting = 1,
274 .roaming = 1,
275 .dbccing = 1,
276 ._4way = 1,
277 },
278 };
279
chip_id_to_bt_rom_code_id(u32 id)280 static u32 chip_id_to_bt_rom_code_id(u32 id)
281 {
282 switch (id) {
283 case RTL8852A:
284 case RTL8852B:
285 case RTL8852C:
286 case RTL8852BT:
287 return 0x8852;
288 case RTL8851B:
289 return 0x8851;
290 case RTL8922A:
291 return 0x8922;
292 default:
293 return 0;
294 }
295 }
296
297 #define CASE_BTC_MLME_STATE(e) case MLME_##e: return #e
298
id_to_mlme_state(u32 id)299 static const char *id_to_mlme_state(u32 id)
300 {
301 switch (id) {
302 CASE_BTC_MLME_STATE(NO_LINK);
303 CASE_BTC_MLME_STATE(LINKING);
304 CASE_BTC_MLME_STATE(LINKED);
305 default:
306 return "unknown";
307 }
308 }
309
chip_id_str(u32 id)310 static char *chip_id_str(u32 id)
311 {
312 switch (id) {
313 case RTL8852A:
314 return "RTL8852A";
315 case RTL8852B:
316 return "RTL8852B";
317 case RTL8852C:
318 return "RTL8852C";
319 case RTL8852BT:
320 return "RTL8852BT";
321 case RTL8851B:
322 return "RTL8851B";
323 case RTL8922A:
324 return "RTL8922A";
325 default:
326 return "UNKNOWN";
327 }
328 }
329
330 struct rtw89_btc_btf_tlv {
331 u8 type;
332 u8 len;
333 u8 val[];
334 } __packed;
335
336 struct rtw89_btc_btf_tlv_v7 {
337 u8 type;
338 u8 ver;
339 u8 len;
340 u8 val[];
341 } __packed;
342
343 enum btc_btf_set_report_en {
344 RPT_EN_TDMA,
345 RPT_EN_CYCLE,
346 RPT_EN_MREG,
347 RPT_EN_BT_VER_INFO,
348 RPT_EN_BT_SCAN_INFO,
349 RPT_EN_BT_DEVICE_INFO,
350 RPT_EN_BT_AFH_MAP,
351 RPT_EN_BT_AFH_MAP_LE,
352 RPT_EN_BT_TX_PWR_LVL,
353 RPT_EN_FW_STEP_INFO,
354 RPT_EN_TEST,
355 RPT_EN_WL_ALL,
356 RPT_EN_BT_ALL,
357 RPT_EN_ALL,
358 RPT_EN_MONITER,
359 };
360
361 struct rtw89_btc_btf_set_report_v1 {
362 u8 fver;
363 __le32 enable;
364 __le32 para;
365 } __packed;
366
367 struct rtw89_btc_btf_set_report_v8 {
368 u8 type;
369 u8 fver;
370 u8 len;
371 __le32 map;
372 } __packed;
373
374 union rtw89_fbtc_rtp_ctrl {
375 struct rtw89_btc_btf_set_report_v1 v1;
376 struct rtw89_btc_btf_set_report_v8 v8;
377 };
378
379 #define BTF_SET_SLOT_TABLE_VER 1
380 struct rtw89_btc_btf_set_slot_table {
381 u8 fver;
382 u8 tbl_num;
383 struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num);
384 } __packed;
385
386 struct rtw89_btc_btf_set_slot_table_v7 {
387 u8 type;
388 u8 ver;
389 u8 len;
390 struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX];
391 } __packed;
392
393 struct rtw89_btc_btf_set_mon_reg_v1 {
394 u8 fver;
395 u8 reg_num;
396 struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num);
397 } __packed;
398
399 struct rtw89_btc_btf_set_mon_reg_v7 {
400 u8 type;
401 u8 fver;
402 u8 len;
403 struct rtw89_btc_fbtc_mreg regs[] __counted_by(len);
404 } __packed;
405
406 union rtw89_fbtc_set_mon_reg {
407 struct rtw89_btc_btf_set_mon_reg_v1 v1;
408 struct rtw89_btc_btf_set_mon_reg_v7 v7;
409 } __packed;
410
411 struct _wl_rinfo_now {
412 u8 link_mode;
413 u32 dbcc_2g_phy: 2;
414 };
415
416 enum btc_btf_set_cx_policy {
417 CXPOLICY_TDMA = 0x0,
418 CXPOLICY_SLOT = 0x1,
419 CXPOLICY_TYPE = 0x2,
420 CXPOLICY_MAX,
421 };
422
423 enum btc_b2w_scoreboard {
424 BTC_BSCB_ACT = BIT(0),
425 BTC_BSCB_ON = BIT(1),
426 BTC_BSCB_WHQL = BIT(2),
427 BTC_BSCB_BT_S1 = BIT(3),
428 BTC_BSCB_A2DP_ACT = BIT(4),
429 BTC_BSCB_RFK_RUN = BIT(5),
430 BTC_BSCB_RFK_REQ = BIT(6),
431 BTC_BSCB_LPS = BIT(7),
432 BTC_BSCB_BT_LNAB0 = BIT(8),
433 BTC_BSCB_BT_LNAB1 = BIT(10),
434 BTC_BSCB_WLRFK = BIT(11),
435 BTC_BSCB_BT_HILNA = BIT(13),
436 BTC_BSCB_BT_CONNECT = BIT(16),
437 BTC_BSCB_PATCH_CODE = BIT(30),
438 BTC_BSCB_ALL = GENMASK(30, 0),
439 };
440
441 enum btc_phymap {
442 BTC_PHY_0 = BIT(0),
443 BTC_PHY_1 = BIT(1),
444 BTC_PHY_ALL = BIT(0) | BIT(1),
445 };
446
447 enum btc_cx_state_map {
448 BTC_WIDLE = 0,
449 BTC_WBUSY_BNOSCAN,
450 BTC_WBUSY_BSCAN,
451 BTC_WSCAN_BNOSCAN,
452 BTC_WSCAN_BSCAN,
453 BTC_WLINKING
454 };
455
456 enum btc_ant_phase {
457 BTC_ANT_WPOWERON = 0,
458 BTC_ANT_WINIT,
459 BTC_ANT_WONLY,
460 BTC_ANT_WOFF,
461 BTC_ANT_W2G,
462 BTC_ANT_W5G,
463 BTC_ANT_W25G,
464 BTC_ANT_FREERUN,
465 BTC_ANT_WRFK,
466 BTC_ANT_WRFK2,
467 BTC_ANT_BRFK,
468 BTC_ANT_MAX
469 };
470
471 enum btc_plt {
472 BTC_PLT_NONE = 0,
473 BTC_PLT_LTE_RX = BIT(0),
474 BTC_PLT_GNT_BT_TX = BIT(1),
475 BTC_PLT_GNT_BT_RX = BIT(2),
476 BTC_PLT_GNT_WL = BIT(3),
477 BTC_PLT_BT = BIT(1) | BIT(2),
478 BTC_PLT_ALL = 0xf
479 };
480
481 enum btc_cx_poicy_main_type {
482 BTC_CXP_OFF = 0,
483 BTC_CXP_OFFB,
484 BTC_CXP_OFFE,
485 BTC_CXP_FIX,
486 BTC_CXP_PFIX,
487 BTC_CXP_AUTO,
488 BTC_CXP_PAUTO,
489 BTC_CXP_AUTO2,
490 BTC_CXP_PAUTO2,
491 BTC_CXP_MANUAL,
492 BTC_CXP_USERDEF0,
493 BTC_CXP_MAIN_MAX
494 };
495
496 enum btc_cx_poicy_type {
497 /* TDMA off + pri: BT > WL */
498 BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0,
499
500 /* TDMA off + pri: WL > BT */
501 BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1,
502
503 /* TDMA off + pri: BT = WL */
504 BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2,
505
506 /* TDMA off + pri: BT = WL > BT_Lo */
507 BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3,
508
509 /* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */
510 BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4,
511
512 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
513 BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5,
514
515 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
516 BTC_CXP_OFF_EQ4 = (BTC_CXP_OFF << 8) | 6,
517
518 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
519 BTC_CXP_OFF_EQ5 = (BTC_CXP_OFF << 8) | 7,
520
521 /* TDMA off + pri: BT_Hi > WL > BT_Lo */
522 BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 8,
523
524 /* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
525 BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 9,
526
527 /* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
528 BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 10,
529
530 /* TDMA off + pri: WL_Hi-Tx = BT */
531 BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 11,
532
533 /* TDMA off + pri: WL > BT, Block-BT*/
534 BTC_CXP_OFF_WL2 = (BTC_CXP_OFF << 8) | 12,
535
536 /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/
537 BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
538
539 /* TDMA off + Ext-Ctrl + pri: default */
540 BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0,
541
542 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
543 BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1,
544
545 /* TDMA off + Ext-Ctrl + pri: default */
546 BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2,
547
548 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
549 BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3,
550
551 /* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */
552 BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4,
553
554 /* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */
555 BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5,
556
557 /* TDMA off + Ext-Ctrl + pri: default */
558 BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6,
559
560 /* TDMA Fix slot-0: W1:B1 = 30:30 */
561 BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0,
562
563 /* TDMA Fix slot-1: W1:B1 = 50:50 */
564 BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1,
565
566 /* TDMA Fix slot-2: W1:B1 = 20:30 */
567 BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2,
568
569 /* TDMA Fix slot-3: W1:B1 = 40:10 */
570 BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3,
571
572 /* TDMA Fix slot-4: W1:B1 = 70:10 */
573 BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4,
574
575 /* TDMA Fix slot-5: W1:B1 = 20:60 */
576 BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5,
577
578 /* TDMA Fix slot-6: W1:B1 = 30:60 */
579 BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6,
580
581 /* TDMA Fix slot-7: W1:B1 = 20:80 */
582 BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7,
583
584 /* TDMA Fix slot-8: W1:B1 = user-define */
585 BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8,
586
587 /* TDMA Fix slot-9: W1:B1 = 40:10 */
588 BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 9,
589
590 /* TDMA Fix slot-10: W1:B1 = 40:10 */
591 BTC_CXP_FIX_TD4010ISO_DL = (BTC_CXP_FIX << 8) | 10,
592
593 /* TDMA Fix slot-11: W1:B1 = 40:10 */
594 BTC_CXP_FIX_TD4010ISO_UL = (BTC_CXP_FIX << 8) | 11,
595
596 /* PS-TDMA Fix slot-0: W1:B1 = 30:30 */
597 BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0,
598
599 /* PS-TDMA Fix slot-1: W1:B1 = 50:50 */
600 BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1,
601
602 /* PS-TDMA Fix slot-2: W1:B1 = 20:30 */
603 BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2,
604
605 /* PS-TDMA Fix slot-3: W1:B1 = 20:60 */
606 BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3,
607
608 /* PS-TDMA Fix slot-4: W1:B1 = 30:70 */
609 BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4,
610
611 /* PS-TDMA Fix slot-5: W1:B1 = 20:80 */
612 BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5,
613
614 /* PS-TDMA Fix slot-6: W1:B1 = user-define */
615 BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6,
616
617 /* TDMA Auto slot-0: W1:B1 = 50:200 */
618 BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0,
619
620 /* TDMA Auto slot-1: W1:B1 = 60:200 */
621 BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1,
622
623 /* TDMA Auto slot-2: W1:B1 = 20:200 */
624 BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2,
625
626 /* TDMA Auto slot-3: W1:B1 = user-define */
627 BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3,
628
629 /* PS-TDMA Auto slot-0: W1:B1 = 50:200 */
630 BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0,
631
632 /* PS-TDMA Auto slot-1: W1:B1 = 60:200 */
633 BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1,
634
635 /* PS-TDMA Auto slot-2: W1:B1 = 20:200 */
636 BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2,
637
638 /* PS-TDMA Auto slot-3: W1:B1 = user-define */
639 BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3,
640
641 /* TDMA Auto slot2-0: W1:B4 = 30:50 */
642 BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0,
643
644 /* TDMA Auto slot2-1: W1:B4 = 30:70 */
645 BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1,
646
647 /* TDMA Auto slot2-2: W1:B4 = 50:50 */
648 BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2,
649
650 /* TDMA Auto slot2-3: W1:B4 = 60:60 */
651 BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3,
652
653 /* TDMA Auto slot2-4: W1:B4 = 20:80 */
654 BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4,
655
656 /* TDMA Auto slot2-5: W1:B4 = user-define */
657 BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5,
658
659 /* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */
660 BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0,
661
662 /* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */
663 BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1,
664
665 /* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */
666 BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2,
667
668 /* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */
669 BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3,
670
671 /* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */
672 BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4,
673
674 /* PS-TDMA Auto slot2-5: W1:B4 = user-define */
675 BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5,
676
677 BTC_CXP_MAX = 0xffff
678 };
679
680 enum btc_wl_rfk_result {
681 BTC_WRFK_REJECT = 0,
682 BTC_WRFK_ALLOW = 1,
683 };
684
685 enum btc_coex_info_map_en {
686 BTC_COEX_INFO_CX = BIT(0),
687 BTC_COEX_INFO_WL = BIT(1),
688 BTC_COEX_INFO_BT = BIT(2),
689 BTC_COEX_INFO_DM = BIT(3),
690 BTC_COEX_INFO_MREG = BIT(4),
691 BTC_COEX_INFO_SUMMARY = BIT(5),
692 BTC_COEX_INFO_ALL = GENMASK(7, 0),
693 };
694
695 #define BTC_CXP_MASK GENMASK(15, 8)
696
697 enum btc_w2b_scoreboard {
698 BTC_WSCB_ACTIVE = BIT(0),
699 BTC_WSCB_ON = BIT(1),
700 BTC_WSCB_SCAN = BIT(2),
701 BTC_WSCB_UNDERTEST = BIT(3),
702 BTC_WSCB_RXGAIN = BIT(4),
703 BTC_WSCB_WLBUSY = BIT(7),
704 BTC_WSCB_EXTFEM = BIT(8),
705 BTC_WSCB_TDMA = BIT(9),
706 BTC_WSCB_FIX2M = BIT(10),
707 BTC_WSCB_WLRFK = BIT(11),
708 BTC_WSCB_RXSCAN_PRI = BIT(12),
709 BTC_WSCB_BT_HILNA = BIT(13),
710 BTC_WSCB_BTLOG = BIT(14),
711 BTC_WSCB_ALL = GENMASK(23, 0),
712 };
713
714 enum btc_wl_link_mode {
715 BTC_WLINK_NOLINK = 0x0,
716 BTC_WLINK_2G_STA,
717 BTC_WLINK_2G_AP,
718 BTC_WLINK_2G_GO,
719 BTC_WLINK_2G_GC,
720 BTC_WLINK_2G_SCC,
721 BTC_WLINK_2G_MCC,
722 BTC_WLINK_25G_MCC,
723 BTC_WLINK_25G_DBCC,
724 BTC_WLINK_5G,
725 BTC_WLINK_2G_NAN,
726 BTC_WLINK_OTHER,
727 BTC_WLINK_MAX
728 };
729
730 #define CASE_BTC_WL_LINK_MODE(e) case BTC_WLINK_## e: return #e
731
id_to_linkmode(u8 id)732 static const char *id_to_linkmode(u8 id)
733 {
734 switch (id) {
735 CASE_BTC_WL_LINK_MODE(NOLINK);
736 CASE_BTC_WL_LINK_MODE(2G_STA);
737 CASE_BTC_WL_LINK_MODE(2G_AP);
738 CASE_BTC_WL_LINK_MODE(2G_GO);
739 CASE_BTC_WL_LINK_MODE(2G_GC);
740 CASE_BTC_WL_LINK_MODE(2G_SCC);
741 CASE_BTC_WL_LINK_MODE(2G_MCC);
742 CASE_BTC_WL_LINK_MODE(25G_MCC);
743 CASE_BTC_WL_LINK_MODE(25G_DBCC);
744 CASE_BTC_WL_LINK_MODE(5G);
745 CASE_BTC_WL_LINK_MODE(OTHER);
746 default:
747 return "unknown";
748 }
749 }
750
751 enum btc_wl_mrole_type {
752 BTC_WLMROLE_NONE = 0x0,
753 BTC_WLMROLE_STA_GC,
754 BTC_WLMROLE_STA_GC_NOA,
755 BTC_WLMROLE_STA_GO,
756 BTC_WLMROLE_STA_GO_NOA,
757 BTC_WLMROLE_STA_STA,
758 BTC_WLMROLE_MAX
759 };
760
761 enum btc_bt_hid_type {
762 BTC_HID_218 = BIT(0),
763 BTC_HID_418 = BIT(1),
764 BTC_HID_BLE = BIT(2),
765 BTC_HID_RCU = BIT(3),
766 BTC_HID_RCU_VOICE = BIT(4),
767 BTC_HID_OTHER_LEGACY = BIT(5)
768 };
769
770 enum btc_reset_module {
771 BTC_RESET_CX = BIT(0),
772 BTC_RESET_DM = BIT(1),
773 BTC_RESET_CTRL = BIT(2),
774 BTC_RESET_CXDM = BIT(0) | BIT(1),
775 BTC_RESET_BTINFO = BIT(3),
776 BTC_RESET_MDINFO = BIT(4),
777 BTC_RESET_ALL = GENMASK(7, 0),
778 };
779
780 enum btc_gnt_state {
781 BTC_GNT_HW = 0,
782 BTC_GNT_SW_LO,
783 BTC_GNT_SW_HI,
784 BTC_GNT_MAX
785 };
786
787 enum btc_ctr_path {
788 BTC_CTRL_BY_BT = 0,
789 BTC_CTRL_BY_WL
790 };
791
792 enum btc_wlact_state {
793 BTC_WLACT_HW = 0,
794 BTC_WLACT_SW_LO,
795 BTC_WLACT_SW_HI,
796 BTC_WLACT_MAX,
797 };
798
799 enum btc_wl_max_tx_time {
800 BTC_MAX_TX_TIME_L1 = 500,
801 BTC_MAX_TX_TIME_L2 = 1000,
802 BTC_MAX_TX_TIME_L3 = 2000,
803 BTC_MAX_TX_TIME_DEF = 5280
804 };
805
806 enum btc_wl_max_tx_retry {
807 BTC_MAX_TX_RETRY_L1 = 7,
808 BTC_MAX_TX_RETRY_L2 = 15,
809 BTC_MAX_TX_RETRY_DEF = 31,
810 };
811
812 enum btc_reason_and_action {
813 BTC_RSN_NONE,
814 BTC_RSN_NTFY_INIT,
815 BTC_RSN_NTFY_SWBAND,
816 BTC_RSN_NTFY_WL_STA,
817 BTC_RSN_NTFY_RADIO_STATE,
818 BTC_RSN_UPDATE_BT_SCBD,
819 BTC_RSN_NTFY_WL_RFK,
820 BTC_RSN_UPDATE_BT_INFO,
821 BTC_RSN_NTFY_SCAN_START,
822 BTC_RSN_NTFY_SCAN_FINISH,
823 BTC_RSN_NTFY_SPECIFIC_PACKET,
824 BTC_RSN_NTFY_POWEROFF,
825 BTC_RSN_NTFY_ROLE_INFO,
826 BTC_RSN_CMD_SET_COEX,
827 BTC_RSN_ACT1_WORK,
828 BTC_RSN_BT_DEVINFO_WORK,
829 BTC_RSN_RFK_CHK_WORK,
830 BTC_RSN_NUM,
831 BTC_ACT_NONE = 100,
832 BTC_ACT_WL_ONLY,
833 BTC_ACT_WL_5G,
834 BTC_ACT_WL_OTHER,
835 BTC_ACT_WL_IDLE,
836 BTC_ACT_WL_NC,
837 BTC_ACT_WL_RFK,
838 BTC_ACT_WL_INIT,
839 BTC_ACT_WL_OFF,
840 BTC_ACT_FREERUN,
841 BTC_ACT_BT_WHQL,
842 BTC_ACT_BT_RFK,
843 BTC_ACT_BT_OFF,
844 BTC_ACT_BT_IDLE,
845 BTC_ACT_BT_HFP,
846 BTC_ACT_BT_HID,
847 BTC_ACT_BT_A2DP,
848 BTC_ACT_BT_A2DPSINK,
849 BTC_ACT_BT_PAN,
850 BTC_ACT_BT_A2DP_HID,
851 BTC_ACT_BT_A2DP_PAN,
852 BTC_ACT_BT_PAN_HID,
853 BTC_ACT_BT_A2DP_PAN_HID,
854 BTC_ACT_WL_25G_MCC,
855 BTC_ACT_WL_2G_MCC,
856 BTC_ACT_WL_2G_SCC,
857 BTC_ACT_WL_2G_AP,
858 BTC_ACT_WL_2G_GO,
859 BTC_ACT_WL_2G_GC,
860 BTC_ACT_WL_2G_NAN,
861 BTC_ACT_LAST,
862 BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE,
863 BTC_ACT_EXT_BIT = BIT(14),
864 BTC_POLICY_EXT_BIT = BIT(15),
865 };
866
867 #define BTC_FREERUN_ANTISO_MIN 30
868 #define BTC_TDMA_BTHID_MAX 2
869 #define BTC_BLINK_NOCONNECT 0
870 #define BTC_B1_MAX 250 /* unit ms */
871
872 static void _run_coex(struct rtw89_dev *rtwdev,
873 enum btc_reason_and_action reason);
874 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state);
875 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update);
876
_send_fw_cmd(struct rtw89_dev * rtwdev,u8 h2c_class,u8 h2c_func,void * param,u16 len)877 static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func,
878 void *param, u16 len)
879 {
880 struct rtw89_btc *btc = &rtwdev->btc;
881 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
882 struct rtw89_btc_cx *cx = &btc->cx;
883 struct rtw89_btc_wl_info *wl = &cx->wl;
884 struct rtw89_btc_dm *dm = &btc->dm;
885 int ret;
886
887 if (len > BTC_H2C_MAXLEN || len == 0) {
888 btc->fwinfo.cnt_h2c_fail++;
889 dm->error.map.h2c_buffer_over = true;
890 return -EINVAL;
891 } else if (!wl->status.map.init_ok) {
892 rtw89_debug(rtwdev, RTW89_DBG_BTC,
893 "[BTC], %s(): return by btc not init!!\n", __func__);
894 pfwinfo->cnt_h2c_fail++;
895 return -EINVAL;
896 } else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF &&
897 wl->status.map.rf_off == BTC_LPS_RF_OFF) ||
898 (wl->status.map.lps_pre == BTC_LPS_RF_OFF &&
899 wl->status.map.lps == BTC_LPS_RF_OFF)) {
900 rtw89_debug(rtwdev, RTW89_DBG_BTC,
901 "[BTC], %s(): return by wl off!!\n", __func__);
902 pfwinfo->cnt_h2c_fail++;
903 return -EINVAL;
904 }
905
906 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, param, len,
907 false, true);
908 if (ret)
909 pfwinfo->cnt_h2c_fail++;
910 else
911 pfwinfo->cnt_h2c++;
912
913 return ret;
914 }
915
916 #define BTC_BT_DEF_BR_TX_PWR 4
917 #define BTC_BT_DEF_LE_TX_PWR 4
918
_reset_btc_var(struct rtw89_dev * rtwdev,u8 type)919 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
920 {
921 struct rtw89_btc *btc = &rtwdev->btc;
922 const struct rtw89_btc_ver *ver = btc->ver;
923 struct rtw89_btc_cx *cx = &btc->cx;
924 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
925 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
926 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
927 struct rtw89_btc_wl_link_info *wl_linfo;
928 u8 i;
929
930 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
931
932 if (type & BTC_RESET_CX)
933 memset(cx, 0, sizeof(*cx));
934
935 if (type & BTC_RESET_BTINFO) /* only for BT enable */
936 memset(bt, 0, sizeof(*bt));
937
938 if (type & BTC_RESET_CTRL) {
939 memset(&btc->ctrl, 0, sizeof(btc->ctrl));
940 btc->manual_ctrl = false;
941 if (ver->fcxctrl != 7)
942 btc->ctrl.ctrl.trace_step = FCXDEF_STEP;
943 }
944
945 /* Init Coex variables that are not zero */
946 if (type & BTC_RESET_DM) {
947 memset(&btc->dm, 0, sizeof(btc->dm));
948 memset(bt_linfo->rssi_state, 0, sizeof(bt_linfo->rssi_state));
949 for (i = 0; i < RTW89_PORT_NUM; i++) {
950 if (btc->ver->fwlrole == 8)
951 wl_linfo = &wl->rlink_info[i][0];
952 else
953 wl_linfo = &wl->link_info[i];
954 memset(wl_linfo->rssi_state, 0, sizeof(wl_linfo->rssi_state));
955 }
956
957 /* set the slot_now table to original */
958 btc->dm.tdma_now = t_def[CXTD_OFF];
959 btc->dm.tdma = t_def[CXTD_OFF];
960 if (ver->fcxslots >= 7) {
961 for (i = 0; i < ARRAY_SIZE(s_def); i++) {
962 btc->dm.slot.v7[i].dur = s_def[i].dur;
963 btc->dm.slot.v7[i].cxtype = s_def[i].cxtype;
964 btc->dm.slot.v7[i].cxtbl = s_def[i].cxtbl;
965 }
966 memcpy(&btc->dm.slot_now.v7, &btc->dm.slot.v7,
967 sizeof(btc->dm.slot_now.v7));
968 } else {
969 memcpy(&btc->dm.slot_now.v1, s_def,
970 sizeof(btc->dm.slot_now.v1));
971 memcpy(&btc->dm.slot.v1, s_def,
972 sizeof(btc->dm.slot.v1));
973 }
974
975 btc->policy_len = 0;
976 btc->bt_req_len = 0;
977
978 btc->dm.coex_info_map = BTC_COEX_INFO_ALL;
979 btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF;
980 btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF;
981 btc->dm.wl_pre_agc_rb = BTC_PREAGC_NOTFOUND;
982 btc->dm.wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_NOTFOUND;
983 }
984
985 if (type & BTC_RESET_MDINFO)
986 memset(&btc->mdinfo, 0, sizeof(btc->mdinfo));
987
988 bt->link_info.bt_txpwr_desc.br_dbm = BTC_BT_DEF_BR_TX_PWR;
989 bt->link_info.bt_txpwr_desc.le_dbm = BTC_BT_DEF_LE_TX_PWR;
990 }
991
_search_reg_index(struct rtw89_dev * rtwdev,u8 mreg_num,u16 reg_type,u32 target)992 static u8 _search_reg_index(struct rtw89_dev *rtwdev, u8 mreg_num, u16 reg_type, u32 target)
993 {
994 const struct rtw89_chip_info *chip = rtwdev->chip;
995 u8 i;
996
997 for (i = 0; i < mreg_num; i++)
998 if (le16_to_cpu(chip->mon_reg[i].type) == reg_type &&
999 le32_to_cpu(chip->mon_reg[i].offset) == target) {
1000 return i;
1001 }
1002 return BTC_REG_NOTFOUND;
1003 }
1004
_get_reg_status(struct rtw89_dev * rtwdev,u8 type,u8 * val)1005 static void _get_reg_status(struct rtw89_dev *rtwdev, u8 type, u8 *val)
1006 {
1007 struct rtw89_btc *btc = &rtwdev->btc;
1008 const struct rtw89_btc_ver *ver = btc->ver;
1009 union rtw89_btc_module_info *md = &btc->mdinfo;
1010 union rtw89_btc_fbtc_mreg_val *pmreg;
1011 u32 pre_agc_addr = R_BTC_BB_PRE_AGC_S1;
1012 u32 reg_val;
1013 u8 idx, switch_type;
1014
1015 if (ver->fcxinit == 7)
1016 switch_type = md->md_v7.switch_type;
1017 else
1018 switch_type = md->md.switch_type;
1019
1020 if (btc->btg_pos == RF_PATH_A)
1021 pre_agc_addr = R_BTC_BB_PRE_AGC_S0;
1022
1023 switch (type) {
1024 case BTC_CSTATUS_TXDIV_POS:
1025 if (switch_type == BTC_SWITCH_INTERNAL)
1026 *val = BTC_ANT_DIV_MAIN;
1027 break;
1028 case BTC_CSTATUS_RXDIV_POS:
1029 if (switch_type == BTC_SWITCH_INTERNAL)
1030 *val = BTC_ANT_DIV_MAIN;
1031 break;
1032 case BTC_CSTATUS_BB_GNT_MUX:
1033 reg_val = rtw89_phy_read32(rtwdev, R_BTC_BB_BTG_RX);
1034 *val = !(reg_val & B_BTC_BB_GNT_MUX);
1035 break;
1036 case BTC_CSTATUS_BB_GNT_MUX_MON:
1037 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
1038 return;
1039
1040 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
1041 if (ver->fcxmreg == 1) {
1042 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
1043 REG_BB, R_BTC_BB_BTG_RX);
1044 if (idx == BTC_REG_NOTFOUND) {
1045 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
1046 } else {
1047 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]);
1048 *val = !(reg_val & B_BTC_BB_GNT_MUX);
1049 }
1050 } else if (ver->fcxmreg == 2) {
1051 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
1052 REG_BB, R_BTC_BB_BTG_RX);
1053 if (idx == BTC_REG_NOTFOUND) {
1054 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
1055 } else {
1056 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]);
1057 *val = !(reg_val & B_BTC_BB_GNT_MUX);
1058 }
1059 }
1060 break;
1061 case BTC_CSTATUS_BB_PRE_AGC:
1062 reg_val = rtw89_phy_read32(rtwdev, pre_agc_addr);
1063 reg_val &= B_BTC_BB_PRE_AGC_MASK;
1064 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1065 break;
1066 case BTC_CSTATUS_BB_PRE_AGC_MON:
1067 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
1068 return;
1069
1070 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
1071 if (ver->fcxmreg == 1) {
1072 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
1073 REG_BB, pre_agc_addr);
1074 if (idx == BTC_REG_NOTFOUND) {
1075 *val = BTC_PREAGC_NOTFOUND;
1076 } else {
1077 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]) &
1078 B_BTC_BB_PRE_AGC_MASK;
1079 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1080 }
1081 } else if (ver->fcxmreg == 2) {
1082 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
1083 REG_BB, pre_agc_addr);
1084 if (idx == BTC_REG_NOTFOUND) {
1085 *val = BTC_PREAGC_NOTFOUND;
1086 } else {
1087 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]) &
1088 B_BTC_BB_PRE_AGC_MASK;
1089 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1090 }
1091 }
1092 break;
1093 default:
1094 break;
1095 }
1096 }
1097
1098 #define BTC_RPT_HDR_SIZE 3
1099 #define BTC_CHK_WLSLOT_DRIFT_MAX 15
1100 #define BTC_CHK_BTSLOT_DRIFT_MAX 15
1101 #define BTC_CHK_HANG_MAX 3
1102
_chk_btc_err(struct rtw89_dev * rtwdev,u8 type,u32 cnt)1103 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt)
1104 {
1105 struct rtw89_btc *btc = &rtwdev->btc;
1106 struct rtw89_btc_cx *cx = &btc->cx;
1107 struct rtw89_btc_bt_info *bt = &cx->bt;
1108 struct rtw89_btc_wl_info *wl = &cx->wl;
1109 struct rtw89_btc_dm *dm = &btc->dm;
1110
1111 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1112 "[BTC], %s(): type:%d cnt:%d\n",
1113 __func__, type, cnt);
1114
1115 switch (type) {
1116 case BTC_DCNT_WL_FW_VER_MATCH:
1117 if ((wl->ver_info.fw_coex & 0xffff0000) !=
1118 rtwdev->chip->wlcx_desired) {
1119 wl->fw_ver_mismatch = true;
1120 dm->error.map.wl_ver_mismatch = true;
1121 } else {
1122 wl->fw_ver_mismatch = false;
1123 dm->error.map.wl_ver_mismatch = false;
1124 }
1125 break;
1126 case BTC_DCNT_RPT_HANG:
1127 if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map)
1128 dm->cnt_dm[BTC_DCNT_RPT_HANG]++;
1129 else
1130 dm->cnt_dm[BTC_DCNT_RPT_HANG] = 0;
1131
1132 if (dm->cnt_dm[BTC_DCNT_RPT_HANG] >= BTC_CHK_HANG_MAX)
1133 dm->error.map.wl_fw_hang = true;
1134 else
1135 dm->error.map.wl_fw_hang = false;
1136
1137 dm->cnt_dm[BTC_DCNT_RPT] = cnt;
1138 break;
1139 case BTC_DCNT_CYCLE_HANG:
1140 if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt &&
1141 (dm->tdma_now.type != CXTDMA_OFF ||
1142 dm->tdma_now.ext_ctrl == CXECTL_EXT))
1143 dm->cnt_dm[BTC_DCNT_CYCLE_HANG]++;
1144 else
1145 dm->cnt_dm[BTC_DCNT_CYCLE_HANG] = 0;
1146
1147 if (dm->cnt_dm[BTC_DCNT_CYCLE_HANG] >= BTC_CHK_HANG_MAX)
1148 dm->error.map.cycle_hang = true;
1149 else
1150 dm->error.map.cycle_hang = false;
1151
1152 dm->cnt_dm[BTC_DCNT_CYCLE] = cnt;
1153 break;
1154 case BTC_DCNT_W1_HANG:
1155 if (dm->cnt_dm[BTC_DCNT_W1] == cnt &&
1156 dm->tdma_now.type != CXTDMA_OFF)
1157 dm->cnt_dm[BTC_DCNT_W1_HANG]++;
1158 else
1159 dm->cnt_dm[BTC_DCNT_W1_HANG] = 0;
1160
1161 if (dm->cnt_dm[BTC_DCNT_W1_HANG] >= BTC_CHK_HANG_MAX)
1162 dm->error.map.w1_hang = true;
1163 else
1164 dm->error.map.w1_hang = false;
1165
1166 dm->cnt_dm[BTC_DCNT_W1] = cnt;
1167 break;
1168 case BTC_DCNT_B1_HANG:
1169 if (dm->cnt_dm[BTC_DCNT_B1] == cnt &&
1170 dm->tdma_now.type != CXTDMA_OFF)
1171 dm->cnt_dm[BTC_DCNT_B1_HANG]++;
1172 else
1173 dm->cnt_dm[BTC_DCNT_B1_HANG] = 0;
1174
1175 if (dm->cnt_dm[BTC_DCNT_B1_HANG] >= BTC_CHK_HANG_MAX)
1176 dm->error.map.b1_hang = true;
1177 else
1178 dm->error.map.b1_hang = false;
1179
1180 dm->cnt_dm[BTC_DCNT_B1] = cnt;
1181 break;
1182 case BTC_DCNT_E2G_HANG:
1183 if (dm->cnt_dm[BTC_DCNT_E2G] == cnt &&
1184 dm->tdma_now.ext_ctrl == CXECTL_EXT)
1185 dm->cnt_dm[BTC_DCNT_E2G_HANG]++;
1186 else
1187 dm->cnt_dm[BTC_DCNT_E2G_HANG] = 0;
1188
1189 if (dm->cnt_dm[BTC_DCNT_E2G_HANG] >= BTC_CHK_HANG_MAX)
1190 dm->error.map.wl_e2g_hang = true;
1191 else
1192 dm->error.map.wl_e2g_hang = false;
1193
1194 dm->cnt_dm[BTC_DCNT_E2G] = cnt;
1195 break;
1196 case BTC_DCNT_TDMA_NONSYNC:
1197 if (cnt != 0) /* if tdma not sync between drv/fw */
1198 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++;
1199 else
1200 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0;
1201
1202 if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX)
1203 dm->error.map.tdma_no_sync = true;
1204 else
1205 dm->error.map.tdma_no_sync = false;
1206 break;
1207 case BTC_DCNT_SLOT_NONSYNC:
1208 if (cnt != 0) /* if slot not sync between drv/fw */
1209 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++;
1210 else
1211 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0;
1212
1213 if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX)
1214 dm->error.map.slot_no_sync = true;
1215 else
1216 dm->error.map.slot_no_sync = false;
1217 break;
1218 case BTC_DCNT_BTTX_HANG:
1219 cnt = cx->cnt_bt[BTC_BCNT_LOPRI_TX];
1220
1221 if (cnt == 0 && bt->link_info.slave_role)
1222 dm->cnt_dm[BTC_DCNT_BTTX_HANG]++;
1223 else
1224 dm->cnt_dm[BTC_DCNT_BTTX_HANG] = 0;
1225
1226 if (dm->cnt_dm[BTC_DCNT_BTTX_HANG] >= BTC_CHK_HANG_MAX)
1227 dm->error.map.bt_tx_hang = true;
1228 else
1229 dm->error.map.bt_tx_hang = false;
1230 break;
1231 case BTC_DCNT_BTCNT_HANG:
1232 cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] +
1233 cx->cnt_bt[BTC_BCNT_HIPRI_TX] +
1234 cx->cnt_bt[BTC_BCNT_LOPRI_RX] +
1235 cx->cnt_bt[BTC_BCNT_LOPRI_TX];
1236
1237 if (cnt == 0)
1238 dm->cnt_dm[BTC_DCNT_BTCNT_HANG]++;
1239 else
1240 dm->cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
1241
1242 if ((dm->cnt_dm[BTC_DCNT_BTCNT_HANG] >= BTC_CHK_HANG_MAX &&
1243 bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_HANG] &&
1244 !bt->enable.now))
1245 _update_bt_scbd(rtwdev, false);
1246 break;
1247 case BTC_DCNT_WL_SLOT_DRIFT:
1248 if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX)
1249 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++;
1250 else
1251 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0;
1252
1253 if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1254 dm->error.map.wl_slot_drift = true;
1255 else
1256 dm->error.map.wl_slot_drift = false;
1257 break;
1258 case BTC_DCNT_BT_SLOT_DRIFT:
1259 if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX)
1260 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++;
1261 else
1262 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0;
1263
1264 if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1265 dm->error.map.bt_slot_drift = true;
1266 else
1267 dm->error.map.bt_slot_drift = false;
1268
1269 break;
1270 }
1271 }
1272
_update_bt_report(struct rtw89_dev * rtwdev,u8 rpt_type,u8 * pfinfo)1273 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo)
1274 {
1275 struct rtw89_btc *btc = &rtwdev->btc;
1276 const struct rtw89_btc_ver *ver = btc->ver;
1277 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1278 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
1279 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc;
1280 union rtw89_btc_fbtc_btver *pver = &btc->fwinfo.rpt_fbtc_btver.finfo;
1281 struct rtw89_btc_fbtc_btafh_v2 *pafh_v2 = NULL;
1282 struct rtw89_btc_fbtc_btafh_v7 *pafh_v7 = NULL;
1283 struct rtw89_btc_fbtc_btdevinfo *pdev = NULL;
1284 struct rtw89_btc_fbtc_btafh *pafh_v1 = NULL;
1285 struct rtw89_btc_fbtc_btscan_v1 *pscan_v1;
1286 struct rtw89_btc_fbtc_btscan_v2 *pscan_v2;
1287 struct rtw89_btc_fbtc_btscan_v7 *pscan_v7;
1288 bool scan_update = true;
1289 int i;
1290
1291 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1292 "[BTC], %s(): rpt_type:%d\n",
1293 __func__, rpt_type);
1294
1295 switch (rpt_type) {
1296 case BTC_RPT_TYPE_BT_VER:
1297 if (ver->fcxbtver == 7) {
1298 pver->v7 = *(struct rtw89_btc_fbtc_btver_v7 *)pfinfo;
1299 bt->ver_info.fw = le32_to_cpu(pver->v7.fw_ver);
1300 bt->ver_info.fw_coex = le32_get_bits(pver->v7.coex_ver,
1301 GENMASK(7, 0));
1302 bt->feature = le32_to_cpu(pver->v7.feature);
1303 } else {
1304 pver->v1 = *(struct rtw89_btc_fbtc_btver_v1 *)pfinfo;
1305 bt->ver_info.fw = le32_to_cpu(pver->v1.fw_ver);
1306 bt->ver_info.fw_coex = le32_get_bits(pver->v1.coex_ver,
1307 GENMASK(7, 0));
1308 bt->feature = le32_to_cpu(pver->v1.feature);
1309 }
1310 break;
1311 case BTC_RPT_TYPE_BT_SCAN:
1312 if (ver->fcxbtscan == 1) {
1313 pscan_v1 = (struct rtw89_btc_fbtc_btscan_v1 *)pfinfo;
1314 for (i = 0; i < BTC_SCAN_MAX1; i++) {
1315 bt->scan_info_v1[i] = pscan_v1->scan[i];
1316 if (bt->scan_info_v1[i].win == 0 &&
1317 bt->scan_info_v1[i].intvl == 0)
1318 scan_update = false;
1319 }
1320 } else if (ver->fcxbtscan == 2) {
1321 pscan_v2 = (struct rtw89_btc_fbtc_btscan_v2 *)pfinfo;
1322 for (i = 0; i < CXSCAN_MAX; i++) {
1323 bt->scan_info_v2[i] = pscan_v2->para[i];
1324 if ((pscan_v2->type & BIT(i)) &&
1325 pscan_v2->para[i].win == 0 &&
1326 pscan_v2->para[i].intvl == 0)
1327 scan_update = false;
1328 }
1329 } else if (ver->fcxbtscan == 7) {
1330 pscan_v7 = (struct rtw89_btc_fbtc_btscan_v7 *)pfinfo;
1331 for (i = 0; i < CXSCAN_MAX; i++) {
1332 bt->scan_info_v2[i] = pscan_v7->para[i];
1333 if ((pscan_v7->type & BIT(i)) &&
1334 pscan_v7->para[i].win == 0 &&
1335 pscan_v7->para[i].intvl == 0)
1336 scan_update = false;
1337 }
1338 }
1339 if (scan_update)
1340 bt->scan_info_update = 1;
1341 break;
1342 case BTC_RPT_TYPE_BT_AFH:
1343 if (ver->fcxbtafh == 2) {
1344 pafh_v2 = (struct rtw89_btc_fbtc_btafh_v2 *)pfinfo;
1345 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1346 memcpy(&bt_linfo->afh_map[0], pafh_v2->afh_l, 4);
1347 memcpy(&bt_linfo->afh_map[4], pafh_v2->afh_m, 4);
1348 memcpy(&bt_linfo->afh_map[8], pafh_v2->afh_h, 2);
1349 }
1350 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LE) {
1351 memcpy(&bt_linfo->afh_map_le[0], pafh_v2->afh_le_a, 4);
1352 memcpy(&bt_linfo->afh_map_le[4], pafh_v2->afh_le_b, 1);
1353 }
1354 } else if (ver->fcxbtafh == 7) {
1355 pafh_v7 = (struct rtw89_btc_fbtc_btafh_v7 *)pfinfo;
1356 if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1357 memcpy(&bt_linfo->afh_map[0], pafh_v7->afh_l, 4);
1358 memcpy(&bt_linfo->afh_map[4], pafh_v7->afh_m, 4);
1359 memcpy(&bt_linfo->afh_map[8], pafh_v7->afh_h, 2);
1360 }
1361 if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LE) {
1362 memcpy(&bt_linfo->afh_map_le[0], pafh_v7->afh_le_a, 4);
1363 memcpy(&bt_linfo->afh_map_le[4], pafh_v7->afh_le_b, 1);
1364 }
1365 } else if (ver->fcxbtafh == 1) {
1366 pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo;
1367 memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4);
1368 memcpy(&bt_linfo->afh_map[4], pafh_v1->afh_m, 4);
1369 memcpy(&bt_linfo->afh_map[8], pafh_v1->afh_h, 2);
1370 }
1371 break;
1372 case BTC_RPT_TYPE_BT_DEVICE:
1373 pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo;
1374 a2dp->device_name = le32_to_cpu(pdev->dev_name);
1375 a2dp->vendor_id = le16_to_cpu(pdev->vendor_id);
1376 a2dp->flush_time = le32_to_cpu(pdev->flush_time);
1377 break;
1378 default:
1379 break;
1380 }
1381 }
1382
rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev * rtwdev,u8 * index)1383 static void rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev *rtwdev, u8 *index)
1384 {
1385 struct rtw89_btc *btc = &rtwdev->btc;
1386 const struct rtw89_btc_ver *ver = btc->ver;
1387
1388 if (ver->fwevntrptl == 1)
1389 return;
1390
1391 if (*index <= __BTC_RPT_TYPE_V0_SAME)
1392 return;
1393 else if (*index <= __BTC_RPT_TYPE_V0_MAX)
1394 (*index)++;
1395 else
1396 *index = BTC_RPT_TYPE_MAX;
1397 }
1398
1399 #define BTC_LEAK_AP_TH 10
1400 #define BTC_CYSTA_CHK_PERIOD 100
1401
1402 struct rtw89_btc_prpt {
1403 u8 type;
1404 __le16 len;
1405 u8 content[];
1406 } __packed;
1407
_chk_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * prptbuf,u32 index)1408 static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
1409 struct rtw89_btc_btf_fwinfo *pfwinfo,
1410 u8 *prptbuf, u32 index)
1411 {
1412 struct rtw89_btc *btc = &rtwdev->btc;
1413 struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver;
1414 const struct rtw89_btc_ver *ver = btc->ver;
1415 struct rtw89_btc_dm *dm = &btc->dm;
1416 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
1417 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1418 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1419 union rtw89_btc_fbtc_rpt_ctrl_ver_info *prpt = NULL;
1420 union rtw89_btc_fbtc_cysta_info *pcysta = NULL;
1421 struct rtw89_btc_prpt *btc_prpt = NULL;
1422 void *rpt_content = NULL, *pfinfo = NULL;
1423 u8 rpt_type = 0;
1424 u16 wl_slot_set = 0, wl_slot_real = 0, val16;
1425 u32 trace_step = 0, rpt_len = 0, diff_t = 0;
1426 u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr;
1427 u8 i, val = 0, val1, val2;
1428
1429 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1430 "[BTC], %s(): index:%d\n",
1431 __func__, index);
1432
1433 if (!prptbuf) {
1434 pfwinfo->err[BTFRE_INVALID_INPUT]++;
1435 return 0;
1436 }
1437
1438 btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index];
1439 rpt_type = btc_prpt->type;
1440 rpt_len = le16_to_cpu(btc_prpt->len);
1441 rpt_content = btc_prpt->content;
1442
1443 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1444 "[BTC], %s(): rpt_type:%d\n",
1445 __func__, rpt_type);
1446
1447 rtw89_btc_fw_rpt_evnt_ver(rtwdev, &rpt_type);
1448
1449 switch (rpt_type) {
1450 case BTC_RPT_TYPE_CTRL:
1451 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
1452 prpt = &pfwinfo->rpt_ctrl.finfo;
1453 if (ver->fcxbtcrpt == 1) {
1454 pfinfo = &pfwinfo->rpt_ctrl.finfo.v1;
1455 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v1);
1456 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v1.fver;
1457 } else if (ver->fcxbtcrpt == 4) {
1458 pfinfo = &pfwinfo->rpt_ctrl.finfo.v4;
1459 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v4);
1460 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v4.fver;
1461 } else if (ver->fcxbtcrpt == 5) {
1462 pfinfo = &pfwinfo->rpt_ctrl.finfo.v5;
1463 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v5);
1464 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v5.fver;
1465 } else if (ver->fcxbtcrpt == 105) {
1466 pfinfo = &pfwinfo->rpt_ctrl.finfo.v105;
1467 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v105);
1468 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v105.fver;
1469 pcinfo->req_fver = 5;
1470 break;
1471 } else if (ver->fcxbtcrpt == 8) {
1472 pfinfo = &pfwinfo->rpt_ctrl.finfo.v8;
1473 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8);
1474 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v8.fver;
1475 } else if (ver->fcxbtcrpt == 7) {
1476 pfinfo = &pfwinfo->rpt_ctrl.finfo.v7;
1477 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v7);
1478 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v7.fver;
1479 } else {
1480 goto err;
1481 }
1482 pcinfo->req_fver = ver->fcxbtcrpt;
1483 break;
1484 case BTC_RPT_TYPE_TDMA:
1485 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
1486 if (ver->fcxtdma == 1) {
1487 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
1488 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1);
1489 fwsubver->fcxtdma = 0;
1490 } else if (ver->fcxtdma == 3 || ver->fcxtdma == 7) {
1491 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3;
1492 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3);
1493 fwsubver->fcxtdma = pfwinfo->rpt_fbtc_tdma.finfo.v3.fver;
1494 } else {
1495 goto err;
1496 }
1497 pcinfo->req_fver = ver->fcxtdma;
1498 break;
1499 case BTC_RPT_TYPE_SLOT:
1500 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
1501 if (ver->fcxslots == 1) {
1502 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1;
1503 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v1);
1504 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v1.fver;
1505 } else if (ver->fcxslots == 7) {
1506 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7;
1507 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v7);
1508 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v7.fver;
1509 } else {
1510 goto err;
1511 }
1512 pcinfo->req_fver = ver->fcxslots;
1513 break;
1514 case BTC_RPT_TYPE_CYSTA:
1515 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
1516 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
1517 if (ver->fcxcysta == 2) {
1518 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
1519 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
1520 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v2);
1521 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v2.fver;
1522 } else if (ver->fcxcysta == 3) {
1523 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
1524 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
1525 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v3);
1526 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v3.fver;
1527 } else if (ver->fcxcysta == 4) {
1528 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
1529 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
1530 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v4);
1531 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v4.fver;
1532 } else if (ver->fcxcysta == 5) {
1533 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
1534 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
1535 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v5);
1536 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v5.fver;
1537 } else if (ver->fcxcysta == 7) {
1538 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
1539 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
1540 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v7);
1541 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v7.fver;
1542 } else {
1543 goto err;
1544 }
1545 pcinfo->req_fver = ver->fcxcysta;
1546 break;
1547 case BTC_RPT_TYPE_STEP:
1548 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
1549 if (ver->fcxctrl != 7)
1550 trace_step = btc->ctrl.ctrl.trace_step;
1551
1552 if (ver->fcxstep == 2) {
1553 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v2;
1554 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) *
1555 trace_step +
1556 offsetof(struct rtw89_btc_fbtc_steps_v2, step);
1557 fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v2.fver;
1558 } else if (ver->fcxstep == 3) {
1559 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3;
1560 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) *
1561 trace_step +
1562 offsetof(struct rtw89_btc_fbtc_steps_v3, step);
1563 fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v3.fver;
1564 } else {
1565 goto err;
1566 }
1567 pcinfo->req_fver = ver->fcxstep;
1568 break;
1569 case BTC_RPT_TYPE_NULLSTA:
1570 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
1571 if (ver->fcxnullsta == 1) {
1572 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1;
1573 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v1);
1574 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v1.fver;
1575 } else if (ver->fcxnullsta == 2) {
1576 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2;
1577 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v2);
1578 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v2.fver;
1579 } else if (ver->fcxnullsta == 7) {
1580 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v7;
1581 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v7);
1582 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v7.fver;
1583 } else {
1584 goto err;
1585 }
1586 pcinfo->req_fver = ver->fcxnullsta;
1587 break;
1588 case BTC_RPT_TYPE_MREG:
1589 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
1590 if (ver->fcxmreg == 1) {
1591 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
1592 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v1);
1593 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v1.fver;
1594 } else if (ver->fcxmreg == 2) {
1595 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
1596 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v2);
1597 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v2.fver;
1598 } else if (ver->fcxmreg == 7) {
1599 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
1600 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v7);
1601 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v7.fver;
1602 } else {
1603 goto err;
1604 }
1605 pcinfo->req_fver = ver->fcxmreg;
1606 break;
1607 case BTC_RPT_TYPE_GPIO_DBG:
1608 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
1609 if (ver->fcxgpiodbg == 7) {
1610 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7;
1611 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7);
1612 fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7.fver;
1613 } else {
1614 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1;
1615 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1);
1616 fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1.fver;
1617 }
1618 pcinfo->req_fver = ver->fcxgpiodbg;
1619 break;
1620 case BTC_RPT_TYPE_BT_VER:
1621 pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
1622 if (ver->fcxbtver == 1) {
1623 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v1;
1624 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v1);
1625 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v1.fver;
1626 } else if (ver->fcxbtver == 7) {
1627 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v7;
1628 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v7);
1629 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v7.fver;
1630 }
1631 pcinfo->req_fver = ver->fcxbtver;
1632 break;
1633 case BTC_RPT_TYPE_BT_SCAN:
1634 pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
1635 if (ver->fcxbtscan == 1) {
1636 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1;
1637 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v1);
1638 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v1.fver;
1639 } else if (ver->fcxbtscan == 2) {
1640 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2;
1641 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v2);
1642 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v2.fver;
1643 } else if (ver->fcxbtscan == 7) {
1644 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v7;
1645 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v7);
1646 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v7.fver;
1647 } else {
1648 goto err;
1649 }
1650 pcinfo->req_fver = ver->fcxbtscan;
1651 break;
1652 case BTC_RPT_TYPE_BT_AFH:
1653 pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
1654 if (ver->fcxbtafh == 1) {
1655 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1;
1656 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v1);
1657 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v1.fver;
1658 } else if (ver->fcxbtafh == 2) {
1659 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2;
1660 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2);
1661 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v2.fver;
1662 } else if (ver->fcxbtafh == 7) {
1663 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v7;
1664 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v7);
1665 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v7.fver;
1666 } else {
1667 goto err;
1668 }
1669 pcinfo->req_fver = ver->fcxbtafh;
1670 break;
1671 case BTC_RPT_TYPE_BT_DEVICE:
1672 pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
1673 pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo;
1674 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo);
1675 fwsubver->fcxbtdevinfo = pfwinfo->rpt_fbtc_btdev.finfo.fver;
1676 pcinfo->req_fver = ver->fcxbtdevinfo;
1677 break;
1678 default:
1679 pfwinfo->err[BTFRE_UNDEF_TYPE]++;
1680 return 0;
1681 }
1682
1683 pcinfo->rx_len = rpt_len;
1684 pcinfo->rx_cnt++;
1685
1686 if (rpt_len != pcinfo->req_len) {
1687 if (rpt_type < BTC_RPT_TYPE_MAX)
1688 pfwinfo->len_mismch |= (0x1 << rpt_type);
1689 else
1690 pfwinfo->len_mismch |= BIT(31);
1691 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1692 "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n",
1693 __func__, rpt_type, rpt_len, pcinfo->req_len);
1694
1695 pcinfo->valid = 0;
1696 return 0;
1697 } else if (!pfinfo || !rpt_content || !pcinfo->req_len) {
1698 pfwinfo->err[BTFRE_EXCEPTION]++;
1699 pcinfo->valid = 0;
1700 return 0;
1701 }
1702
1703 memcpy(pfinfo, rpt_content, pcinfo->req_len);
1704 pcinfo->valid = 1;
1705
1706 switch (rpt_type) {
1707 case BTC_RPT_TYPE_CTRL:
1708 if (ver->fcxbtcrpt == 1) {
1709 prpt->v1 = pfwinfo->rpt_ctrl.finfo.v1;
1710 btc->fwinfo.rpt_en_map = prpt->v1.rpt_enable;
1711 wl->ver_info.fw_coex = prpt->v1.wl_fw_coex_ver;
1712 wl->ver_info.fw = prpt->v1.wl_fw_ver;
1713 dm->wl_fw_cx_offload = !!prpt->v1.wl_fw_cx_offload;
1714
1715 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1716 pfwinfo->event[BTF_EVNT_RPT]);
1717
1718 /* To avoid I/O if WL LPS or power-off */
1719 if (wl->status.map.lps != BTC_LPS_RF_OFF &&
1720 !wl->status.map.rf_off) {
1721 rtwdev->chip->ops->btc_update_bt_cnt(rtwdev);
1722 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1723
1724 btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1725 rtw89_mac_get_plt_cnt(rtwdev,
1726 RTW89_MAC_0);
1727 }
1728 } else if (ver->fcxbtcrpt == 4) {
1729 prpt->v4 = pfwinfo->rpt_ctrl.finfo.v4;
1730 btc->fwinfo.rpt_en_map = le32_to_cpu(prpt->v4.rpt_info.en);
1731 wl->ver_info.fw_coex = le32_to_cpu(prpt->v4.wl_fw_info.cx_ver);
1732 wl->ver_info.fw = le32_to_cpu(prpt->v4.wl_fw_info.fw_ver);
1733 dm->wl_fw_cx_offload = !!le32_to_cpu(prpt->v4.wl_fw_info.cx_offload);
1734
1735 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1736 memcpy(&dm->gnt.band[i], &prpt->v4.gnt_val[i],
1737 sizeof(dm->gnt.band[i]));
1738
1739 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1740 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_TX]);
1741 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1742 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_RX]);
1743 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1744 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_TX]);
1745 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1746 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_RX]);
1747 btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1748 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_POLLUTED]);
1749
1750 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1751 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1752 pfwinfo->event[BTF_EVNT_RPT]);
1753
1754 if (le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
1755 bt->rfk_info.map.timeout = 1;
1756 else
1757 bt->rfk_info.map.timeout = 0;
1758
1759 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1760 } else if (ver->fcxbtcrpt == 5) {
1761 prpt->v5 = pfwinfo->rpt_ctrl.finfo.v5;
1762 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v5.rpt_info.en);
1763 wl->ver_info.fw_coex = le32_to_cpu(prpt->v5.rpt_info.cx_ver);
1764 wl->ver_info.fw = le32_to_cpu(prpt->v5.rpt_info.fw_ver);
1765 dm->wl_fw_cx_offload = 0;
1766
1767 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1768 memcpy(&dm->gnt.band[i], &prpt->v5.gnt_val[i][0],
1769 sizeof(dm->gnt.band[i]));
1770
1771 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1772 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_TX]);
1773 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1774 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_RX]);
1775 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1776 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_TX]);
1777 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1778 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_RX]);
1779 btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1780 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_POLLUTED]);
1781
1782 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1783 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1784 pfwinfo->event[BTF_EVNT_RPT]);
1785
1786 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1787 } else if (ver->fcxbtcrpt == 105) {
1788 prpt->v105 = pfwinfo->rpt_ctrl.finfo.v105;
1789 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v105.rpt_info.en);
1790 wl->ver_info.fw_coex = le32_to_cpu(prpt->v105.rpt_info.cx_ver);
1791 wl->ver_info.fw = le32_to_cpu(prpt->v105.rpt_info.fw_ver);
1792 dm->wl_fw_cx_offload = 0;
1793
1794 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1795 memcpy(&dm->gnt.band[i], &prpt->v105.gnt_val[i][0],
1796 sizeof(dm->gnt.band[i]));
1797
1798 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1799 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_TX_V105]);
1800 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1801 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_RX_V105]);
1802 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1803 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_TX_V105]);
1804 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1805 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_RX_V105]);
1806 btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1807 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1808
1809 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1810 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1811 pfwinfo->event[BTF_EVNT_RPT]);
1812
1813 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1814 } else if (ver->fcxbtcrpt == 7) {
1815 prpt->v7 = pfwinfo->rpt_ctrl.finfo.v7;
1816 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v7.rpt_info.en);
1817 wl->ver_info.fw_coex = le32_to_cpu(prpt->v7.rpt_info.cx_ver);
1818 wl->ver_info.fw = le32_to_cpu(prpt->v7.rpt_info.fw_ver);
1819
1820 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1821 memcpy(&dm->gnt.band[i], &prpt->v7.gnt_val[i][0],
1822 sizeof(dm->gnt.band[i]));
1823
1824 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1825 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_TX_V105]);
1826 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1827 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_RX_V105]);
1828 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1829 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_TX_V105]);
1830 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1831 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_RX_V105]);
1832
1833 val1 = le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1834 if (val1 > btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW])
1835 val1 -= btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]; /* diff */
1836
1837 btc->cx.cnt_bt[BTC_BCNT_POLUT_DIFF] = val1;
1838 btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW] =
1839 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1840
1841 val1 = pfwinfo->event[BTF_EVNT_RPT];
1842 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1843 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
1844 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
1845 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
1846 } else if (ver->fcxbtcrpt == 8) {
1847 prpt->v8 = pfwinfo->rpt_ctrl.finfo.v8;
1848 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v8.rpt_info.en);
1849 wl->ver_info.fw_coex = le32_to_cpu(prpt->v8.rpt_info.cx_ver);
1850 wl->ver_info.fw = le32_to_cpu(prpt->v8.rpt_info.fw_ver);
1851
1852 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1853 memcpy(&dm->gnt.band[i], &prpt->v8.gnt_val[i][0],
1854 sizeof(dm->gnt.band[i]));
1855
1856 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1857 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_TX_V105]);
1858 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1859 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_RX_V105]);
1860 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1861 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_TX_V105]);
1862 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1863 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_RX_V105]);
1864
1865 val1 = le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1866 if (val1 > btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW])
1867 val1 -= btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]; /* diff */
1868
1869 btc->cx.cnt_bt[BTC_BCNT_POLUT_DIFF] = val1;
1870 btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW] =
1871 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1872
1873 val1 = pfwinfo->event[BTF_EVNT_RPT];
1874 if (((prpt->v8.rpt_len_max_h << 8) +
1875 prpt->v8.rpt_len_max_l) != ver->info_buf)
1876 dm->error.map.h2c_c2h_buffer_mismatch = true;
1877 else
1878 dm->error.map.h2c_c2h_buffer_mismatch = false;
1879
1880 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1881 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
1882 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
1883 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
1884 } else {
1885 goto err;
1886 }
1887 break;
1888 case BTC_RPT_TYPE_TDMA:
1889 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1890 "[BTC], %s(): check %d %zu\n", __func__,
1891 BTC_DCNT_TDMA_NONSYNC,
1892 sizeof(dm->tdma_now));
1893 if (ver->fcxtdma == 1)
1894 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
1895 memcmp(&dm->tdma_now,
1896 &pfwinfo->rpt_fbtc_tdma.finfo.v1,
1897 sizeof(dm->tdma_now)));
1898 else if (ver->fcxtdma == 3 || ver->fcxtdma == 7)
1899 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
1900 memcmp(&dm->tdma_now,
1901 &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma,
1902 sizeof(dm->tdma_now)));
1903 else
1904 goto err;
1905 break;
1906 case BTC_RPT_TYPE_SLOT:
1907 if (ver->fcxslots == 7) {
1908 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1909 "[BTC], %s(): check %d %zu\n",
1910 __func__, BTC_DCNT_SLOT_NONSYNC,
1911 sizeof(dm->slot_now.v7));
1912 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
1913 memcmp(dm->slot_now.v7,
1914 pfwinfo->rpt_fbtc_slots.finfo.v7.slot,
1915 sizeof(dm->slot_now.v7)));
1916 } else if (ver->fcxslots == 1) {
1917 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1918 "[BTC], %s(): check %d %zu\n",
1919 __func__, BTC_DCNT_SLOT_NONSYNC,
1920 sizeof(dm->slot_now.v1));
1921 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
1922 memcmp(dm->slot_now.v1,
1923 pfwinfo->rpt_fbtc_slots.finfo.v1.slot,
1924 sizeof(dm->slot_now.v1)));
1925 }
1926 break;
1927 case BTC_RPT_TYPE_CYSTA:
1928 if (ver->fcxcysta == 2) {
1929 if (le16_to_cpu(pcysta->v2.cycles) < BTC_CYSTA_CHK_PERIOD)
1930 break;
1931 /* Check Leak-AP */
1932 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) != 0 &&
1933 le32_to_cpu(pcysta->v2.leakrx_cnt) != 0 && dm->tdma_now.rxflctrl) {
1934 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) <
1935 BTC_LEAK_AP_TH * le32_to_cpu(pcysta->v2.leakrx_cnt))
1936 dm->leak_ap = 1;
1937 }
1938
1939 /* Check diff time between WL slot and W1/E2G slot */
1940 if (dm->tdma_now.type == CXTDMA_OFF &&
1941 dm->tdma_now.ext_ctrl == CXECTL_EXT) {
1942 if (ver->fcxslots == 1)
1943 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_E2G].dur);
1944 else if (ver->fcxslots == 7)
1945 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_E2G].dur);
1946 } else {
1947 if (ver->fcxslots == 1)
1948 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1949 else if (ver->fcxslots == 7)
1950 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1951 }
1952
1953 if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) {
1954 diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set;
1955 _chk_btc_err(rtwdev,
1956 BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1957 }
1958
1959 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1960 le32_to_cpu(pcysta->v2.slot_cnt[CXST_W1]));
1961 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1962 le32_to_cpu(pcysta->v2.slot_cnt[CXST_B1]));
1963 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1964 le16_to_cpu(pcysta->v2.cycles));
1965 } else if (ver->fcxcysta == 3) {
1966 if (le16_to_cpu(pcysta->v3.cycles) < BTC_CYSTA_CHK_PERIOD)
1967 break;
1968
1969 cnt_leak_slot = le32_to_cpu(pcysta->v3.slot_cnt[CXST_LK]);
1970 cnt_rx_imr = le32_to_cpu(pcysta->v3.leak_slot.cnt_rximr);
1971
1972 /* Check Leak-AP */
1973 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
1974 dm->tdma_now.rxflctrl) {
1975 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
1976 dm->leak_ap = 1;
1977 }
1978
1979 /* Check diff time between real WL slot and W1 slot */
1980 if (dm->tdma_now.type == CXTDMA_OFF) {
1981 if (ver->fcxslots == 1)
1982 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1983 else if (ver->fcxslots == 7)
1984 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1985 wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]);
1986 if (wl_slot_real > wl_slot_set) {
1987 diff_t = wl_slot_real - wl_slot_set;
1988 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1989 }
1990 }
1991
1992 /* Check diff time between real BT slot and EBT/E5G slot */
1993 if (dm->tdma_now.type == CXTDMA_OFF &&
1994 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
1995 btc->bt_req_len != 0) {
1996 bt_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_BT]);
1997 if (btc->bt_req_len > bt_slot_real) {
1998 diff_t = btc->bt_req_len - bt_slot_real;
1999 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2000 }
2001 }
2002
2003 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2004 le32_to_cpu(pcysta->v3.slot_cnt[CXST_W1]));
2005 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2006 le32_to_cpu(pcysta->v3.slot_cnt[CXST_B1]));
2007 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2008 le16_to_cpu(pcysta->v3.cycles));
2009 } else if (ver->fcxcysta == 4) {
2010 if (le16_to_cpu(pcysta->v4.cycles) < BTC_CYSTA_CHK_PERIOD)
2011 break;
2012
2013 cnt_leak_slot = le16_to_cpu(pcysta->v4.slot_cnt[CXST_LK]);
2014 cnt_rx_imr = le32_to_cpu(pcysta->v4.leak_slot.cnt_rximr);
2015
2016 /* Check Leak-AP */
2017 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
2018 dm->tdma_now.rxflctrl) {
2019 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
2020 dm->leak_ap = 1;
2021 }
2022
2023 /* Check diff time between real WL slot and W1 slot */
2024 if (dm->tdma_now.type == CXTDMA_OFF) {
2025 if (ver->fcxslots == 1)
2026 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2027 else if (ver->fcxslots == 7)
2028 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2029 wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]);
2030 if (wl_slot_real > wl_slot_set) {
2031 diff_t = wl_slot_real - wl_slot_set;
2032 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2033 }
2034 }
2035
2036 /* Check diff time between real BT slot and EBT/E5G slot */
2037 if (dm->tdma_now.type == CXTDMA_OFF &&
2038 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
2039 btc->bt_req_len != 0) {
2040 bt_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_BT]);
2041
2042 if (btc->bt_req_len > bt_slot_real) {
2043 diff_t = btc->bt_req_len - bt_slot_real;
2044 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2045 }
2046 }
2047
2048 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2049 le16_to_cpu(pcysta->v4.slot_cnt[CXST_W1]));
2050 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2051 le16_to_cpu(pcysta->v4.slot_cnt[CXST_B1]));
2052 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2053 le16_to_cpu(pcysta->v4.cycles));
2054 } else if (ver->fcxcysta == 5) {
2055 if (dm->fddt_train == BTC_FDDT_ENABLE)
2056 break;
2057 cnt_leak_slot = le16_to_cpu(pcysta->v5.slot_cnt[CXST_LK]);
2058 cnt_rx_imr = le32_to_cpu(pcysta->v5.leak_slot.cnt_rximr);
2059
2060 /* Check Leak-AP */
2061 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
2062 dm->tdma_now.rxflctrl) {
2063 if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD &&
2064 cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
2065 dm->leak_ap = 1;
2066 }
2067
2068 /* Check diff time between real WL slot and W1 slot */
2069 if (dm->tdma_now.type == CXTDMA_OFF) {
2070 if (ver->fcxslots == 1)
2071 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2072 else if (ver->fcxslots == 7)
2073 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2074 wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]);
2075
2076 if (wl_slot_real > wl_slot_set)
2077 diff_t = wl_slot_real - wl_slot_set;
2078 else
2079 diff_t = wl_slot_set - wl_slot_real;
2080 }
2081 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2082
2083 /* Check diff time between real BT slot and EBT/E5G slot */
2084 bt_slot_set = btc->bt_req_len;
2085 bt_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_BT]);
2086 diff_t = 0;
2087 if (dm->tdma_now.type == CXTDMA_OFF &&
2088 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
2089 bt_slot_set != 0) {
2090 if (bt_slot_set > bt_slot_real)
2091 diff_t = bt_slot_set - bt_slot_real;
2092 else
2093 diff_t = bt_slot_real - bt_slot_set;
2094 }
2095
2096 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2097 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
2098 le16_to_cpu(pcysta->v5.slot_cnt[CXST_E2G]));
2099 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2100 le16_to_cpu(pcysta->v5.slot_cnt[CXST_W1]));
2101 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2102 le16_to_cpu(pcysta->v5.slot_cnt[CXST_B1]));
2103 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2104 le16_to_cpu(pcysta->v5.cycles));
2105 } else if (ver->fcxcysta == 7) {
2106 if (dm->fddt_train == BTC_FDDT_ENABLE)
2107 break;
2108
2109 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
2110
2111 if (dm->tdma_now.type != CXTDMA_OFF) {
2112 /* Check diff time between real WL slot and W1 slot */
2113 val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_WL]);
2114 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, val16);
2115
2116 /* Check Leak-AP */
2117 val1 = le32_to_cpu(pcysta->v7.leak_slot.cnt_rximr) *
2118 BTC_LEAK_AP_TH;
2119 val2 = le16_to_cpu(pcysta->v7.slot_cnt[CXST_LK]);
2120
2121 val16 = le16_to_cpu(pcysta->v7.cycles);
2122 if (dm->tdma_now.rxflctrl &&
2123 val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
2124 dm->leak_ap = 1;
2125 } else if (dm->tdma_now.ext_ctrl == CXECTL_EXT) {
2126 val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_BT]);
2127 /* Check diff between real BT slot and EBT/E5G slot */
2128 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, val16);
2129
2130 /* Check bt slot length for P2P mode*/
2131 val1 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt_timeout) *
2132 BTC_SLOT_REQ_TH;
2133 val2 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt);
2134
2135 val16 = le16_to_cpu(pcysta->v7.cycles);
2136 if (val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
2137 dm->slot_req_more = 1;
2138 else if (bt->link_info.status.map.connect == 0)
2139 dm->slot_req_more = 0;
2140 }
2141
2142 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
2143 le16_to_cpu(pcysta->v7.slot_cnt[CXST_E2G]));
2144 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2145 le16_to_cpu(pcysta->v7.slot_cnt[CXST_W1]));
2146 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2147 le16_to_cpu(pcysta->v7.slot_cnt[CXST_B1]));
2148
2149 /* "BT_SLOT_FLOOD" error-check MUST before "CYCLE_HANG" */
2150 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_FLOOD,
2151 le16_to_cpu(pcysta->v7.cycles));
2152 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2153 le16_to_cpu(pcysta->v7.cycles));
2154 } else {
2155 goto err;
2156 }
2157 break;
2158 case BTC_RPT_TYPE_MREG:
2159 if (ver->fcxmreg == 7)
2160 break;
2161 _get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX_MON, &val);
2162 if (dm->wl_btg_rx == BTC_BTGCTRL_BB_GNT_FWCTRL)
2163 dm->wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_FWCTRL;
2164 else
2165 dm->wl_btg_rx_rb = val;
2166
2167 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC_MON, &val);
2168 if (dm->wl_pre_agc == BTC_PREAGC_BB_FWCTRL)
2169 dm->wl_pre_agc_rb = BTC_PREAGC_BB_FWCTRL;
2170 else
2171 dm->wl_pre_agc_rb = val;
2172 break;
2173 case BTC_RPT_TYPE_BT_VER:
2174 case BTC_RPT_TYPE_BT_SCAN:
2175 case BTC_RPT_TYPE_BT_AFH:
2176 case BTC_RPT_TYPE_BT_DEVICE:
2177 _update_bt_report(rtwdev, rpt_type, pfinfo);
2178 break;
2179 }
2180 return (rpt_len + BTC_RPT_HDR_SIZE);
2181
2182 err:
2183 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2184 "[BTC], %s(): Undefined version for type=%d\n", __func__, rpt_type);
2185 return 0;
2186 }
2187
_parse_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * pbuf,u32 buf_len)2188 static void _parse_btc_report(struct rtw89_dev *rtwdev,
2189 struct rtw89_btc_btf_fwinfo *pfwinfo,
2190 u8 *pbuf, u32 buf_len)
2191 {
2192 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
2193 struct rtw89_btc_prpt *btc_prpt = NULL;
2194 u32 index = 0, rpt_len = 0;
2195
2196 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2197 "[BTC], %s(): buf_len:%d\n",
2198 __func__, buf_len);
2199
2200 while (pbuf) {
2201 btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index];
2202 if (index + 2 >= ver->info_buf)
2203 break;
2204 /* At least 3 bytes: type(1) & len(2) */
2205 rpt_len = le16_to_cpu(btc_prpt->len);
2206 if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len)
2207 break;
2208
2209 rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index);
2210 if (!rpt_len)
2211 break;
2212 index += rpt_len;
2213 }
2214 }
2215
2216 #define BTC_TLV_HDR_LEN 2
2217 #define BTC_TLV_HDR_LEN_V7 3
2218
_append_tdma(struct rtw89_dev * rtwdev)2219 static void _append_tdma(struct rtw89_dev *rtwdev)
2220 {
2221 struct rtw89_btc *btc = &rtwdev->btc;
2222 const struct rtw89_btc_ver *ver = btc->ver;
2223 struct rtw89_btc_dm *dm = &btc->dm;
2224 struct rtw89_btc_btf_tlv *tlv;
2225 struct rtw89_btc_btf_tlv_v7 *tlv_v7;
2226 struct rtw89_btc_fbtc_tdma *v;
2227 struct rtw89_btc_fbtc_tdma_v3 *v3;
2228 u16 len = btc->policy_len;
2229
2230 if (!btc->update_policy_force &&
2231 !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) {
2232 rtw89_debug(rtwdev,
2233 RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n",
2234 __func__);
2235 return;
2236 }
2237
2238 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
2239 tlv->type = CXPOLICY_TDMA;
2240 if (ver->fcxtdma == 1) {
2241 v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0];
2242 tlv->len = sizeof(*v);
2243 *v = dm->tdma;
2244 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
2245 } else if (ver->fcxtdma == 7) {
2246 tlv_v7 = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2247 tlv_v7->len = sizeof(dm->tdma);
2248 tlv_v7->ver = ver->fcxtdma;
2249 tlv_v7->type = CXPOLICY_TDMA;
2250 memcpy(tlv_v7->val, &dm->tdma, tlv_v7->len);
2251 btc->policy_len += BTC_TLV_HDR_LEN_V7 + tlv_v7->len;
2252 } else {
2253 tlv->len = sizeof(*v3);
2254 v3 = (struct rtw89_btc_fbtc_tdma_v3 *)&tlv->val[0];
2255 v3->fver = ver->fcxtdma;
2256 v3->tdma = dm->tdma;
2257 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v3);
2258 }
2259
2260 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2261 "[BTC], %s(): type:%d, rxflctrl=%d, txpause=%d, wtgle_n=%d, leak_n=%d, ext_ctrl=%d\n",
2262 __func__, dm->tdma.type, dm->tdma.rxflctrl,
2263 dm->tdma.txpause, dm->tdma.wtgle_n, dm->tdma.leak_n,
2264 dm->tdma.ext_ctrl);
2265 }
2266
_append_slot_v1(struct rtw89_dev * rtwdev)2267 static void _append_slot_v1(struct rtw89_dev *rtwdev)
2268 {
2269 struct rtw89_btc *btc = &rtwdev->btc;
2270 struct rtw89_btc_dm *dm = &btc->dm;
2271 struct rtw89_btc_btf_tlv *tlv = NULL;
2272 struct btc_fbtc_1slot *v = NULL;
2273 u16 len = 0;
2274 u8 i, cnt = 0;
2275
2276 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2277 "[BTC], %s(): A:btc->policy_len = %d\n",
2278 __func__, btc->policy_len);
2279
2280 for (i = 0; i < CXST_MAX; i++) {
2281 if (!btc->update_policy_force &&
2282 !memcmp(&dm->slot.v1[i], &dm->slot_now.v1[i],
2283 sizeof(dm->slot.v1[i])))
2284 continue;
2285
2286 len = btc->policy_len;
2287
2288 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
2289 v = (struct btc_fbtc_1slot *)&tlv->val[0];
2290 tlv->type = CXPOLICY_SLOT;
2291 tlv->len = sizeof(*v);
2292
2293 v->fver = btc->ver->fcxslots;
2294 v->sid = i;
2295 v->slot = dm->slot.v1[i];
2296
2297 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2298 "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n",
2299 __func__, i, dm->slot.v1[i].dur, dm->slot.v1[i].cxtbl,
2300 dm->slot.v1[i].cxtype);
2301 cnt++;
2302
2303 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
2304 }
2305
2306 if (cnt > 0)
2307 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2308 "[BTC], %s(): slot update (cnt=%d)!!\n",
2309 __func__, cnt);
2310 }
2311
_append_slot_v7(struct rtw89_dev * rtwdev)2312 static void _append_slot_v7(struct rtw89_dev *rtwdev)
2313 {
2314 struct rtw89_btc_btf_tlv_v7 *tlv = NULL;
2315 struct rtw89_btc *btc = &rtwdev->btc;
2316 struct rtw89_btc_dm *dm = &btc->dm;
2317 u8 i, cnt = 0;
2318 u16 len;
2319
2320 for (i = 0; i < CXST_MAX; i++) {
2321 if (!btc->update_policy_force &&
2322 !memcmp(&dm->slot.v7[i], &dm->slot_now.v7[i],
2323 sizeof(dm->slot.v7[i])))
2324 continue;
2325
2326 len = btc->policy_len;
2327
2328 if (!tlv) {
2329 if ((len + BTC_TLV_HDR_LEN_V7) > RTW89_BTC_POLICY_MAXLEN) {
2330 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2331 "[BTC], %s(): buff overflow!\n", __func__);
2332 break;
2333 }
2334
2335 tlv = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2336 tlv->type = CXPOLICY_SLOT;
2337 tlv->ver = btc->ver->fcxslots;
2338 tlv->len = sizeof(dm->slot.v7[0]) + BTC_TLV_SLOT_ID_LEN_V7;
2339 len += BTC_TLV_HDR_LEN_V7;
2340 }
2341
2342 if ((len + (u16)tlv->len) > RTW89_BTC_POLICY_MAXLEN) {
2343 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2344 "[BTC], %s(): buff overflow!\n", __func__);
2345 break;
2346 }
2347
2348 btc->policy[len] = i; /* slot-id */
2349 memcpy(&btc->policy[len + 1], &dm->slot.v7[i],
2350 sizeof(dm->slot.v7[0]));
2351 len += tlv->len;
2352
2353 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2354 "[BTC], %s: policy_len=%d, slot-%d: dur=%d, type=%d, table=0x%08x\n",
2355 __func__, btc->policy_len, i, dm->slot.v7[i].dur,
2356 dm->slot.v7[i].cxtype, dm->slot.v7[i].cxtbl);
2357 cnt++;
2358 btc->policy_len = len; /* update total length */
2359 }
2360
2361 if (cnt > 0)
2362 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2363 "[BTC], %s: slot update (cnt=%d, len=%d)!!\n",
2364 __func__, cnt, btc->policy_len);
2365 }
2366
_append_slot(struct rtw89_dev * rtwdev)2367 static void _append_slot(struct rtw89_dev *rtwdev)
2368 {
2369 struct rtw89_btc *btc = &rtwdev->btc;
2370
2371 if (btc->ver->fcxslots == 7)
2372 _append_slot_v7(rtwdev);
2373 else
2374 _append_slot_v1(rtwdev);
2375 }
2376
rtw89_btc_fw_rpt_ver(struct rtw89_dev * rtwdev,u32 rpt_map)2377 static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map)
2378 {
2379 struct rtw89_btc *btc = &rtwdev->btc;
2380 const struct rtw89_btc_ver *ver = btc->ver;
2381 u32 bit_map = 0;
2382
2383 switch (rpt_map) {
2384 case RPT_EN_TDMA:
2385 bit_map = BIT(0);
2386 break;
2387 case RPT_EN_CYCLE:
2388 bit_map = BIT(1);
2389 break;
2390 case RPT_EN_MREG:
2391 bit_map = BIT(2);
2392 break;
2393 case RPT_EN_BT_VER_INFO:
2394 bit_map = BIT(3);
2395 break;
2396 case RPT_EN_BT_SCAN_INFO:
2397 bit_map = BIT(4);
2398 break;
2399 case RPT_EN_BT_DEVICE_INFO:
2400 switch (ver->frptmap) {
2401 case 0:
2402 case 1:
2403 case 2:
2404 bit_map = BIT(6);
2405 break;
2406 case 3:
2407 case 4:
2408 bit_map = BIT(5);
2409 break;
2410 default:
2411 break;
2412 }
2413 break;
2414 case RPT_EN_BT_AFH_MAP:
2415 switch (ver->frptmap) {
2416 case 0:
2417 case 1:
2418 case 2:
2419 bit_map = BIT(5);
2420 break;
2421 case 3:
2422 case 4:
2423 bit_map = BIT(6);
2424 break;
2425 default:
2426 break;
2427 }
2428 break;
2429 case RPT_EN_BT_AFH_MAP_LE:
2430 switch (ver->frptmap) {
2431 case 2:
2432 bit_map = BIT(8);
2433 break;
2434 case 3:
2435 case 4:
2436 bit_map = BIT(7);
2437 break;
2438 default:
2439 break;
2440 }
2441 break;
2442 case RPT_EN_BT_TX_PWR_LVL:
2443 switch (ver->frptmap) {
2444 case 0:
2445 case 1:
2446 case 2:
2447 case 3:
2448 break;
2449 case 4:
2450 bit_map = BIT(8);
2451 break;
2452 default:
2453 break;
2454 }
2455 break;
2456 case RPT_EN_FW_STEP_INFO:
2457 switch (ver->frptmap) {
2458 case 1:
2459 case 2:
2460 bit_map = BIT(7);
2461 break;
2462 case 3:
2463 bit_map = BIT(8);
2464 break;
2465 case 4:
2466 bit_map = BIT(9);
2467 break;
2468 default:
2469 break;
2470 }
2471 break;
2472 case RPT_EN_TEST:
2473 bit_map = BIT(31);
2474 break;
2475 case RPT_EN_WL_ALL:
2476 switch (ver->frptmap) {
2477 case 0:
2478 case 1:
2479 case 2:
2480 bit_map = GENMASK(2, 0);
2481 break;
2482 case 3:
2483 bit_map = GENMASK(2, 0) | BIT(8);
2484 break;
2485 case 4:
2486 bit_map = GENMASK(2, 0) | BIT(9);
2487 break;
2488 default:
2489 break;
2490 }
2491 break;
2492 case RPT_EN_BT_ALL:
2493 switch (ver->frptmap) {
2494 case 0:
2495 case 1:
2496 bit_map = GENMASK(6, 3);
2497 break;
2498 case 2:
2499 bit_map = GENMASK(6, 3) | BIT(8);
2500 break;
2501 case 3:
2502 bit_map = GENMASK(7, 3);
2503 break;
2504 case 4:
2505 bit_map = GENMASK(8, 3);
2506 break;
2507 default:
2508 break;
2509 }
2510 break;
2511 case RPT_EN_ALL:
2512 switch (ver->frptmap) {
2513 case 0:
2514 bit_map = GENMASK(6, 0);
2515 break;
2516 case 1:
2517 bit_map = GENMASK(7, 0);
2518 break;
2519 case 2:
2520 case 3:
2521 bit_map = GENMASK(8, 0);
2522 break;
2523 case 4:
2524 bit_map = GENMASK(9, 0);
2525 break;
2526 default:
2527 break;
2528 }
2529 break;
2530 case RPT_EN_MONITER:
2531 switch (ver->frptmap) {
2532 case 0:
2533 case 1:
2534 bit_map = GENMASK(6, 2);
2535 break;
2536 case 2:
2537 bit_map = GENMASK(6, 2) | BIT(8);
2538 break;
2539 case 3:
2540 bit_map = GENMASK(8, 2);
2541 break;
2542 case 4:
2543 bit_map = GENMASK(9, 2);
2544 break;
2545 default:
2546 break;
2547 }
2548 break;
2549 }
2550
2551 return bit_map;
2552 }
2553
rtw89_btc_fw_set_slots(struct rtw89_dev * rtwdev)2554 static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev)
2555 {
2556 struct rtw89_btc *btc = &rtwdev->btc;
2557 const struct rtw89_btc_ver *ver = btc->ver;
2558 struct rtw89_btc_btf_tlv_v7 *tlv_v7 = NULL;
2559 struct rtw89_btc_btf_set_slot_table *tbl;
2560 struct rtw89_btc_dm *dm = &btc->dm;
2561 u16 n, len;
2562
2563 if (ver->fcxslots == 7) {
2564 len = sizeof(*tlv_v7) + sizeof(dm->slot.v7);
2565 tlv_v7 = kmalloc(len, GFP_KERNEL);
2566 if (!tlv_v7)
2567 return;
2568
2569 tlv_v7->type = SET_SLOT_TABLE;
2570 tlv_v7->ver = ver->fcxslots;
2571 tlv_v7->len = ARRAY_SIZE(dm->slot.v7);
2572 memcpy(tlv_v7->val, dm->slot.v7, sizeof(dm->slot.v7));
2573
2574 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, (u8 *)tlv_v7, len);
2575
2576 kfree(tlv_v7);
2577 } else {
2578 n = struct_size(tbl, tbls, CXST_MAX);
2579 tbl = kmalloc(n, GFP_KERNEL);
2580 if (!tbl)
2581 return;
2582
2583 tbl->fver = BTF_SET_SLOT_TABLE_VER;
2584 tbl->tbl_num = CXST_MAX;
2585 memcpy(tbl->tbls, dm->slot.v1, flex_array_size(tbl, tbls, CXST_MAX));
2586
2587 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
2588
2589 kfree(tbl);
2590 }
2591 }
2592
rtw89_btc_fw_en_rpt(struct rtw89_dev * rtwdev,u32 rpt_map,bool rpt_state)2593 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
2594 u32 rpt_map, bool rpt_state)
2595 {
2596 struct rtw89_btc *btc = &rtwdev->btc;
2597 struct rtw89_btc_wl_smap *wl_smap = &btc->cx.wl.status.map;
2598 struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo;
2599 union rtw89_fbtc_rtp_ctrl r;
2600 u32 val, bit_map;
2601 int ret;
2602
2603 if ((wl_smap->rf_off || wl_smap->lps != BTC_LPS_OFF) && rpt_state != 0)
2604 return;
2605
2606 bit_map = rtw89_btc_fw_rpt_ver(rtwdev, rpt_map);
2607
2608 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2609 "[BTC], %s(): rpt_map=%x, rpt_state=%x\n",
2610 __func__, rpt_map, rpt_state);
2611
2612 if (rpt_state)
2613 val = fwinfo->rpt_en_map | bit_map;
2614 else
2615 val = fwinfo->rpt_en_map & ~bit_map;
2616
2617 if (val == fwinfo->rpt_en_map)
2618 return;
2619
2620 if (btc->ver->fcxbtcrpt == 7 || btc->ver->fcxbtcrpt == 8) {
2621 r.v8.type = SET_REPORT_EN;
2622 r.v8.fver = btc->ver->fcxbtcrpt;
2623 r.v8.len = sizeof(r.v8.map);
2624 r.v8.map = cpu_to_le32(val);
2625 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v8,
2626 sizeof(r.v8));
2627 } else {
2628 if (btc->ver->fcxbtcrpt == 105)
2629 r.v1.fver = 5;
2630 else
2631 r.v1.fver = btc->ver->fcxbtcrpt;
2632 r.v1.enable = cpu_to_le32(val);
2633 r.v1.para = cpu_to_le32(rpt_state);
2634 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v1,
2635 sizeof(r.v1));
2636 }
2637
2638 if (!ret)
2639 fwinfo->rpt_en_map = val;
2640 }
2641
btc_fw_set_monreg(struct rtw89_dev * rtwdev)2642 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
2643 {
2644 const struct rtw89_chip_info *chip = rtwdev->chip;
2645 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
2646 struct rtw89_btc_btf_set_mon_reg_v1 *v1 = NULL;
2647 struct rtw89_btc_btf_set_mon_reg_v7 *v7 = NULL;
2648 u8 i, n, ulen, cxmreg_max;
2649 u16 sz = 0;
2650
2651 n = chip->mon_reg_num;
2652 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2653 "[BTC], %s(): mon_reg_num=%d\n", __func__, n);
2654
2655 if (ver->fcxmreg == 1)
2656 cxmreg_max = CXMREG_MAX;
2657 else
2658 cxmreg_max = CXMREG_MAX_V2;
2659
2660 if (n > cxmreg_max) {
2661 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2662 "[BTC], %s(): mon reg count %d > %d\n",
2663 __func__, n, cxmreg_max);
2664 return;
2665 }
2666
2667 ulen = sizeof(struct rtw89_btc_fbtc_mreg);
2668
2669 if (ver->fcxmreg == 7) {
2670 sz = struct_size(v7, regs, n);
2671 v7 = kmalloc(sz, GFP_KERNEL);
2672 if (!v7)
2673 return;
2674 v7->type = RPT_EN_MREG;
2675 v7->fver = ver->fcxmreg;
2676 v7->len = n;
2677 for (i = 0; i < n; i++) {
2678 v7->regs[i].type = chip->mon_reg[i].type;
2679 v7->regs[i].bytes = chip->mon_reg[i].bytes;
2680 v7->regs[i].offset = chip->mon_reg[i].offset;
2681 }
2682
2683 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v7, sz);
2684 kfree(v7);
2685 } else {
2686 sz = struct_size(v1, regs, n);
2687 v1 = kmalloc(sz, GFP_KERNEL);
2688 if (!v1)
2689 return;
2690 v1->fver = ver->fcxmreg;
2691 v1->reg_num = n;
2692 memcpy(v1->regs, chip->mon_reg, flex_array_size(v1, regs, n));
2693
2694 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v1, sz);
2695 kfree(v1);
2696 }
2697
2698 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2699 "[BTC], %s(): sz=%d ulen=%d n=%d\n",
2700 __func__, sz, ulen, n);
2701
2702 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
2703 }
2704
_update_dm_step(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason_or_action)2705 static void _update_dm_step(struct rtw89_dev *rtwdev,
2706 enum btc_reason_and_action reason_or_action)
2707 {
2708 struct rtw89_btc *btc = &rtwdev->btc;
2709 struct rtw89_btc_dm *dm = &btc->dm;
2710
2711 /* use ring-structure to store dm step */
2712 dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action;
2713 dm->dm_step.step_pos++;
2714
2715 if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) {
2716 dm->dm_step.step_pos = 0;
2717 dm->dm_step.step_ov = true;
2718 }
2719 }
2720
_fw_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)2721 static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
2722 enum btc_reason_and_action action)
2723 {
2724 struct rtw89_btc *btc = &rtwdev->btc;
2725 struct rtw89_btc_dm *dm = &btc->dm;
2726 int ret;
2727
2728 dm->run_action = action;
2729
2730 _update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT);
2731 _update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT);
2732
2733 btc->policy_len = 0;
2734 btc->policy_type = policy_type;
2735
2736 _append_tdma(rtwdev);
2737 _append_slot(rtwdev);
2738
2739 if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN)
2740 return;
2741
2742 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2743 "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n",
2744 __func__, action, policy_type, btc->policy_len);
2745
2746 if (dm->tdma.rxflctrl == CXFLC_NULLP ||
2747 dm->tdma.rxflctrl == CXFLC_QOSNULL)
2748 btc->lps = 1;
2749 else
2750 btc->lps = 0;
2751
2752 if (btc->lps == 1)
2753 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
2754
2755 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY,
2756 btc->policy, btc->policy_len);
2757 if (!ret) {
2758 memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now));
2759 if (btc->ver->fcxslots == 7)
2760 memcpy(&dm->slot_now.v7, &dm->slot.v7, sizeof(dm->slot_now.v7));
2761 else
2762 memcpy(&dm->slot_now.v1, &dm->slot.v1, sizeof(dm->slot_now.v1));
2763 }
2764
2765 if (btc->update_policy_force)
2766 btc->update_policy_force = false;
2767
2768 if (btc->lps == 0)
2769 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
2770 }
2771
_fw_set_drv_info(struct rtw89_dev * rtwdev,u8 type)2772 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 type)
2773 {
2774 struct rtw89_btc *btc = &rtwdev->btc;
2775 const struct rtw89_btc_ver *ver = btc->ver;
2776 struct rtw89_btc_dm *dm = &btc->dm;
2777 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2778 struct rtw89_btc_rf_trx_para rf_para = dm->rf_trx_para;
2779
2780 switch (type) {
2781 case CXDRVINFO_INIT:
2782 if (ver->fcxinit == 7)
2783 rtw89_fw_h2c_cxdrv_init_v7(rtwdev, type);
2784 else
2785 rtw89_fw_h2c_cxdrv_init(rtwdev, type);
2786 break;
2787 case CXDRVINFO_ROLE:
2788 if (ver->fwlrole == 0)
2789 rtw89_fw_h2c_cxdrv_role(rtwdev, type);
2790 else if (ver->fwlrole == 1)
2791 rtw89_fw_h2c_cxdrv_role_v1(rtwdev, type);
2792 else if (ver->fwlrole == 2)
2793 rtw89_fw_h2c_cxdrv_role_v2(rtwdev, type);
2794 else if (ver->fwlrole == 7)
2795 rtw89_fw_h2c_cxdrv_role_v7(rtwdev, type);
2796 else if (ver->fwlrole == 8)
2797 rtw89_fw_h2c_cxdrv_role_v8(rtwdev, type);
2798 break;
2799 case CXDRVINFO_CTRL:
2800 if (ver->drvinfo_type == 1)
2801 type = 2;
2802
2803 if (ver->fcxctrl == 7)
2804 rtw89_fw_h2c_cxdrv_ctrl_v7(rtwdev, type);
2805 else
2806 rtw89_fw_h2c_cxdrv_ctrl(rtwdev, type);
2807 break;
2808 case CXDRVINFO_TRX:
2809 if (ver->drvinfo_type == 1)
2810 type = 3;
2811
2812 dm->trx_info.tx_power = u32_get_bits(rf_para.wl_tx_power,
2813 RTW89_BTC_WL_DEF_TX_PWR);
2814 dm->trx_info.rx_gain = u32_get_bits(rf_para.wl_rx_gain,
2815 RTW89_BTC_WL_DEF_TX_PWR);
2816 dm->trx_info.bt_tx_power = u32_get_bits(rf_para.bt_tx_power,
2817 RTW89_BTC_WL_DEF_TX_PWR);
2818 dm->trx_info.bt_rx_gain = u32_get_bits(rf_para.bt_rx_gain,
2819 RTW89_BTC_WL_DEF_TX_PWR);
2820 dm->trx_info.cn = wl->cn_report;
2821 dm->trx_info.nhm = wl->nhm.pwr;
2822 rtw89_fw_h2c_cxdrv_trx(rtwdev, type);
2823 break;
2824 case CXDRVINFO_RFK:
2825 if (ver->drvinfo_type == 1)
2826 return;
2827
2828 rtw89_fw_h2c_cxdrv_rfk(rtwdev, type);
2829 break;
2830 case CXDRVINFO_TXPWR:
2831 case CXDRVINFO_FDDT:
2832 case CXDRVINFO_MLO:
2833 case CXDRVINFO_OSI:
2834 if (!ver->fcxosi)
2835 return;
2836
2837 if (ver->drvinfo_type == 2)
2838 type = 7;
2839 else
2840 return;
2841
2842 rtw89_fw_h2c_cxdrv_osi_info(rtwdev, type);
2843 break;
2844 default:
2845 break;
2846 }
2847 }
2848
2849 static
btc_fw_event(struct rtw89_dev * rtwdev,u8 evt_id,void * data,u32 len)2850 void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len)
2851 {
2852 struct rtw89_btc *btc = &rtwdev->btc;
2853 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
2854
2855 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2856 "[BTC], %s(): evt_id:%d len:%d\n",
2857 __func__, evt_id, len);
2858
2859 if (!len || !data)
2860 return;
2861
2862 switch (evt_id) {
2863 case BTF_EVNT_RPT:
2864 _parse_btc_report(rtwdev, pfwinfo, data, len);
2865 break;
2866 default:
2867 break;
2868 }
2869 }
2870
_set_gnt(struct rtw89_dev * rtwdev,u8 phy_map,u8 wl_state,u8 bt_state)2871 static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map, u8 wl_state, u8 bt_state)
2872 {
2873 struct rtw89_btc *btc = &rtwdev->btc;
2874 struct rtw89_btc_dm *dm = &btc->dm;
2875 struct rtw89_mac_ax_gnt *g = dm->gnt.band;
2876 u8 i;
2877
2878 if (phy_map > BTC_PHY_ALL)
2879 return;
2880
2881 for (i = 0; i < RTW89_PHY_NUM; i++) {
2882 if (!(phy_map & BIT(i)))
2883 continue;
2884
2885 switch (wl_state) {
2886 case BTC_GNT_HW:
2887 g[i].gnt_wl_sw_en = 0;
2888 g[i].gnt_wl = 0;
2889 break;
2890 case BTC_GNT_SW_LO:
2891 g[i].gnt_wl_sw_en = 1;
2892 g[i].gnt_wl = 0;
2893 break;
2894 case BTC_GNT_SW_HI:
2895 g[i].gnt_wl_sw_en = 1;
2896 g[i].gnt_wl = 1;
2897 break;
2898 }
2899
2900 switch (bt_state) {
2901 case BTC_GNT_HW:
2902 g[i].gnt_bt_sw_en = 0;
2903 g[i].gnt_bt = 0;
2904 break;
2905 case BTC_GNT_SW_LO:
2906 g[i].gnt_bt_sw_en = 1;
2907 g[i].gnt_bt = 0;
2908 break;
2909 case BTC_GNT_SW_HI:
2910 g[i].gnt_bt_sw_en = 1;
2911 g[i].gnt_bt = 1;
2912 break;
2913 }
2914 }
2915
2916 rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
2917 }
2918
_set_gnt_v1(struct rtw89_dev * rtwdev,u8 phy_map,u8 wl_state,u8 bt_state,u8 wlact_state)2919 static void _set_gnt_v1(struct rtw89_dev *rtwdev, u8 phy_map,
2920 u8 wl_state, u8 bt_state, u8 wlact_state)
2921 {
2922 struct rtw89_btc *btc = &rtwdev->btc;
2923 struct rtw89_btc_dm *dm = &btc->dm;
2924 struct rtw89_btc_fbtc_outsrc_set_info *osi = &dm->ost_info;
2925 struct rtw89_mac_ax_wl_act *b = dm->gnt.bt;
2926 struct rtw89_mac_ax_gnt *g = dm->gnt.band;
2927 u8 i, bt_idx = dm->bt_select + 1;
2928
2929 if (phy_map > BTC_PHY_ALL)
2930 return;
2931
2932 for (i = 0; i < RTW89_PHY_NUM; i++) {
2933 if (!(phy_map & BIT(i)))
2934 continue;
2935
2936 switch (wl_state) {
2937 case BTC_GNT_HW:
2938 g[i].gnt_wl_sw_en = 0;
2939 g[i].gnt_wl = 0;
2940 break;
2941 case BTC_GNT_SW_LO:
2942 g[i].gnt_wl_sw_en = 1;
2943 g[i].gnt_wl = 0;
2944 break;
2945 case BTC_GNT_SW_HI:
2946 g[i].gnt_wl_sw_en = 1;
2947 g[i].gnt_wl = 1;
2948 break;
2949 }
2950
2951 switch (bt_state) {
2952 case BTC_GNT_HW:
2953 g[i].gnt_bt_sw_en = 0;
2954 g[i].gnt_bt = 0;
2955 break;
2956 case BTC_GNT_SW_LO:
2957 g[i].gnt_bt_sw_en = 1;
2958 g[i].gnt_bt = 0;
2959 break;
2960 case BTC_GNT_SW_HI:
2961 g[i].gnt_bt_sw_en = 1;
2962 g[i].gnt_bt = 1;
2963 break;
2964 }
2965 }
2966
2967 if (rtwdev->chip->para_ver & BTC_FEAT_WLAN_ACT_MUX) {
2968 for (i = 0; i < 2; i++) {
2969 if (!(bt_idx & BIT(i)))
2970 continue;
2971
2972 switch (wlact_state) {
2973 case BTC_WLACT_HW:
2974 b[i].wlan_act_en = 0;
2975 b[i].wlan_act = 0;
2976 break;
2977 case BTC_WLACT_SW_LO:
2978 b[i].wlan_act_en = 1;
2979 b[i].wlan_act = 0;
2980 break;
2981 case BTC_WLACT_SW_HI:
2982 b[i].wlan_act_en = 1;
2983 b[i].wlan_act = 1;
2984 break;
2985 }
2986 }
2987 }
2988
2989 if (!btc->ver->fcxosi) {
2990 rtw89_mac_cfg_gnt_v2(rtwdev, &dm->gnt);
2991 return;
2992 }
2993
2994 memcpy(osi->gnt_set, dm->gnt.band, sizeof(osi->gnt_set));
2995 memcpy(osi->wlact_set, dm->gnt.bt, sizeof(osi->wlact_set));
2996
2997 /* GBT source should be GBT_S1 in 1+1 (HWB0:5G + HWB1:2G) case */
2998 if (osi->rf_band[BTC_RF_S0] == 1 &&
2999 osi->rf_band[BTC_RF_S1] == 0)
3000 osi->rf_gbt_source = BTC_RF_S1;
3001 else
3002 osi->rf_gbt_source = BTC_RF_S0;
3003 }
3004
3005 #define BTC_TDMA_WLROLE_MAX 3
3006
_set_bt_ignore_wlan_act(struct rtw89_dev * rtwdev,u8 enable)3007 static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable)
3008 {
3009 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3010 "[BTC], %s(): set bt %s wlan_act\n", __func__,
3011 enable ? "ignore" : "do not ignore");
3012
3013 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1);
3014 }
3015
3016 #define WL_TX_POWER_NO_BTC_CTRL GENMASK(31, 0)
3017 #define WL_TX_POWER_ALL_TIME GENMASK(15, 0)
3018 #define WL_TX_POWER_WITH_BT GENMASK(31, 16)
3019 #define WL_TX_POWER_INT_PART GENMASK(8, 2)
3020 #define WL_TX_POWER_FRA_PART GENMASK(1, 0)
3021 #define B_BTC_WL_TX_POWER_SIGN BIT(7)
3022 #define B_TSSI_WL_TX_POWER_SIGN BIT(8)
3023
_set_wl_tx_power(struct rtw89_dev * rtwdev,u32 level)3024 static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level)
3025 {
3026 const struct rtw89_chip_info *chip = rtwdev->chip;
3027 struct rtw89_btc *btc = &rtwdev->btc;
3028 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3029 u32 pwr_val;
3030
3031 if (wl->rf_para.tx_pwr_freerun == level)
3032 return;
3033
3034 wl->rf_para.tx_pwr_freerun = level;
3035 btc->dm.rf_trx_para.wl_tx_power = level;
3036
3037 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3038 "[BTC], %s(): level = %d\n",
3039 __func__, level);
3040
3041 if (level == RTW89_BTC_WL_DEF_TX_PWR) {
3042 pwr_val = WL_TX_POWER_NO_BTC_CTRL;
3043 } else { /* only apply "force tx power" */
3044 pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level);
3045 if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR)
3046 pwr_val = RTW89_BTC_WL_DEF_TX_PWR;
3047
3048 if (level & B_BTC_WL_TX_POWER_SIGN)
3049 pwr_val |= B_TSSI_WL_TX_POWER_SIGN;
3050 pwr_val |= WL_TX_POWER_WITH_BT;
3051 }
3052
3053 chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val);
3054 }
3055
_set_wl_rx_gain(struct rtw89_dev * rtwdev,u32 level)3056 static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
3057 {
3058 const struct rtw89_chip_info *chip = rtwdev->chip;
3059 struct rtw89_btc *btc = &rtwdev->btc;
3060 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3061
3062 if (wl->rf_para.rx_gain_freerun == level)
3063 return;
3064
3065 wl->rf_para.rx_gain_freerun = level;
3066 btc->dm.rf_trx_para.wl_rx_gain = level;
3067
3068 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3069 "[BTC], %s(): level = %d\n",
3070 __func__, level);
3071
3072 chip->ops->btc_set_wl_rx_gain(rtwdev, level);
3073 }
3074
_set_bt_tx_power(struct rtw89_dev * rtwdev,u8 level)3075 static void _set_bt_tx_power(struct rtw89_dev *rtwdev, u8 level)
3076 {
3077 struct rtw89_btc *btc = &rtwdev->btc;
3078 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3079 int ret;
3080 u8 buf;
3081
3082 if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0)
3083 return;
3084
3085 if (bt->rf_para.tx_pwr_freerun == level)
3086 return;
3087
3088 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3089 "[BTC], %s(): level = %d\n",
3090 __func__, level);
3091
3092 buf = (s8)(-level);
3093 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_TX_PWR, &buf, 1);
3094 if (!ret) {
3095 bt->rf_para.tx_pwr_freerun = level;
3096 btc->dm.rf_trx_para.bt_tx_power = level;
3097 }
3098 }
3099
3100 #define BTC_BT_RX_NORMAL_LVL 7
3101
_set_bt_rx_gain(struct rtw89_dev * rtwdev,u8 level)3102 static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, u8 level)
3103 {
3104 struct rtw89_btc *btc = &rtwdev->btc;
3105 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3106
3107 if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0)
3108 return;
3109
3110 if ((bt->rf_para.rx_gain_freerun == level ||
3111 level > BTC_BT_RX_NORMAL_LVL) &&
3112 (!rtwdev->chip->scbd || bt->lna_constrain == level))
3113 return;
3114
3115 bt->rf_para.rx_gain_freerun = level;
3116 btc->dm.rf_trx_para.bt_rx_gain = level;
3117
3118 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3119 "[BTC], %s(): level = %d\n",
3120 __func__, level);
3121
3122 if (level == BTC_BT_RX_NORMAL_LVL)
3123 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, false);
3124 else
3125 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
3126
3127 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_LNA_CONSTRAIN, &level, sizeof(level));
3128 }
3129
_set_rf_trx_para(struct rtw89_dev * rtwdev)3130 static void _set_rf_trx_para(struct rtw89_dev *rtwdev)
3131 {
3132 const struct rtw89_chip_info *chip = rtwdev->chip;
3133 struct rtw89_btc *btc = &rtwdev->btc;
3134 const struct rtw89_btc_ver *ver = btc->ver;
3135 struct rtw89_btc_dm *dm = &btc->dm;
3136 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3137 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3138 struct rtw89_btc_bt_link_info *b = &bt->link_info;
3139 struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
3140 struct rtw89_btc_rf_trx_para para;
3141 u32 wl_stb_chg = 0;
3142 u8 level_id = 0, link_mode = 0, i, dbcc_2g_phy = 0;
3143
3144 if (ver->fwlrole == 0) {
3145 link_mode = wl->role_info.link_mode;
3146 for (i = 0; i < RTW89_PHY_NUM; i++) {
3147 if (wl->dbcc_info.real_band[i] == RTW89_BAND_2G)
3148 dbcc_2g_phy = i;
3149 }
3150 } else if (ver->fwlrole == 1) {
3151 link_mode = wl->role_info_v1.link_mode;
3152 dbcc_2g_phy = wl->role_info_v1.dbcc_2g_phy;
3153 } else if (ver->fwlrole == 2) {
3154 link_mode = wl->role_info_v2.link_mode;
3155 dbcc_2g_phy = wl->role_info_v2.dbcc_2g_phy;
3156 }
3157
3158 /* decide trx_para_level */
3159 if (btc->ant_type == BTC_ANT_SHARED) {
3160 /* fix LNA2 + TIA gain not change by GNT_BT */
3161 if ((btc->dm.wl_btg_rx && b->profile_cnt.now != 0) ||
3162 dm->bt_only == 1)
3163 dm->trx_para_level = 1; /* for better BT ACI issue */
3164 else
3165 dm->trx_para_level = 0;
3166 } else { /* non-shared antenna */
3167 dm->trx_para_level = 5;
3168 /* modify trx_para if WK 2.4G-STA-DL + bt link */
3169 if (b->profile_cnt.now != 0 &&
3170 link_mode == BTC_WLINK_2G_STA &&
3171 wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { /* uplink */
3172 if (wl->rssi_level == 4 && bt->rssi_level > 2)
3173 dm->trx_para_level = 6;
3174 else if (wl->rssi_level == 3 && bt->rssi_level > 3)
3175 dm->trx_para_level = 7;
3176 }
3177 }
3178
3179 level_id = dm->trx_para_level;
3180 if (level_id >= chip->rf_para_dlink_num ||
3181 level_id >= chip->rf_para_ulink_num) {
3182 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3183 "[BTC], %s(): invalid level_id: %d\n",
3184 __func__, level_id);
3185 return;
3186 }
3187
3188 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
3189 para = chip->rf_para_ulink[level_id];
3190 else
3191 para = chip->rf_para_dlink[level_id];
3192
3193 if (dm->fddt_train) {
3194 _set_wl_rx_gain(rtwdev, 1);
3195 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
3196 } else {
3197 _set_wl_tx_power(rtwdev, para.wl_tx_power);
3198 _set_wl_rx_gain(rtwdev, para.wl_rx_gain);
3199 _set_bt_tx_power(rtwdev, para.bt_tx_power);
3200 _set_bt_rx_gain(rtwdev, para.bt_rx_gain);
3201 }
3202
3203 if (!bt->enable.now || dm->wl_only || wl_smap->rf_off ||
3204 wl_smap->lps == BTC_LPS_RF_OFF ||
3205 link_mode == BTC_WLINK_5G ||
3206 link_mode == BTC_WLINK_NOLINK ||
3207 (rtwdev->dbcc_en && dbcc_2g_phy != RTW89_PHY_1))
3208 wl_stb_chg = 0;
3209 else
3210 wl_stb_chg = 1;
3211
3212 if (wl_stb_chg != dm->wl_stb_chg) {
3213 dm->wl_stb_chg = wl_stb_chg;
3214 chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg);
3215 }
3216 }
3217
_update_btc_state_map(struct rtw89_dev * rtwdev)3218 static void _update_btc_state_map(struct rtw89_dev *rtwdev)
3219 {
3220 struct rtw89_btc *btc = &rtwdev->btc;
3221 struct rtw89_btc_cx *cx = &btc->cx;
3222 struct rtw89_btc_wl_info *wl = &cx->wl;
3223 struct rtw89_btc_bt_info *bt = &cx->bt;
3224 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
3225
3226 if (wl->status.map.connecting || wl->status.map._4way ||
3227 wl->status.map.roaming || wl->status.map.dbccing) {
3228 cx->state_map = BTC_WLINKING;
3229 } else if (wl->status.map.scan) { /* wl scan */
3230 if (bt_linfo->status.map.inq_pag)
3231 cx->state_map = BTC_WSCAN_BSCAN;
3232 else
3233 cx->state_map = BTC_WSCAN_BNOSCAN;
3234 } else if (wl->status.map.busy) { /* only busy */
3235 if (bt_linfo->status.map.inq_pag)
3236 cx->state_map = BTC_WBUSY_BSCAN;
3237 else
3238 cx->state_map = BTC_WBUSY_BNOSCAN;
3239 } else { /* wl idle */
3240 cx->state_map = BTC_WIDLE;
3241 }
3242 }
3243
_set_bt_afh_info_v0(struct rtw89_dev * rtwdev)3244 static void _set_bt_afh_info_v0(struct rtw89_dev *rtwdev)
3245 {
3246 const struct rtw89_chip_info *chip = rtwdev->chip;
3247 struct rtw89_btc *btc = &rtwdev->btc;
3248 const struct rtw89_btc_ver *ver = btc->ver;
3249 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3250 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3251 struct rtw89_btc_bt_link_info *b = &bt->link_info;
3252 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3253 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3254 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
3255 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
3256 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
3257 struct rtw89_btc_wl_active_role *r;
3258 struct rtw89_btc_wl_active_role_v1 *r1;
3259 struct rtw89_btc_wl_active_role_v2 *r2;
3260 struct rtw89_btc_wl_active_role_v7 *r7;
3261 struct rtw89_btc_wl_rlink *rlink;
3262 u8 en = 0, i, ch = 0, bw = 0;
3263 u8 mode, connect_cnt;
3264
3265 if (btc->manual_ctrl || wl->status.map.scan)
3266 return;
3267
3268 if (ver->fwlrole == 0) {
3269 mode = wl_rinfo->link_mode;
3270 connect_cnt = wl_rinfo->connect_cnt;
3271 } else if (ver->fwlrole == 1) {
3272 mode = wl_rinfo_v1->link_mode;
3273 connect_cnt = wl_rinfo_v1->connect_cnt;
3274 } else if (ver->fwlrole == 2) {
3275 mode = wl_rinfo_v2->link_mode;
3276 connect_cnt = wl_rinfo_v2->connect_cnt;
3277 } else if (ver->fwlrole == 7) {
3278 mode = wl_rinfo_v7->link_mode;
3279 connect_cnt = wl_rinfo_v7->connect_cnt;
3280 } else if (ver->fwlrole == 8) {
3281 mode = wl_rinfo_v8->link_mode;
3282 connect_cnt = wl_rinfo_v8->connect_cnt;
3283 } else {
3284 return;
3285 }
3286
3287 if (wl->status.map.rf_off || bt->whql_test ||
3288 mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_5G ||
3289 connect_cnt > BTC_TDMA_WLROLE_MAX) {
3290 en = false;
3291 } else if (mode == BTC_WLINK_2G_MCC || mode == BTC_WLINK_2G_SCC) {
3292 en = true;
3293 /* get p2p channel */
3294 for (i = 0; i < RTW89_PORT_NUM; i++) {
3295 r = &wl_rinfo->active_role[i];
3296 r1 = &wl_rinfo_v1->active_role_v1[i];
3297 r2 = &wl_rinfo_v2->active_role_v2[i];
3298 r7 = &wl_rinfo_v7->active_role[i];
3299 rlink = &wl_rinfo_v8->rlink[i][0];
3300
3301 if (ver->fwlrole == 0 &&
3302 (r->role == RTW89_WIFI_ROLE_P2P_GO ||
3303 r->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3304 ch = r->ch;
3305 bw = r->bw;
3306 break;
3307 } else if (ver->fwlrole == 1 &&
3308 (r1->role == RTW89_WIFI_ROLE_P2P_GO ||
3309 r1->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3310 ch = r1->ch;
3311 bw = r1->bw;
3312 break;
3313 } else if (ver->fwlrole == 2 &&
3314 (r2->role == RTW89_WIFI_ROLE_P2P_GO ||
3315 r2->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3316 ch = r2->ch;
3317 bw = r2->bw;
3318 break;
3319 } else if (ver->fwlrole == 7 &&
3320 (r7->role == RTW89_WIFI_ROLE_P2P_GO ||
3321 r7->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3322 ch = r7->ch;
3323 bw = r7->bw;
3324 break;
3325 } else if (ver->fwlrole == 8 &&
3326 (rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
3327 rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3328 ch = rlink->ch;
3329 bw = rlink->bw;
3330 break;
3331 }
3332 }
3333 } else {
3334 en = true;
3335 /* get 2g channel */
3336 for (i = 0; i < RTW89_PORT_NUM; i++) {
3337 r = &wl_rinfo->active_role[i];
3338 r1 = &wl_rinfo_v1->active_role_v1[i];
3339 r2 = &wl_rinfo_v2->active_role_v2[i];
3340 r7 = &wl_rinfo_v7->active_role[i];
3341 rlink = &wl_rinfo_v8->rlink[i][0];
3342
3343 if (ver->fwlrole == 0 &&
3344 r->connected && r->band == RTW89_BAND_2G) {
3345 ch = r->ch;
3346 bw = r->bw;
3347 break;
3348 } else if (ver->fwlrole == 1 &&
3349 r1->connected && r1->band == RTW89_BAND_2G) {
3350 ch = r1->ch;
3351 bw = r1->bw;
3352 break;
3353 } else if (ver->fwlrole == 2 &&
3354 r2->connected && r2->band == RTW89_BAND_2G) {
3355 ch = r2->ch;
3356 bw = r2->bw;
3357 break;
3358 } else if (ver->fwlrole == 7 &&
3359 r7->connected && r7->band == RTW89_BAND_2G) {
3360 ch = r7->ch;
3361 bw = r7->bw;
3362 break;
3363 } else if (ver->fwlrole == 8 &&
3364 rlink->connected && rlink->rf_band == RTW89_BAND_2G) {
3365 ch = rlink->ch;
3366 bw = rlink->bw;
3367 break;
3368 }
3369 }
3370 }
3371
3372 switch (bw) {
3373 case RTW89_CHANNEL_WIDTH_20:
3374 bw = 20 + chip->afh_guard_ch * 2;
3375 break;
3376 case RTW89_CHANNEL_WIDTH_40:
3377 bw = 40 + chip->afh_guard_ch * 2;
3378 break;
3379 case RTW89_CHANNEL_WIDTH_5:
3380 bw = 5 + chip->afh_guard_ch * 2;
3381 break;
3382 case RTW89_CHANNEL_WIDTH_10:
3383 bw = 10 + chip->afh_guard_ch * 2;
3384 break;
3385 default:
3386 bw = 0;
3387 en = false; /* turn off AFH info if BW > 40 */
3388 break;
3389 }
3390
3391 if (wl->afh_info.en == en &&
3392 wl->afh_info.ch == ch &&
3393 wl->afh_info.bw == bw &&
3394 b->profile_cnt.last == b->profile_cnt.now) {
3395 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3396 "[BTC], %s(): return because no change!\n",
3397 __func__);
3398 return;
3399 }
3400
3401 wl->afh_info.en = en;
3402 wl->afh_info.ch = ch;
3403 wl->afh_info.bw = bw;
3404
3405 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3);
3406
3407 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3408 "[BTC], %s(): en=%d, ch=%d, bw=%d\n",
3409 __func__, en, ch, bw);
3410 btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++;
3411 }
3412
_set_bt_afh_info_v1(struct rtw89_dev * rtwdev)3413 static void _set_bt_afh_info_v1(struct rtw89_dev *rtwdev)
3414 {
3415 const struct rtw89_chip_info *chip = rtwdev->chip;
3416 struct rtw89_btc *btc = &rtwdev->btc;
3417 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3418 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
3419 struct rtw89_btc_wl_afh_info *wl_afh = &wl->afh_info;
3420 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3421 struct rtw89_btc_wl_rlink *rlink;
3422 u8 en = 0, ch = 0, bw = 0, buf[3] = {};
3423 u8 i, j, link_mode;
3424
3425 if (btc->manual_ctrl || wl->status.map.scan)
3426 return;
3427
3428 link_mode = wl_rinfo->link_mode;
3429
3430 for (i = 0; i < btc->ver->max_role_num; i++) {
3431 for (j = RTW89_MAC_0; j < RTW89_MAC_NUM; j++) {
3432 if (wl->status.map.rf_off || bt->whql_test ||
3433 link_mode == BTC_WLINK_NOLINK ||
3434 link_mode == BTC_WLINK_5G)
3435 break;
3436
3437 rlink = &wl_rinfo->rlink[i][j];
3438
3439 /* Don't care no-connected/non-2G-band role */
3440 if (!rlink->connected || !rlink->active ||
3441 rlink->rf_band != RTW89_BAND_2G)
3442 continue;
3443
3444 en = 1;
3445 ch = rlink->ch;
3446 bw = rlink->bw;
3447
3448 if (link_mode == BTC_WLINK_2G_MCC &&
3449 (rlink->role == RTW89_WIFI_ROLE_AP ||
3450 rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
3451 rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3452 /* for 2.4G MCC, take role = ap/go/gc */
3453 break;
3454 } else if (link_mode != BTC_WLINK_2G_SCC ||
3455 rlink->bw == RTW89_CHANNEL_WIDTH_40) {
3456 /* for 2.4G scc, take bw = 40M */
3457 break;
3458 }
3459 }
3460 }
3461
3462 /* default AFH channel sapn = center-ch +- 6MHz */
3463 switch (bw) {
3464 case RTW89_CHANNEL_WIDTH_20:
3465 if (btc->dm.freerun || btc->dm.fddt_train)
3466 bw = 48;
3467 else
3468 bw = 20 + chip->afh_guard_ch * 2;
3469 break;
3470 case RTW89_CHANNEL_WIDTH_40:
3471 if (btc->dm.freerun)
3472 bw = 40 + chip->afh_guard_ch * 2;
3473 else
3474 bw = 40;
3475 break;
3476 case RTW89_CHANNEL_WIDTH_5:
3477 bw = 5 + chip->afh_guard_ch * 2;
3478 break;
3479 case RTW89_CHANNEL_WIDTH_10:
3480 bw = 10 + chip->afh_guard_ch * 2;
3481 break;
3482 default:
3483 en = false; /* turn off AFH info if invalid BW */
3484 bw = 0;
3485 ch = 0;
3486 break;
3487 }
3488
3489 if (!en || ch > 14 || ch == 0) {
3490 en = false;
3491 bw = 0;
3492 ch = 0;
3493 }
3494
3495 if (wl_afh->en == en &&
3496 wl_afh->ch == ch &&
3497 wl_afh->bw == bw &&
3498 (!bt->enable.now || bt->enable.last))
3499 return;
3500
3501 wl_afh->en = buf[0];
3502 wl_afh->ch = buf[1];
3503 wl_afh->bw = buf[2];
3504
3505 if (_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3)) {
3506 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3507 "[BTC], %s(): en=%d, ch=%d, bw=%d\n",
3508 __func__, en, ch, bw);
3509
3510 btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++;
3511 }
3512 }
3513
_set_bt_afh_info(struct rtw89_dev * rtwdev)3514 static void _set_bt_afh_info(struct rtw89_dev *rtwdev)
3515 {
3516 if (rtwdev->chip->chip_id == RTL8922A)
3517 _set_bt_afh_info_v1(rtwdev);
3518 else
3519 _set_bt_afh_info_v0(rtwdev);
3520 }
3521
_check_freerun(struct rtw89_dev * rtwdev)3522 static bool _check_freerun(struct rtw89_dev *rtwdev)
3523 {
3524 struct rtw89_btc *btc = &rtwdev->btc;
3525 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3526 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3527 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3528 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3529 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
3530 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
3531 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
3532 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
3533 struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc;
3534 union rtw89_btc_module_info *md = &btc->mdinfo;
3535 const struct rtw89_btc_ver *ver = btc->ver;
3536 u8 isolation, connect_cnt = 0;
3537
3538 if (ver->fcxinit == 7)
3539 isolation = md->md_v7.ant.isolation;
3540 else
3541 isolation = md->md.ant.isolation;
3542
3543 if (ver->fwlrole == 0)
3544 connect_cnt = wl_rinfo->connect_cnt;
3545 else if (ver->fwlrole == 1)
3546 connect_cnt = wl_rinfo_v1->connect_cnt;
3547 else if (ver->fwlrole == 2)
3548 connect_cnt = wl_rinfo_v2->connect_cnt;
3549 else if (ver->fwlrole == 7)
3550 connect_cnt = wl_rinfo_v7->connect_cnt;
3551 else if (ver->fwlrole == 8)
3552 connect_cnt = wl_rinfo_v8->connect_cnt;
3553
3554 if (btc->ant_type == BTC_ANT_SHARED) {
3555 btc->dm.trx_para_level = 0;
3556 return false;
3557 }
3558
3559 /* The below is dedicated antenna case */
3560 if (connect_cnt > BTC_TDMA_WLROLE_MAX) {
3561 btc->dm.trx_para_level = 5;
3562 return true;
3563 }
3564
3565 if (bt_linfo->profile_cnt.now == 0) {
3566 btc->dm.trx_para_level = 5;
3567 return true;
3568 }
3569
3570 if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) {
3571 btc->dm.trx_para_level = 5;
3572 return true;
3573 }
3574
3575 /* TODO get isolation by BT psd */
3576 if (isolation >= BTC_FREERUN_ANTISO_MIN) {
3577 btc->dm.trx_para_level = 5;
3578 return true;
3579 }
3580
3581 if (!wl->status.map.busy) {/* wl idle -> freerun */
3582 btc->dm.trx_para_level = 5;
3583 return true;
3584 } else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */
3585 btc->dm.trx_para_level = 0;
3586 return false;
3587 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
3588 if (wl->rssi_level == 0 && bt_linfo->rssi > 31) {
3589 btc->dm.trx_para_level = 6;
3590 return true;
3591 } else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) {
3592 btc->dm.trx_para_level = 7;
3593 return true;
3594 }
3595 btc->dm.trx_para_level = 0;
3596 return false;
3597 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) {
3598 if (bt_linfo->rssi > 28) {
3599 btc->dm.trx_para_level = 6;
3600 return true;
3601 }
3602 }
3603
3604 btc->dm.trx_para_level = 0;
3605 return false;
3606 }
3607
3608 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; })
3609 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; })
3610 #define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; })
3611 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; })
3612
3613 struct btc_btinfo_lb2 {
3614 u8 connect: 1;
3615 u8 sco_busy: 1;
3616 u8 inq_pag: 1;
3617 u8 acl_busy: 1;
3618 u8 hfp: 1;
3619 u8 hid: 1;
3620 u8 a2dp: 1;
3621 u8 pan: 1;
3622 };
3623
3624 struct btc_btinfo_lb3 {
3625 u8 retry: 4;
3626 u8 cqddr: 1;
3627 u8 inq: 1;
3628 u8 mesh_busy: 1;
3629 u8 pag: 1;
3630 };
3631
3632 struct btc_btinfo_hb0 {
3633 s8 rssi;
3634 };
3635
3636 struct btc_btinfo_hb1 {
3637 u8 ble_connect: 1;
3638 u8 reinit: 1;
3639 u8 relink: 1;
3640 u8 igno_wl: 1;
3641 u8 voice: 1;
3642 u8 ble_scan: 1;
3643 u8 role_sw: 1;
3644 u8 multi_link: 1;
3645 };
3646
3647 struct btc_btinfo_hb2 {
3648 u8 pan_active: 1;
3649 u8 afh_update: 1;
3650 u8 a2dp_active: 1;
3651 u8 slave: 1;
3652 u8 hid_slot: 2;
3653 u8 hid_cnt: 2;
3654 };
3655
3656 struct btc_btinfo_hb3 {
3657 u8 a2dp_bitpool: 6;
3658 u8 tx_3m: 1;
3659 u8 a2dp_sink: 1;
3660 };
3661
3662 union btc_btinfo {
3663 u8 val;
3664 struct btc_btinfo_lb2 lb2;
3665 struct btc_btinfo_lb3 lb3;
3666 struct btc_btinfo_hb0 hb0;
3667 struct btc_btinfo_hb1 hb1;
3668 struct btc_btinfo_hb2 hb2;
3669 struct btc_btinfo_hb3 hb3;
3670 };
3671
_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)3672 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
3673 enum btc_reason_and_action action)
3674 {
3675 const struct rtw89_chip_info *chip = rtwdev->chip;
3676
3677 chip->ops->btc_set_policy(rtwdev, policy_type);
3678 _fw_set_policy(rtwdev, policy_type, action);
3679 }
3680
3681 #define BTC_B1_MAX 250 /* unit ms */
rtw89_btc_set_policy(struct rtw89_dev * rtwdev,u16 policy_type)3682 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type)
3683 {
3684 struct rtw89_btc *btc = &rtwdev->btc;
3685 struct rtw89_btc_dm *dm = &btc->dm;
3686 struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
3687 struct rtw89_btc_fbtc_slot *s = dm->slot.v1;
3688 u8 type;
3689 u32 tbl_w1, tbl_b1, tbl_b4;
3690
3691 if (btc->ant_type == BTC_ANT_SHARED) {
3692 if (btc->cx.wl.status.map._4way)
3693 tbl_w1 = cxtbl[1];
3694 else
3695 tbl_w1 = cxtbl[8];
3696 tbl_b1 = cxtbl[3];
3697 tbl_b4 = cxtbl[3];
3698 } else {
3699 tbl_w1 = cxtbl[16];
3700 tbl_b1 = cxtbl[17];
3701 tbl_b4 = cxtbl[17];
3702 }
3703
3704 type = (u8)((policy_type & BTC_CXP_MASK) >> 8);
3705 btc->bt_req_en = false;
3706
3707 switch (type) {
3708 case BTC_CXP_USERDEF0:
3709 *t = t_def[CXTD_OFF];
3710 s[CXST_OFF] = s_def[CXST_OFF];
3711 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
3712 btc->update_policy_force = true;
3713 break;
3714 case BTC_CXP_OFF: /* TDMA off */
3715 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
3716 *t = t_def[CXTD_OFF];
3717 s[CXST_OFF] = s_def[CXST_OFF];
3718
3719 switch (policy_type) {
3720 case BTC_CXP_OFF_BT:
3721 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
3722 break;
3723 case BTC_CXP_OFF_WL:
3724 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
3725 break;
3726 case BTC_CXP_OFF_EQ0:
3727 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
3728 break;
3729 case BTC_CXP_OFF_EQ1:
3730 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
3731 break;
3732 case BTC_CXP_OFF_EQ2:
3733 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
3734 break;
3735 case BTC_CXP_OFF_EQ3:
3736 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
3737 break;
3738 case BTC_CXP_OFF_BWB0:
3739 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
3740 break;
3741 case BTC_CXP_OFF_BWB1:
3742 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
3743 break;
3744 case BTC_CXP_OFF_BWB3:
3745 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
3746 break;
3747 }
3748 break;
3749 case BTC_CXP_OFFB: /* TDMA off + beacon protect */
3750 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
3751 *t = t_def[CXTD_OFF_B2];
3752 s[CXST_OFF] = s_def[CXST_OFF];
3753 switch (policy_type) {
3754 case BTC_CXP_OFFB_BWB0:
3755 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
3756 break;
3757 }
3758 break;
3759 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
3760 btc->bt_req_en = true;
3761 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3762 *t = t_def[CXTD_OFF_EXT];
3763 switch (policy_type) {
3764 case BTC_CXP_OFFE_DEF:
3765 s[CXST_E2G] = s_def[CXST_E2G];
3766 s[CXST_E5G] = s_def[CXST_E5G];
3767 s[CXST_EBT] = s_def[CXST_EBT];
3768 s[CXST_ENULL] = s_def[CXST_ENULL];
3769 break;
3770 case BTC_CXP_OFFE_DEF2:
3771 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
3772 s[CXST_E5G] = s_def[CXST_E5G];
3773 s[CXST_EBT] = s_def[CXST_EBT];
3774 s[CXST_ENULL] = s_def[CXST_ENULL];
3775 break;
3776 }
3777 break;
3778 case BTC_CXP_FIX: /* TDMA Fix-Slot */
3779 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3780 *t = t_def[CXTD_FIX];
3781 switch (policy_type) {
3782 case BTC_CXP_FIX_TD3030:
3783 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3784 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3785 break;
3786 case BTC_CXP_FIX_TD5050:
3787 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3788 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
3789 break;
3790 case BTC_CXP_FIX_TD2030:
3791 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3792 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3793 break;
3794 case BTC_CXP_FIX_TD4010:
3795 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
3796 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3797 break;
3798 case BTC_CXP_FIX_TD4010ISO:
3799 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
3800 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3801 break;
3802 case BTC_CXP_FIX_TD4010ISO_DL:
3803 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
3804 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
3805 break;
3806 case BTC_CXP_FIX_TD4010ISO_UL:
3807 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
3808 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
3809 break;
3810 case BTC_CXP_FIX_TD7010:
3811 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
3812 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3813 break;
3814 case BTC_CXP_FIX_TD2060:
3815 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3816 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3817 break;
3818 case BTC_CXP_FIX_TD3060:
3819 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3820 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3821 break;
3822 case BTC_CXP_FIX_TD2080:
3823 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3824 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
3825 break;
3826 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
3827 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3828 tbl_w1, SLOT_ISO);
3829 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3830 tbl_b1, SLOT_MIX);
3831 break;
3832 }
3833 break;
3834 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
3835 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3836 *t = t_def[CXTD_PFIX];
3837 if (btc->cx.wl.role_info.role_map.role.ap)
3838 _tdma_set_flctrl(btc, CXFLC_QOSNULL);
3839
3840 switch (policy_type) {
3841 case BTC_CXP_PFIX_TD3030:
3842 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3843 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3844 break;
3845 case BTC_CXP_PFIX_TD5050:
3846 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3847 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
3848 break;
3849 case BTC_CXP_PFIX_TD2030:
3850 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3851 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3852 break;
3853 case BTC_CXP_PFIX_TD2060:
3854 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3855 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3856 break;
3857 case BTC_CXP_PFIX_TD3070:
3858 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3859 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3860 break;
3861 case BTC_CXP_PFIX_TD2080:
3862 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3863 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
3864 break;
3865 }
3866 break;
3867 case BTC_CXP_AUTO: /* TDMA Auto-Slot */
3868 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3869 *t = t_def[CXTD_AUTO];
3870 switch (policy_type) {
3871 case BTC_CXP_AUTO_TD50B1:
3872 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3873 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3874 break;
3875 case BTC_CXP_AUTO_TD60B1:
3876 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3877 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3878 break;
3879 case BTC_CXP_AUTO_TD20B1:
3880 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3881 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3882 break;
3883 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
3884 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3885 tbl_w1, SLOT_ISO);
3886 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3887 tbl_b1, SLOT_MIX);
3888 break;
3889 }
3890 break;
3891 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
3892 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3893 *t = t_def[CXTD_PAUTO];
3894 switch (policy_type) {
3895 case BTC_CXP_PAUTO_TD50B1:
3896 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3897 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3898 break;
3899 case BTC_CXP_PAUTO_TD60B1:
3900 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3901 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3902 break;
3903 case BTC_CXP_PAUTO_TD20B1:
3904 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3905 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3906 break;
3907 case BTC_CXP_PAUTO_TDW1B1:
3908 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3909 tbl_w1, SLOT_ISO);
3910 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3911 tbl_b1, SLOT_MIX);
3912 break;
3913 }
3914 break;
3915 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
3916 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3917 *t = t_def[CXTD_AUTO2];
3918 switch (policy_type) {
3919 case BTC_CXP_AUTO2_TD3050:
3920 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3921 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3922 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3923 break;
3924 case BTC_CXP_AUTO2_TD3070:
3925 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3926 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
3927 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3928 break;
3929 case BTC_CXP_AUTO2_TD5050:
3930 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3931 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3932 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3933 break;
3934 case BTC_CXP_AUTO2_TD6060:
3935 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3936 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
3937 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3938 break;
3939 case BTC_CXP_AUTO2_TD2080:
3940 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3941 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
3942 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3943 break;
3944 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
3945 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3946 tbl_w1, SLOT_ISO);
3947 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
3948 tbl_b4, SLOT_MIX);
3949 break;
3950 }
3951 break;
3952 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
3953 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3954 *t = t_def[CXTD_PAUTO2];
3955 switch (policy_type) {
3956 case BTC_CXP_PAUTO2_TD3050:
3957 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3958 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3959 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3960 break;
3961 case BTC_CXP_PAUTO2_TD3070:
3962 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3963 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
3964 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3965 break;
3966 case BTC_CXP_PAUTO2_TD5050:
3967 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3968 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3969 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3970 break;
3971 case BTC_CXP_PAUTO2_TD6060:
3972 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3973 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
3974 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3975 break;
3976 case BTC_CXP_PAUTO2_TD2080:
3977 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3978 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
3979 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3980 break;
3981 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
3982 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3983 tbl_w1, SLOT_ISO);
3984 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
3985 tbl_b4, SLOT_MIX);
3986 break;
3987 }
3988 break;
3989 }
3990 }
3991 EXPORT_SYMBOL(rtw89_btc_set_policy);
3992
rtw89_btc_set_policy_v1(struct rtw89_dev * rtwdev,u16 policy_type)3993 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
3994 {
3995 struct rtw89_btc *btc = &rtwdev->btc;
3996 struct rtw89_btc_dm *dm = &btc->dm;
3997 struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
3998 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1;
3999 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
4000 struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
4001 struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc;
4002 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4003 u8 type, null_role;
4004 u32 tbl_w1, tbl_b1, tbl_b4;
4005 u16 dur_2;
4006
4007 if (wl->status.map.lps) {
4008 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
4009 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
4010 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4011 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4012 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4013 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4014 }
4015
4016 type = FIELD_GET(BTC_CXP_MASK, policy_type);
4017
4018 if (btc->ant_type == BTC_ANT_SHARED) {
4019 if (btc->cx.wl.status.map._4way)
4020 tbl_w1 = cxtbl[1];
4021 else if (hid->exist && hid->type == BTC_HID_218)
4022 tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */
4023 else
4024 tbl_w1 = cxtbl[8];
4025
4026 if (dm->leak_ap &&
4027 (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) {
4028 tbl_b1 = cxtbl[3];
4029 tbl_b4 = cxtbl[3];
4030 } else if (hid->exist && hid->type == BTC_HID_218) {
4031 tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */
4032 tbl_b4 = cxtbl[4];
4033 } else {
4034 tbl_b1 = cxtbl[2];
4035 tbl_b4 = cxtbl[2];
4036 }
4037 } else {
4038 tbl_b1 = cxtbl[17];
4039 tbl_b4 = cxtbl[17];
4040
4041 if (wl->bg_mode)
4042 tbl_w1 = cxtbl[8];
4043 else if ((wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) &&
4044 hid->exist)
4045 tbl_w1 = cxtbl[19];
4046 else
4047 tbl_w1 = cxtbl[16];
4048 }
4049
4050 switch (type) {
4051 case BTC_CXP_USERDEF0:
4052 btc->update_policy_force = true;
4053 *t = t_def[CXTD_OFF];
4054 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4055 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4056 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
4057 break;
4058 case BTC_CXP_OFF: /* TDMA off */
4059 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
4060 *t = t_def[CXTD_OFF];
4061 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4062 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4063
4064 switch (policy_type) {
4065 case BTC_CXP_OFF_BT:
4066 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
4067 break;
4068 case BTC_CXP_OFF_WL:
4069 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
4070 break;
4071 case BTC_CXP_OFF_WL2:
4072 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
4073 _slot_set_type(btc, CXST_OFF, SLOT_ISO);
4074 break;
4075 case BTC_CXP_OFF_EQ0:
4076 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
4077 _slot_set_type(btc, CXST_OFF, SLOT_ISO);
4078 break;
4079 case BTC_CXP_OFF_EQ1:
4080 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
4081 break;
4082 case BTC_CXP_OFF_EQ2:
4083 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
4084 break;
4085 case BTC_CXP_OFF_EQ3:
4086 _slot_set_tbl(btc, CXST_OFF, cxtbl[24]);
4087 break;
4088 case BTC_CXP_OFF_EQ4:
4089 _slot_set_tbl(btc, CXST_OFF, cxtbl[26]);
4090 break;
4091 case BTC_CXP_OFF_EQ5:
4092 _slot_set_tbl(btc, CXST_OFF, cxtbl[27]);
4093 break;
4094 case BTC_CXP_OFF_BWB0:
4095 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
4096 break;
4097 case BTC_CXP_OFF_BWB1:
4098 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
4099 break;
4100 case BTC_CXP_OFF_BWB2:
4101 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
4102 break;
4103 case BTC_CXP_OFF_BWB3:
4104 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
4105 break;
4106 default:
4107 break;
4108 }
4109 break;
4110 case BTC_CXP_OFFB: /* TDMA off + beacon protect */
4111 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
4112 *t = t_def[CXTD_OFF_B2];
4113 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4114 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4115
4116 switch (policy_type) {
4117 case BTC_CXP_OFFB_BWB0:
4118 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
4119 break;
4120 default:
4121 break;
4122 }
4123 break;
4124 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
4125 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4126 *t = t_def[CXTD_OFF_EXT];
4127
4128 /* To avoid wl-s0 tx break by hid/hfp tx */
4129 if (hid->exist || hfp->exist)
4130 tbl_w1 = cxtbl[16];
4131
4132 dur_2 = dm->e2g_slot_limit;
4133
4134 switch (policy_type) {
4135 case BTC_CXP_OFFE_2GBWISOB: /* for normal-case */
4136 _slot_set(btc, CXST_E2G, 5, tbl_w1, SLOT_ISO);
4137 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4138 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4139 _slot_set_dur(btc, CXST_EBT, dur_2);
4140 break;
4141 case BTC_CXP_OFFE_2GISOB: /* for bt no-link */
4142 _slot_set(btc, CXST_E2G, 5, cxtbl[1], SLOT_ISO);
4143 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4144 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4145 _slot_set_dur(btc, CXST_EBT, dur_2);
4146 break;
4147 case BTC_CXP_OFFE_DEF:
4148 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
4149 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
4150 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4151 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4152 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4153 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4154 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
4155 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
4156 _slot_set_dur(btc, CXST_EBT, dur_2);
4157 break;
4158 case BTC_CXP_OFFE_DEF2:
4159 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
4160 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4161 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4162 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4163 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4164 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
4165 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
4166 _slot_set_dur(btc, CXST_EBT, dur_2);
4167 break;
4168 case BTC_CXP_OFFE_2GBWMIXB:
4169 if (a2dp->exist)
4170 _slot_set(btc, CXST_E2G, 5, cxtbl[2], SLOT_MIX);
4171 else
4172 _slot_set(btc, CXST_E2G, 5, tbl_w1, SLOT_MIX);
4173 _slot_set_le(btc, CXST_EBT, cpu_to_le16(40),
4174 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4175 _slot_set_dur(btc, CXST_EBT, dur_2);
4176 break;
4177 case BTC_CXP_OFFE_WL: /* for 4-way */
4178 _slot_set(btc, CXST_E2G, 5, cxtbl[1], SLOT_MIX);
4179 _slot_set(btc, CXST_EBT, 5, cxtbl[1], SLOT_MIX);
4180 break;
4181 default:
4182 break;
4183 }
4184 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4185 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4186 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4187 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4188 break;
4189 case BTC_CXP_FIX: /* TDMA Fix-Slot */
4190 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4191 *t = t_def[CXTD_FIX];
4192
4193 switch (policy_type) {
4194 case BTC_CXP_FIX_TD3030:
4195 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4196 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4197 break;
4198 case BTC_CXP_FIX_TD5050:
4199 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4200 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
4201 break;
4202 case BTC_CXP_FIX_TD2030:
4203 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4204 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4205 break;
4206 case BTC_CXP_FIX_TD4010:
4207 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
4208 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4209 break;
4210 case BTC_CXP_FIX_TD4010ISO:
4211 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
4212 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4213 break;
4214 case BTC_CXP_FIX_TD4010ISO_DL:
4215 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
4216 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
4217 break;
4218 case BTC_CXP_FIX_TD4010ISO_UL:
4219 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
4220 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
4221 break;
4222 case BTC_CXP_FIX_TD7010:
4223 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
4224 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4225 break;
4226 case BTC_CXP_FIX_TD2060:
4227 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4228 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4229 break;
4230 case BTC_CXP_FIX_TD3060:
4231 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4232 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4233 break;
4234 case BTC_CXP_FIX_TD2080:
4235 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4236 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
4237 break;
4238 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
4239 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4240 tbl_w1, SLOT_ISO);
4241 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4242 tbl_b1, SLOT_MIX);
4243 break;
4244 default:
4245 break;
4246 }
4247 break;
4248 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
4249 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4250 *t = t_def[CXTD_PFIX];
4251
4252 switch (policy_type) {
4253 case BTC_CXP_PFIX_TD3030:
4254 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4255 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4256 break;
4257 case BTC_CXP_PFIX_TD5050:
4258 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4259 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
4260 break;
4261 case BTC_CXP_PFIX_TD2030:
4262 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4263 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4264 break;
4265 case BTC_CXP_PFIX_TD2060:
4266 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4267 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4268 break;
4269 case BTC_CXP_PFIX_TD3070:
4270 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4271 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4272 break;
4273 case BTC_CXP_PFIX_TD2080:
4274 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4275 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
4276 break;
4277 case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */
4278 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4279 tbl_w1, SLOT_ISO);
4280 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4281 tbl_b1, SLOT_MIX);
4282 break;
4283 default:
4284 break;
4285 }
4286 break;
4287 case BTC_CXP_AUTO: /* TDMA Auto-Slot */
4288 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4289 *t = t_def[CXTD_AUTO];
4290
4291 switch (policy_type) {
4292 case BTC_CXP_AUTO_TD50B1:
4293 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4294 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4295 break;
4296 case BTC_CXP_AUTO_TD60B1:
4297 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4298 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4299 break;
4300 case BTC_CXP_AUTO_TD20B1:
4301 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4302 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4303 break;
4304 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
4305 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4306 tbl_w1, SLOT_ISO);
4307 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4308 tbl_b1, SLOT_MIX);
4309 break;
4310 default:
4311 break;
4312 }
4313 break;
4314 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
4315 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4316 *t = t_def[CXTD_PAUTO];
4317
4318 switch (policy_type) {
4319 case BTC_CXP_PAUTO_TD50B1:
4320 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4321 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4322 break;
4323 case BTC_CXP_PAUTO_TD60B1:
4324 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4325 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4326 break;
4327 case BTC_CXP_PAUTO_TD20B1:
4328 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4329 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4330 break;
4331 case BTC_CXP_PAUTO_TDW1B1:
4332 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4333 tbl_w1, SLOT_ISO);
4334 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4335 tbl_b1, SLOT_MIX);
4336 break;
4337 default:
4338 break;
4339 }
4340 break;
4341 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
4342 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4343 *t = t_def[CXTD_AUTO2];
4344
4345 switch (policy_type) {
4346 case BTC_CXP_AUTO2_TD3050:
4347 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4348 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4349 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4350 break;
4351 case BTC_CXP_AUTO2_TD3070:
4352 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4353 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4354 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
4355 break;
4356 case BTC_CXP_AUTO2_TD5050:
4357 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4358 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4359 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4360 break;
4361 case BTC_CXP_AUTO2_TD6060:
4362 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4363 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4364 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
4365 break;
4366 case BTC_CXP_AUTO2_TD2080:
4367 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4368 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4369 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
4370 break;
4371 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
4372 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4373 tbl_w1, SLOT_ISO);
4374 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4375 tbl_b1, SLOT_MIX);
4376 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
4377 tbl_b4, SLOT_MIX);
4378 break;
4379 default:
4380 break;
4381 }
4382 break;
4383 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
4384 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4385 *t = t_def[CXTD_PAUTO2];
4386
4387 switch (policy_type) {
4388 case BTC_CXP_PAUTO2_TD3050:
4389 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4390 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4391 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4392 break;
4393 case BTC_CXP_PAUTO2_TD3070:
4394 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4395 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4396 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
4397 break;
4398 case BTC_CXP_PAUTO2_TD5050:
4399 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4400 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4401 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4402 break;
4403 case BTC_CXP_PAUTO2_TD6060:
4404 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4405 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4406 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
4407 break;
4408 case BTC_CXP_PAUTO2_TD2080:
4409 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4410 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4411 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
4412 break;
4413 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
4414 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4415 tbl_w1, SLOT_ISO);
4416 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4417 tbl_b1, SLOT_MIX);
4418 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
4419 tbl_b4, SLOT_MIX);
4420 break;
4421 default:
4422 break;
4423 }
4424 break;
4425 }
4426
4427 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) {
4428 null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) |
4429 FIELD_PREP(0xf0, dm->wl_scc.null_role2);
4430 _tdma_set_flctrl_role(btc, null_role);
4431 }
4432
4433 /* enter leak_slot after each null-1 */
4434 if (dm->leak_ap && dm->tdma.leak_n > 1)
4435 _tdma_set_lek(btc, 1);
4436
4437 if (dm->tdma_instant_excute) {
4438 btc->dm.tdma.option_ctrl |= BIT(0);
4439 btc->update_policy_force = true;
4440 }
4441 }
4442 EXPORT_SYMBOL(rtw89_btc_set_policy_v1);
4443
_set_bt_plut(struct rtw89_dev * rtwdev,u8 phy_map,u8 tx_val,u8 rx_val)4444 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
4445 u8 tx_val, u8 rx_val)
4446 {
4447 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
4448 struct rtw89_mac_ax_plt plt;
4449
4450 plt.tx = tx_val;
4451 plt.rx = rx_val;
4452
4453 if (rtwdev->btc.ver->fwlrole == 8) {
4454 plt.band = wl->pta_req_mac;
4455 if (wl->bt_polut_type[plt.band] == tx_val)
4456 return;
4457
4458 wl->bt_polut_type[plt.band] = tx_val;
4459 rtw89_mac_cfg_plt(rtwdev, &plt);
4460 } else {
4461 plt.band = RTW89_MAC_0;
4462
4463 if (phy_map & BTC_PHY_0)
4464 rtw89_mac_cfg_plt(rtwdev, &plt);
4465
4466 if (!rtwdev->dbcc_en)
4467 return;
4468
4469 plt.band = RTW89_MAC_1;
4470 if (phy_map & BTC_PHY_1)
4471 rtw89_mac_cfg_plt(rtwdev, &plt);
4472 }
4473 }
4474
_set_ant_v0(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4475 static void _set_ant_v0(struct rtw89_dev *rtwdev, bool force_exec,
4476 u8 phy_map, u8 type)
4477 {
4478 struct rtw89_btc *btc = &rtwdev->btc;
4479 struct rtw89_btc_dm *dm = &btc->dm;
4480 struct rtw89_btc_cx *cx = &btc->cx;
4481 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4482 struct rtw89_btc_bt_info *bt = &cx->bt;
4483 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4484 u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0;
4485 bool dbcc_chg = false;
4486 u32 ant_path_type;
4487
4488 ant_path_type = ((phy_map << 8) + type);
4489
4490 if (btc->ver->fwlrole == 1)
4491 dbcc_chg = wl->role_info_v1.dbcc_chg;
4492 else if (btc->ver->fwlrole == 2)
4493 dbcc_chg = wl->role_info_v2.dbcc_chg;
4494 else if (btc->ver->fwlrole == 7)
4495 dbcc_chg = wl->role_info_v7.dbcc_chg;
4496 else if (btc->ver->fwlrole == 8)
4497 dbcc_chg = wl->role_info_v8.dbcc_chg;
4498
4499 if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
4500 btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
4501 btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || dbcc_chg)
4502 force_exec = FC_EXEC;
4503
4504 if (!force_exec && ant_path_type == dm->set_ant_path) {
4505 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4506 "[BTC], %s(): return by no change!!\n",
4507 __func__);
4508 return;
4509 } else if (bt->rfk_info.map.run) {
4510 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4511 "[BTC], %s(): return by bt rfk!!\n", __func__);
4512 return;
4513 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
4514 wl->rfk_info.state != BTC_WRFK_STOP) {
4515 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4516 "[BTC], %s(): return by wl rfk!!\n", __func__);
4517 return;
4518 }
4519
4520 dm->set_ant_path = ant_path_type;
4521
4522 rtw89_debug(rtwdev,
4523 RTW89_DBG_BTC,
4524 "[BTC], %s(): path=0x%x, set_type=0x%x\n",
4525 __func__, phy_map, dm->set_ant_path & 0xff);
4526
4527 switch (type) {
4528 case BTC_ANT_WPOWERON:
4529 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4530 break;
4531 case BTC_ANT_WINIT:
4532 if (bt->enable.now)
4533 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
4534 else
4535 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4536
4537 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4538 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT);
4539 break;
4540 case BTC_ANT_WONLY:
4541 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4542 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4543 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4544 break;
4545 case BTC_ANT_WOFF:
4546 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4547 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4548 break;
4549 case BTC_ANT_W2G:
4550 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4551 if (rtwdev->dbcc_en) {
4552 for (i = 0; i < RTW89_PHY_NUM; i++) {
4553 b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G);
4554
4555 gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
4556 gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
4557 /* BT should control by GNT_BT if WL_2G at S0 */
4558 if (i == 1 &&
4559 wl_dinfo->real_band[0] == RTW89_BAND_2G &&
4560 wl_dinfo->real_band[1] == RTW89_BAND_5G)
4561 gnt_bt_ctrl = BTC_GNT_HW;
4562 _set_gnt(rtwdev, BIT(i), gnt_wl_ctrl, gnt_bt_ctrl);
4563 plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE;
4564 _set_bt_plut(rtwdev, BIT(i),
4565 plt_ctrl, plt_ctrl);
4566 }
4567 } else {
4568 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
4569 _set_bt_plut(rtwdev, BTC_PHY_ALL,
4570 BTC_PLT_BT, BTC_PLT_BT);
4571 }
4572 break;
4573 case BTC_ANT_W5G:
4574 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4575 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW);
4576 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4577 break;
4578 case BTC_ANT_W25G:
4579 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4580 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
4581 _set_bt_plut(rtwdev, BTC_PHY_ALL,
4582 BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
4583 break;
4584 case BTC_ANT_FREERUN:
4585 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4586 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI);
4587 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4588 break;
4589 case BTC_ANT_WRFK:
4590 case BTC_ANT_WRFK2:
4591 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4592 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4593 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
4594 break;
4595 case BTC_ANT_BRFK:
4596 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4597 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
4598 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
4599 break;
4600 default:
4601 break;
4602 }
4603 }
4604
_set_ant_v1(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4605 static void _set_ant_v1(struct rtw89_dev *rtwdev, bool force_exec,
4606 u8 phy_map, u8 type)
4607 {
4608 struct rtw89_btc *btc = &rtwdev->btc;
4609 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4610 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4611 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
4612 u32 ant_path_type = rtw89_get_antpath_type(phy_map, type);
4613 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4614 struct rtw89_btc_dm *dm = &btc->dm;
4615 u8 gwl = BTC_GNT_HW;
4616
4617 if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
4618 btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
4619 btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || wl_rinfo->dbcc_chg)
4620 force_exec = FC_EXEC;
4621
4622 if (wl_rinfo->link_mode != BTC_WLINK_25G_MCC &&
4623 btc->dm.wl_btg_rx == 2)
4624 force_exec = FC_EXEC;
4625
4626 if (!force_exec && ant_path_type == dm->set_ant_path) {
4627 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4628 "[BTC], %s(): return by no change!!\n",
4629 __func__);
4630 return;
4631 } else if (bt->rfk_info.map.run) {
4632 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4633 "[BTC], %s(): return by bt rfk!!\n", __func__);
4634 return;
4635 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
4636 wl->rfk_info.state != BTC_WRFK_STOP) {
4637 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4638 "[BTC], %s(): return by wl rfk!!\n", __func__);
4639 return;
4640 }
4641
4642 dm->set_ant_path = ant_path_type;
4643
4644 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4645 "[BTC], %s(): path=0x%x, set_type=0x%x\n",
4646 __func__, phy_map, dm->set_ant_path & 0xff);
4647
4648 switch (type) {
4649 case BTC_ANT_WINIT:
4650 /* To avoid BT MP driver case (bt_enable but no mailbox) */
4651 if (bt->enable.now && bt->run_patch_code)
4652 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
4653 BTC_WLACT_SW_LO);
4654 else
4655 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4656 BTC_WLACT_SW_HI);
4657 break;
4658 case BTC_ANT_WONLY:
4659 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4660 BTC_WLACT_SW_HI);
4661 break;
4662 case BTC_ANT_WOFF:
4663 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
4664 BTC_WLACT_SW_LO);
4665 break;
4666 case BTC_ANT_W2G:
4667 case BTC_ANT_W25G:
4668 if (wl_rinfo->dbcc_en) {
4669 if (wl_dinfo->real_band[RTW89_PHY_0] == RTW89_BAND_2G)
4670 gwl = BTC_GNT_HW;
4671 else
4672 gwl = BTC_GNT_SW_HI;
4673 _set_gnt_v1(rtwdev, BTC_PHY_0, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4674
4675 if (wl_dinfo->real_band[RTW89_PHY_1] == RTW89_BAND_2G)
4676 gwl = BTC_GNT_HW;
4677 else
4678 gwl = BTC_GNT_SW_HI;
4679 _set_gnt_v1(rtwdev, BTC_PHY_1, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4680 } else {
4681 gwl = BTC_GNT_HW;
4682 _set_gnt_v1(rtwdev, phy_map, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4683 }
4684 break;
4685 case BTC_ANT_W5G:
4686 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW, BTC_WLACT_HW);
4687 break;
4688 case BTC_ANT_FREERUN:
4689 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI,
4690 BTC_WLACT_SW_LO);
4691 break;
4692 case BTC_ANT_WRFK:
4693 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4694 BTC_WLACT_HW);
4695 break;
4696 case BTC_ANT_WRFK2:
4697 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4698 BTC_WLACT_SW_HI); /* no BT-Tx */
4699 break;
4700 default:
4701 return;
4702 }
4703
4704 _set_bt_plut(rtwdev, phy_map, BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
4705 }
4706
_set_ant(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4707 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
4708 u8 phy_map, u8 type)
4709 {
4710 if (rtwdev->chip->chip_id == RTL8922A)
4711 _set_ant_v1(rtwdev, force_exec, phy_map, type);
4712 else
4713 _set_ant_v0(rtwdev, force_exec, phy_map, type);
4714 }
4715
_action_wl_only(struct rtw89_dev * rtwdev)4716 static void _action_wl_only(struct rtw89_dev *rtwdev)
4717 {
4718 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
4719 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY);
4720 }
4721
_action_wl_init(struct rtw89_dev * rtwdev)4722 static void _action_wl_init(struct rtw89_dev *rtwdev)
4723 {
4724 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4725
4726 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT);
4727 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT);
4728 }
4729
_action_wl_off(struct rtw89_dev * rtwdev,u8 mode)4730 static void _action_wl_off(struct rtw89_dev *rtwdev, u8 mode)
4731 {
4732 struct rtw89_btc *btc = &rtwdev->btc;
4733 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4734
4735 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4736
4737 if (wl->status.map.rf_off || btc->dm.bt_only) {
4738 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF);
4739 } else if (wl->status.map.lps == BTC_LPS_RF_ON) {
4740 if (mode == BTC_WLINK_5G)
4741 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
4742 else
4743 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4744 }
4745
4746 if (mode == BTC_WLINK_5G) {
4747 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OFF);
4748 } else if (wl->status.map.lps == BTC_LPS_RF_ON) {
4749 if (btc->cx.bt.link_info.a2dp_desc.active)
4750 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
4751 else
4752 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_WL_OFF);
4753 } else {
4754 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
4755 }
4756 }
4757
_action_freerun(struct rtw89_dev * rtwdev)4758 static void _action_freerun(struct rtw89_dev *rtwdev)
4759 {
4760 struct rtw89_btc *btc = &rtwdev->btc;
4761
4762 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4763
4764 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN);
4765 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN);
4766
4767 btc->dm.freerun = true;
4768 }
4769
_action_bt_whql(struct rtw89_dev * rtwdev)4770 static void _action_bt_whql(struct rtw89_dev *rtwdev)
4771 {
4772 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4773
4774 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4775 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL);
4776 }
4777
_action_bt_off(struct rtw89_dev * rtwdev)4778 static void _action_bt_off(struct rtw89_dev *rtwdev)
4779 {
4780 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4781
4782 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
4783 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF);
4784 }
4785
_action_bt_idle(struct rtw89_dev * rtwdev)4786 static void _action_bt_idle(struct rtw89_dev *rtwdev)
4787 {
4788 struct rtw89_btc *btc = &rtwdev->btc;
4789 struct rtw89_btc_bt_link_info *b = &btc->cx.bt.link_info;
4790 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4791
4792 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4793
4794 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
4795 switch (btc->cx.state_map) {
4796 case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/
4797 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */
4798 if (b->status.map.connect)
4799 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_IDLE);
4800 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
4801 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_DL, BTC_ACT_BT_IDLE);
4802 else
4803 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_UL, BTC_ACT_BT_IDLE);
4804 break;
4805 case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */
4806 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050,
4807 BTC_ACT_BT_IDLE);
4808 break;
4809 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */
4810 _set_policy(rtwdev, BTC_CXP_FIX_TD5050,
4811 BTC_ACT_BT_IDLE);
4812 break;
4813 case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */
4814 _set_policy(rtwdev, BTC_CXP_FIX_TD7010,
4815 BTC_ACT_BT_IDLE);
4816 break;
4817 case BTC_WIDLE: /* wl-idle + bt-idle */
4818 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE);
4819 break;
4820 }
4821 } else { /* dedicated-antenna */
4822 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE);
4823 }
4824 }
4825
_action_bt_hfp(struct rtw89_dev * rtwdev)4826 static void _action_bt_hfp(struct rtw89_dev *rtwdev)
4827 {
4828 struct rtw89_btc *btc = &rtwdev->btc;
4829 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4830
4831 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4832
4833 if (btc->ant_type == BTC_ANT_SHARED) {
4834 if (btc->cx.wl.status.map._4way) {
4835 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP);
4836 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4837 btc->cx.bt.scan_rx_low_pri = true;
4838 _set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP);
4839 } else {
4840 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
4841 }
4842 } else {
4843 if (wl->bg_mode)
4844 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
4845 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
4846 _set_policy(rtwdev, BTC_CXP_OFF_EQ5, BTC_ACT_BT_HFP);
4847 else
4848 _set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP);
4849 }
4850 }
4851
_action_bt_hid(struct rtw89_dev * rtwdev)4852 static void _action_bt_hid(struct rtw89_dev *rtwdev)
4853 {
4854 const struct rtw89_chip_info *chip = rtwdev->chip;
4855 struct rtw89_btc *btc = &rtwdev->btc;
4856 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4857 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4858 struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc;
4859 u16 policy_type = BTC_CXP_OFF_BT;
4860
4861 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4862
4863 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
4864 if (wl->status.map._4way) {
4865 policy_type = BTC_CXP_OFF_WL;
4866 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4867 btc->cx.bt.scan_rx_low_pri = true;
4868 if (hid->type & BTC_HID_BLE)
4869 policy_type = BTC_CXP_OFF_BWB0;
4870 else
4871 policy_type = BTC_CXP_OFF_BWB2;
4872 } else if (hid->type == BTC_HID_218) {
4873 bt->scan_rx_low_pri = true;
4874 policy_type = BTC_CXP_OFF_BWB2;
4875 } else if (chip->para_ver == 0x1) {
4876 policy_type = BTC_CXP_OFF_BWB3;
4877 } else {
4878 policy_type = BTC_CXP_OFF_BWB1;
4879 }
4880 } else { /* dedicated-antenna */
4881 if (wl->bg_mode)
4882 policy_type = BTC_CXP_OFF_BWB1;
4883 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
4884 policy_type = BTC_CXP_OFF_EQ4;
4885 else
4886 policy_type = BTC_CXP_OFF_EQ3;
4887 }
4888
4889 _set_policy(rtwdev, policy_type, BTC_ACT_BT_HID);
4890 }
4891
_action_bt_a2dp(struct rtw89_dev * rtwdev)4892 static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
4893 {
4894 struct rtw89_btc *btc = &rtwdev->btc;
4895 struct rtw89_btc_dm *dm = &btc->dm;
4896
4897 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4898
4899 dm->slot_dur[CXST_W1] = 20;
4900 dm->slot_dur[CXST_B1] = BTC_B1_MAX;
4901
4902 switch (btc->cx.state_map) {
4903 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
4904 _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
4905 break;
4906 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
4907 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP);
4908 break;
4909 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */
4910 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP);
4911 break;
4912 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
4913 case BTC_WLINKING: /* wl-connecting + bt-A2DP */
4914 if (btc->cx.wl.rfk_info.con_rfk)
4915 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP);
4916 else
4917 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP);
4918 break;
4919 case BTC_WIDLE: /* wl-idle + bt-A2DP */
4920 _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP);
4921 break;
4922 }
4923 }
4924
_action_bt_a2dpsink(struct rtw89_dev * rtwdev)4925 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev)
4926 {
4927 struct rtw89_btc *btc = &rtwdev->btc;
4928
4929 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4930
4931 switch (btc->cx.state_map) {
4932 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */
4933 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK);
4934 break;
4935 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */
4936 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK);
4937 break;
4938 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */
4939 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK);
4940 break;
4941 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */
4942 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK);
4943 break;
4944 case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */
4945 if (btc->cx.wl.rfk_info.con_rfk)
4946 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DPSINK);
4947 else
4948 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
4949 break;
4950 case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */
4951 _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK);
4952 break;
4953 }
4954 }
4955
_action_bt_pan(struct rtw89_dev * rtwdev)4956 static void _action_bt_pan(struct rtw89_dev *rtwdev)
4957 {
4958 struct rtw89_btc *btc = &rtwdev->btc;
4959 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
4960 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
4961 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
4962
4963 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4964
4965 switch (btc->cx.state_map) {
4966 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */
4967 if (a2dp.active || !pan.exist) {
4968 btc->dm.slot_dur[CXST_W1] = 80;
4969 btc->dm.slot_dur[CXST_B1] = 20;
4970 _set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN);
4971 } else {
4972 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
4973 }
4974 break;
4975 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */
4976 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN);
4977 break;
4978 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */
4979 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN);
4980 break;
4981 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */
4982 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN);
4983 break;
4984 case BTC_WLINKING: /* wl-connecting + bt-PAN */
4985 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO, BTC_ACT_BT_PAN);
4986 break;
4987 case BTC_WIDLE: /* wl-idle + bt-pan */
4988 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN);
4989 break;
4990 }
4991 }
4992
_action_bt_a2dp_hid(struct rtw89_dev * rtwdev)4993 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
4994 {
4995 struct rtw89_btc *btc = &rtwdev->btc;
4996 struct rtw89_btc_dm *dm = &btc->dm;
4997
4998 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4999
5000 dm->slot_dur[CXST_W1] = 20;
5001 dm->slot_dur[CXST_B1] = BTC_B1_MAX;
5002
5003 switch (btc->cx.state_map) {
5004 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */
5005 case BTC_WIDLE: /* wl-idle + bt-A2DP */
5006 _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
5007 break;
5008 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */
5009 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_HID);
5010 break;
5011
5012 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */
5013 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
5014 break;
5015 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */
5016 case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */
5017 if (btc->cx.wl.rfk_info.con_rfk)
5018 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP_HID);
5019 else
5020 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
5021 break;
5022 }
5023 }
5024
_action_bt_a2dp_pan(struct rtw89_dev * rtwdev)5025 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev)
5026 {
5027 struct rtw89_btc *btc = &rtwdev->btc;
5028
5029 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5030
5031 switch (btc->cx.state_map) {
5032 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */
5033 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
5034 break;
5035 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */
5036 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
5037 break;
5038 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */
5039 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN);
5040 break;
5041 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */
5042 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
5043 break;
5044 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */
5045 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN);
5046 break;
5047 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */
5048 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN);
5049 break;
5050 }
5051 }
5052
_action_bt_pan_hid(struct rtw89_dev * rtwdev)5053 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev)
5054 {
5055 struct rtw89_btc *btc = &rtwdev->btc;
5056
5057 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5058
5059 switch (btc->cx.state_map) {
5060 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */
5061 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID);
5062 break;
5063 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */
5064 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID);
5065 break;
5066 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */
5067 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID);
5068 break;
5069 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */
5070 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID);
5071 break;
5072 case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */
5073 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID);
5074 break;
5075 case BTC_WIDLE: /* wl-idle + bt-PAN+HID */
5076 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID);
5077 break;
5078 }
5079 }
5080
_action_bt_a2dp_pan_hid(struct rtw89_dev * rtwdev)5081 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev)
5082 {
5083 struct rtw89_btc *btc = &rtwdev->btc;
5084
5085 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5086
5087 switch (btc->cx.state_map) {
5088 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */
5089 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
5090 BTC_ACT_BT_A2DP_PAN_HID);
5091 break;
5092 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */
5093 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
5094 BTC_ACT_BT_A2DP_PAN_HID);
5095 break;
5096 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */
5097 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070,
5098 BTC_ACT_BT_A2DP_PAN_HID);
5099 break;
5100 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */
5101 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */
5102 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050,
5103 BTC_ACT_BT_A2DP_PAN_HID);
5104 break;
5105 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */
5106 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080,
5107 BTC_ACT_BT_A2DP_PAN_HID);
5108 break;
5109 }
5110 }
5111
_action_wl_5g(struct rtw89_dev * rtwdev)5112 static void _action_wl_5g(struct rtw89_dev *rtwdev)
5113 {
5114 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
5115 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G);
5116 }
5117
_action_wl_other(struct rtw89_dev * rtwdev)5118 static void _action_wl_other(struct rtw89_dev *rtwdev)
5119 {
5120 struct rtw89_btc *btc = &rtwdev->btc;
5121
5122 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5123
5124 if (btc->ant_type == BTC_ANT_SHARED)
5125 _set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER);
5126 else
5127 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER);
5128 }
5129
_action_wl_nc(struct rtw89_dev * rtwdev)5130 static void _action_wl_nc(struct rtw89_dev *rtwdev)
5131 {
5132 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5133 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC);
5134 }
5135
_action_wl_rfk(struct rtw89_dev * rtwdev)5136 static void _action_wl_rfk(struct rtw89_dev *rtwdev)
5137 {
5138 struct rtw89_btc *btc = &rtwdev->btc;
5139 struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info;
5140
5141 if (rfk.state != BTC_WRFK_START)
5142 return;
5143
5144 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n",
5145 __func__, rfk.band);
5146
5147 btc->dm.tdma_instant_excute = 1;
5148
5149 if (rfk.state == BTC_WRFK_ONESHOT_START ||
5150 btc->ant_type == BTC_ANT_SHARED) {
5151 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2);
5152 _set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK);
5153 } else {
5154 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
5155 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK);
5156 }
5157 }
5158
_set_btg_ctrl(struct rtw89_dev * rtwdev)5159 static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
5160 {
5161 struct rtw89_btc *btc = &rtwdev->btc;
5162 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5163 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5164 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5165 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
5166 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5167 struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info;
5168 struct rtw89_btc_wl_role_info *wl_rinfo_v0 = &wl->role_info;
5169 const struct rtw89_chip_info *chip = rtwdev->chip;
5170 const struct rtw89_btc_ver *ver = btc->ver;
5171 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5172 struct rtw89_btc_dm *dm = &btc->dm;
5173 struct _wl_rinfo_now wl_rinfo;
5174 u32 is_btg = BTC_BTGCTRL_DISABLE;
5175
5176 if (btc->manual_ctrl)
5177 return;
5178
5179 if (ver->fwlrole == 0)
5180 wl_rinfo.link_mode = wl_rinfo_v0->link_mode;
5181 else if (ver->fwlrole == 1)
5182 wl_rinfo.link_mode = wl_rinfo_v1->link_mode;
5183 else if (ver->fwlrole == 2)
5184 wl_rinfo.link_mode = wl_rinfo_v2->link_mode;
5185 else if (ver->fwlrole == 7)
5186 wl_rinfo.link_mode = wl_rinfo_v7->link_mode;
5187 else if (ver->fwlrole == 8)
5188 wl_rinfo.link_mode = wl_rinfo_v8->link_mode;
5189 else
5190 return;
5191
5192 /* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */
5193 if (btc->ant_type == BTC_ANT_SHARED) {
5194 if (!(bt->run_patch_code && bt->enable.now))
5195 is_btg = BTC_BTGCTRL_DISABLE;
5196 else if (wl_rinfo.link_mode != BTC_WLINK_5G)
5197 is_btg = BTC_BTGCTRL_ENABLE;
5198 else
5199 is_btg = BTC_BTGCTRL_DISABLE;
5200
5201 /* bb call ctrl_btg() in WL FW by slot */
5202 if (!ver->fcxosi &&
5203 wl_rinfo.link_mode == BTC_WLINK_25G_MCC)
5204 is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL;
5205 }
5206
5207 if (is_btg == dm->wl_btg_rx)
5208 return;
5209 else
5210 dm->wl_btg_rx = is_btg;
5211
5212 /* skip setup if btg_ctrl set by wl fw */
5213 if (!ver->fcxosi && is_btg > BTC_BTGCTRL_ENABLE)
5214 return;
5215
5216 /* Below flow is for BTC_FEAT_NEW_BBAPI_FLOW = 1 */
5217 if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */
5218 if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */
5219 o_info->btg_rx[BTC_RF_S0] = BTC_BTGCTRL_DISABLE;
5220 else
5221 o_info->btg_rx[BTC_RF_S0] = is_btg;
5222
5223 if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */
5224 o_info->btg_rx[BTC_RF_S1] = BTC_BTGCTRL_DISABLE;
5225 else
5226 o_info->btg_rx[BTC_RF_S1] = is_btg;
5227 } else { /* 2+0 or 0+2 */
5228 o_info->btg_rx[BTC_RF_S0] = is_btg;
5229 o_info->btg_rx[BTC_RF_S1] = is_btg;
5230 }
5231
5232 if (ver->fcxosi)
5233 return;
5234
5235 chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S0],
5236 RTW89_PHY_0);
5237 if (chip->chip_id != RTL8922A)
5238 return;
5239
5240 chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S1],
5241 RTW89_PHY_1);
5242 }
5243
_set_wl_preagc_ctrl(struct rtw89_dev * rtwdev)5244 static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev)
5245 {
5246 struct rtw89_btc *btc = &rtwdev->btc;
5247 struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info;
5248 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
5249 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5250 struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2;
5251 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
5252 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8;
5253 const struct rtw89_chip_info *chip = rtwdev->chip;
5254 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5255 struct rtw89_btc_dm *dm = &btc->dm;
5256 u8 is_preagc, val, link_mode, dbcc_2g_phy;
5257 u8 role_ver = rtwdev->btc.ver->fwlrole;
5258 bool dbcc_en;
5259
5260 if (btc->manual_ctrl)
5261 return;
5262
5263 if (role_ver == 2) {
5264 dbcc_en = rinfo_v2->dbcc_en;
5265 link_mode = rinfo_v2->link_mode;
5266 dbcc_2g_phy = rinfo_v2->dbcc_2g_phy;
5267 } else if (role_ver == 7) {
5268 dbcc_en = rinfo_v7->dbcc_en;
5269 link_mode = rinfo_v7->link_mode;
5270 dbcc_2g_phy = rinfo_v7->dbcc_2g_phy;
5271 } else if (role_ver == 8) {
5272 dbcc_en = rinfo_v8->dbcc_en;
5273 link_mode = rinfo_v8->link_mode;
5274 dbcc_2g_phy = rinfo_v7->dbcc_2g_phy;
5275 } else {
5276 return;
5277 }
5278
5279 if (!(bt->run_patch_code && bt->enable.now)) {
5280 is_preagc = BTC_PREAGC_DISABLE;
5281 } else if (link_mode == BTC_WLINK_5G) {
5282 is_preagc = BTC_PREAGC_DISABLE;
5283 } else if (link_mode == BTC_WLINK_NOLINK ||
5284 btc->cx.bt.link_info.profile_cnt.now == 0) {
5285 is_preagc = BTC_PREAGC_DISABLE;
5286 } else if (dm->tdma_now.type != CXTDMA_OFF &&
5287 !bt_linfo->hfp_desc.exist &&
5288 !bt_linfo->hid_desc.exist &&
5289 dm->fddt_train == BTC_FDDT_DISABLE) {
5290 is_preagc = BTC_PREAGC_DISABLE;
5291 } else if (dbcc_en && (dbcc_2g_phy != RTW89_PHY_1)) {
5292 is_preagc = BTC_PREAGC_DISABLE;
5293 } else if (btc->ant_type == BTC_ANT_SHARED) {
5294 is_preagc = BTC_PREAGC_DISABLE;
5295 } else {
5296 is_preagc = BTC_PREAGC_ENABLE;
5297 }
5298
5299 if (!btc->ver->fcxosi && link_mode == BTC_WLINK_25G_MCC)
5300 is_preagc = BTC_PREAGC_BB_FWCTRL;
5301
5302 if (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
5303 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) {
5304 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val);
5305 dm->wl_pre_agc_rb = val;
5306 }
5307
5308 if ((wl->coex_mode == BTC_MODE_NORMAL &&
5309 (dm->run_reason == BTC_RSN_NTFY_INIT ||
5310 dm->run_reason == BTC_RSN_NTFY_SWBAND ||
5311 dm->wl_pre_agc_rb != dm->wl_pre_agc)) ||
5312 is_preagc != dm->wl_pre_agc) {
5313 dm->wl_pre_agc = is_preagc;
5314
5315 if (!btc->ver->fcxosi && is_preagc > BTC_PREAGC_ENABLE)
5316 return;
5317
5318 if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */
5319 if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */
5320 o_info->nbtg_tx[BTC_RF_S0] = BTC_PREAGC_DISABLE;
5321 else
5322 o_info->nbtg_tx[BTC_RF_S0] = is_preagc;
5323
5324 if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */
5325 o_info->nbtg_tx[BTC_RF_S1] = BTC_PREAGC_DISABLE;
5326 else
5327 o_info->nbtg_tx[BTC_RF_S1] = is_preagc;
5328
5329 } else { /* 2+0 or 0+2 */
5330 o_info->nbtg_tx[BTC_RF_S0] = is_preagc;
5331 o_info->nbtg_tx[BTC_RF_S1] = is_preagc;
5332 }
5333
5334 if (btc->ver->fcxosi)
5335 return;
5336
5337 chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S0],
5338 RTW89_PHY_0);
5339 if (chip->chip_id != RTL8922A)
5340 return;
5341 chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S1],
5342 RTW89_PHY_1);
5343 }
5344 }
5345
5346 struct rtw89_txtime_data {
5347 struct rtw89_dev *rtwdev;
5348 int type;
5349 u32 tx_time;
5350 u8 tx_retry;
5351 u16 enable;
5352 bool reenable;
5353 };
5354
__rtw89_tx_time_iter(struct rtw89_vif_link * rtwvif_link,struct rtw89_sta_link * rtwsta_link,struct rtw89_txtime_data * iter_data)5355 static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link,
5356 struct rtw89_sta_link *rtwsta_link,
5357 struct rtw89_txtime_data *iter_data)
5358 {
5359 struct rtw89_dev *rtwdev = iter_data->rtwdev;
5360 struct rtw89_btc *btc = &rtwdev->btc;
5361 struct rtw89_btc_cx *cx = &btc->cx;
5362 struct rtw89_btc_wl_info *wl = &cx->wl;
5363 struct rtw89_btc_wl_link_info *plink = NULL;
5364 u8 port = rtwvif_link->port;
5365 u32 tx_time = iter_data->tx_time;
5366 u8 tx_retry = iter_data->tx_retry;
5367 u16 enable = iter_data->enable;
5368 bool reenable = iter_data->reenable;
5369
5370 if (btc->ver->fwlrole == 8)
5371 plink = &wl->rlink_info[port][0];
5372 else
5373 plink = &wl->link_info[port];
5374
5375 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5376 "[BTC], %s(): port = %d\n", __func__, port);
5377
5378 if (!plink->connected) {
5379 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5380 "[BTC], %s(): connected = %d\n",
5381 __func__, plink->connected);
5382 return;
5383 }
5384
5385 /* backup the original tx time before tx-limit on */
5386 if (reenable) {
5387 rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time);
5388 rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry);
5389 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5390 "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n",
5391 __func__, plink->tx_time, plink->tx_retry);
5392 }
5393
5394 /* restore the original tx time if no tx-limit */
5395 if (!enable) {
5396 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time);
5397 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true,
5398 plink->tx_retry);
5399 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5400 "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n",
5401 __func__, plink->tx_time, plink->tx_retry);
5402
5403 } else {
5404 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time);
5405 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry);
5406 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5407 "[BTC], %s(): set, tx_time=%d tx_retry= %d\n",
5408 __func__, tx_time, tx_retry);
5409 }
5410 }
5411
rtw89_tx_time_iter(void * data,struct ieee80211_sta * sta)5412 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
5413 {
5414 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
5415 struct rtw89_txtime_data *iter_data =
5416 (struct rtw89_txtime_data *)data;
5417 struct rtw89_vif_link *rtwvif_link;
5418 struct rtw89_sta_link *rtwsta_link;
5419 unsigned int link_id;
5420
5421 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
5422 rtwvif_link = rtwsta_link->rtwvif_link;
5423 __rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data);
5424 }
5425 }
5426
_set_wl_tx_limit(struct rtw89_dev * rtwdev)5427 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
5428 {
5429 struct rtw89_btc *btc = &rtwdev->btc;
5430 const struct rtw89_btc_ver *ver = btc->ver;
5431 struct rtw89_btc_cx *cx = &btc->cx;
5432 struct rtw89_btc_dm *dm = &btc->dm;
5433 struct rtw89_btc_wl_info *wl = &cx->wl;
5434 struct rtw89_btc_bt_info *bt = &cx->bt;
5435 struct rtw89_btc_bt_link_info *b = &bt->link_info;
5436 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
5437 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
5438 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5439 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5440 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5441 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
5442 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5443 struct rtw89_txtime_data data = {.rtwdev = rtwdev};
5444 u8 mode, igno_bt, tx_retry;
5445 u32 tx_time;
5446 u16 enable;
5447 bool reenable = false;
5448
5449 if (btc->manual_ctrl)
5450 return;
5451
5452 if (ver->fwlrole == 0)
5453 mode = wl_rinfo->link_mode;
5454 else if (ver->fwlrole == 1)
5455 mode = wl_rinfo_v1->link_mode;
5456 else if (ver->fwlrole == 2)
5457 mode = wl_rinfo_v2->link_mode;
5458 else if (ver->fwlrole == 7)
5459 mode = wl_rinfo_v7->link_mode;
5460 else if (ver->fwlrole == 8)
5461 mode = wl_rinfo_v8->link_mode;
5462 else
5463 return;
5464
5465 if (ver->fcxctrl == 7)
5466 igno_bt = btc->ctrl.ctrl_v7.igno_bt;
5467 else
5468 igno_bt = btc->ctrl.ctrl.igno_bt;
5469
5470 if (btc->dm.freerun || igno_bt || b->profile_cnt.now == 0 ||
5471 mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) {
5472 enable = 0;
5473 tx_time = BTC_MAX_TX_TIME_DEF;
5474 tx_retry = BTC_MAX_TX_RETRY_DEF;
5475 } else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) {
5476 enable = 1;
5477 tx_time = BTC_MAX_TX_TIME_L2;
5478 tx_retry = BTC_MAX_TX_RETRY_L1;
5479 } else if (hfp->exist || hid->exist) {
5480 enable = 1;
5481 tx_time = BTC_MAX_TX_TIME_L3;
5482 tx_retry = BTC_MAX_TX_RETRY_L1;
5483 } else {
5484 enable = 0;
5485 tx_time = BTC_MAX_TX_TIME_DEF;
5486 tx_retry = BTC_MAX_TX_RETRY_DEF;
5487 }
5488
5489 if (dm->wl_tx_limit.enable == enable &&
5490 dm->wl_tx_limit.tx_time == tx_time &&
5491 dm->wl_tx_limit.tx_retry == tx_retry)
5492 return;
5493
5494 if (!dm->wl_tx_limit.enable && enable)
5495 reenable = true;
5496
5497 dm->wl_tx_limit.enable = enable;
5498 dm->wl_tx_limit.tx_time = tx_time;
5499 dm->wl_tx_limit.tx_retry = tx_retry;
5500
5501 data.enable = enable;
5502 data.tx_time = tx_time;
5503 data.tx_retry = tx_retry;
5504 data.reenable = reenable;
5505
5506 ieee80211_iterate_stations_atomic(rtwdev->hw,
5507 rtw89_tx_time_iter,
5508 &data);
5509 }
5510
_set_bt_rx_agc(struct rtw89_dev * rtwdev)5511 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
5512 {
5513 struct rtw89_btc *btc = &rtwdev->btc;
5514 const struct rtw89_btc_ver *ver = btc->ver;
5515 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5516 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5517 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5518 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5519 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
5520 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5521 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5522 bool bt_hi_lna_rx = false;
5523 u8 mode;
5524
5525 if (ver->fwlrole == 0)
5526 mode = wl_rinfo->link_mode;
5527 else if (ver->fwlrole == 1)
5528 mode = wl_rinfo_v1->link_mode;
5529 else if (ver->fwlrole == 2)
5530 mode = wl_rinfo_v2->link_mode;
5531 else if (ver->fwlrole == 7)
5532 mode = wl_rinfo_v7->link_mode;
5533 else if (ver->fwlrole == 8)
5534 mode = wl_rinfo_v8->link_mode;
5535 else
5536 return;
5537
5538 if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
5539 bt_hi_lna_rx = true;
5540
5541 if (bt_hi_lna_rx == bt->hi_lna_rx)
5542 return;
5543
5544 _write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx);
5545 }
5546
_set_bt_rx_scan_pri(struct rtw89_dev * rtwdev)5547 static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev)
5548 {
5549 struct rtw89_btc *btc = &rtwdev->btc;
5550 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5551
5552 _write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri));
5553 }
5554
_wl_req_mac(struct rtw89_dev * rtwdev,u8 mac)5555 static void _wl_req_mac(struct rtw89_dev *rtwdev, u8 mac)
5556 {
5557 struct rtw89_btc *btc = &rtwdev->btc;
5558 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5559 struct rtw89_btc_dm *dm = &btc->dm;
5560 u32 add;
5561
5562 if (mac == wl->pta_req_mac)
5563 return;
5564
5565 dm->ost_info.pta_req_hw_band = mac;
5566 wl->pta_req_mac = mac;
5567 wl->pta_reg_mac_chg = true;
5568
5569 if (btc->ver->fcxosi)
5570 return;
5571
5572 if (rtwdev->chip->chip_gen == RTW89_CHIP_BE)
5573 add = R_BE_BTC_CFG;
5574 else
5575 add = R_AX_BTC_CFG;
5576
5577 if (mac == RTW89_MAC_0)
5578 rtw89_write32_clr(rtwdev, add, B_AX_WL_SRC);
5579 else
5580 rtw89_write32_set(rtwdev, add, B_AX_WL_SRC);
5581 }
5582
_action_common(struct rtw89_dev * rtwdev)5583 static void _action_common(struct rtw89_dev *rtwdev)
5584 {
5585 struct rtw89_btc *btc = &rtwdev->btc;
5586 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5587 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8;
5588 struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
5589 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5590 struct rtw89_btc_dm *dm = &btc->dm;
5591 u32 bt_rom_code_id, bt_fw_ver;
5592
5593 if (btc->ver->fwlrole == 8)
5594 _wl_req_mac(rtwdev, rinfo_v8->pta_req_band);
5595
5596 _set_btg_ctrl(rtwdev);
5597 _set_wl_preagc_ctrl(rtwdev);
5598 _set_wl_tx_limit(rtwdev);
5599 _set_bt_afh_info(rtwdev);
5600 _set_bt_rx_agc(rtwdev);
5601 _set_rf_trx_para(rtwdev);
5602 _set_bt_rx_scan_pri(rtwdev);
5603
5604 bt_rom_code_id = chip_id_to_bt_rom_code_id(rtwdev->btc.ver->chip_id);
5605 bt_fw_ver = bt->ver_info.fw & 0xffff;
5606 if (bt->enable.now &&
5607 (bt_fw_ver == 0 ||
5608 (bt_fw_ver == bt_rom_code_id && bt->run_patch_code && rtwdev->chip->scbd)))
5609 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 1);
5610 else
5611 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 0);
5612
5613 if (dm->run_reason == BTC_RSN_NTFY_INIT ||
5614 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE ||
5615 dm->run_reason == BTC_RSN_NTFY_POWEROFF) {
5616 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
5617
5618 if (wl_smap->rf_off == 1 || wl_smap->lps != BTC_LPS_OFF)
5619 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
5620 else
5621 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
5622 }
5623
5624 if (wl->scbd_change) {
5625 rtw89_mac_cfg_sb(rtwdev, wl->scbd);
5626 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n",
5627 wl->scbd);
5628 wl->scbd_change = false;
5629 btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++;
5630 }
5631
5632 if (btc->ver->fcxosi) {
5633 if (memcmp(&dm->ost_info_last, &dm->ost_info,
5634 sizeof(dm->ost_info_last)) ||
5635 dm->run_reason == BTC_RSN_NTFY_INIT ||
5636 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE) {
5637 dm->ost_info_last = dm->ost_info;
5638 _fw_set_drv_info(rtwdev, CXDRVINFO_OSI);
5639 }
5640 }
5641 btc->dm.tdma_instant_excute = 0;
5642 wl->pta_reg_mac_chg = false;
5643 }
5644
_action_by_bt(struct rtw89_dev * rtwdev)5645 static void _action_by_bt(struct rtw89_dev *rtwdev)
5646 {
5647 struct rtw89_btc *btc = &rtwdev->btc;
5648 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5649 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
5650 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
5651 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
5652 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
5653 struct rtw89_btc_dm *dm = &btc->dm;
5654 u8 profile_map = 0;
5655
5656 if (dm->freerun_chk) {
5657 _action_freerun(rtwdev);
5658 return;
5659 }
5660
5661 if (bt_linfo->hfp_desc.exist)
5662 profile_map |= BTC_BT_HFP;
5663
5664 if (bt_linfo->hid_desc.exist)
5665 profile_map |= BTC_BT_HID;
5666
5667 if (bt_linfo->a2dp_desc.exist)
5668 profile_map |= BTC_BT_A2DP;
5669
5670 if (bt_linfo->pan_desc.exist)
5671 profile_map |= BTC_BT_PAN;
5672
5673 switch (profile_map) {
5674 case BTC_BT_NOPROFILE:
5675 if (pan.active)
5676 _action_bt_pan(rtwdev);
5677 else
5678 _action_bt_idle(rtwdev);
5679 break;
5680 case BTC_BT_HFP:
5681 _action_bt_hfp(rtwdev);
5682 break;
5683 case BTC_BT_HFP | BTC_BT_HID:
5684 case BTC_BT_HID:
5685 _action_bt_hid(rtwdev);
5686 break;
5687 case BTC_BT_A2DP:
5688 if (a2dp.sink)
5689 _action_bt_a2dpsink(rtwdev);
5690 else if (bt_linfo->multi_link.now && !hid.pair_cnt)
5691 _action_bt_a2dp_pan(rtwdev);
5692 else
5693 _action_bt_a2dp(rtwdev);
5694 break;
5695 case BTC_BT_PAN:
5696 _action_bt_pan(rtwdev);
5697 break;
5698 case BTC_BT_A2DP | BTC_BT_HFP:
5699 case BTC_BT_A2DP | BTC_BT_HID:
5700 case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID:
5701 if (a2dp.sink)
5702 _action_bt_a2dpsink(rtwdev);
5703 else if (pan.active)
5704 _action_bt_a2dp_pan_hid(rtwdev);
5705 else
5706 _action_bt_a2dp_hid(rtwdev);
5707 break;
5708 case BTC_BT_A2DP | BTC_BT_PAN:
5709 if (a2dp.sink)
5710 _action_bt_a2dpsink(rtwdev);
5711 else
5712 _action_bt_a2dp_pan(rtwdev);
5713 break;
5714 case BTC_BT_PAN | BTC_BT_HFP:
5715 case BTC_BT_PAN | BTC_BT_HID:
5716 case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID:
5717 _action_bt_pan_hid(rtwdev);
5718 break;
5719 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID:
5720 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP:
5721 default:
5722 if (a2dp.sink)
5723 _action_bt_a2dpsink(rtwdev);
5724 else
5725 _action_bt_a2dp_pan_hid(rtwdev);
5726 break;
5727 }
5728 }
5729
_action_wl_2g_sta(struct rtw89_dev * rtwdev)5730 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev)
5731 {
5732 _action_by_bt(rtwdev);
5733 }
5734
_action_wl_25g_mcc(struct rtw89_dev * rtwdev)5735 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev)
5736 {
5737 struct rtw89_btc *btc = &rtwdev->btc;
5738 u16 policy_type = BTC_CXP_OFF_BT;
5739
5740 if (btc->ant_type == BTC_ANT_SHARED) {
5741 if (btc->cx.wl.status.map._4way)
5742 policy_type = BTC_CXP_OFFE_WL;
5743 else if (btc->cx.wl.status.val & btc_scanning_map.val)
5744 policy_type = BTC_CXP_OFFE_2GBWMIXB;
5745 else if (btc->cx.bt.link_info.status.map.connect == 0)
5746 policy_type = BTC_CXP_OFFE_2GISOB;
5747 else
5748 policy_type = BTC_CXP_OFFE_2GBWISOB;
5749 } else { /* dedicated-antenna */
5750 policy_type = BTC_CXP_OFF_EQ0;
5751 }
5752
5753 btc->dm.e2g_slot_limit = BTC_E2G_LIMIT_DEF;
5754
5755 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
5756 _set_policy(rtwdev, policy_type, BTC_ACT_WL_25G_MCC);
5757 }
5758
_action_wl_scan(struct rtw89_dev * rtwdev)5759 static void _action_wl_scan(struct rtw89_dev *rtwdev)
5760 {
5761 struct rtw89_btc *btc = &rtwdev->btc;
5762 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5763 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5764
5765 if (btc->cx.state_map != BTC_WLINKING &&
5766 RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
5767 _action_wl_25g_mcc(rtwdev);
5768 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n");
5769 } else if (rtwdev->dbcc_en) {
5770 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G &&
5771 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
5772 _action_wl_5g(rtwdev);
5773 else
5774 _action_by_bt(rtwdev);
5775 } else {
5776 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G)
5777 _action_wl_5g(rtwdev);
5778 else
5779 _action_by_bt(rtwdev);
5780 }
5781 }
5782
_action_wl_2g_mcc(struct rtw89_dev * rtwdev)5783 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev)
5784 { struct rtw89_btc *btc = &rtwdev->btc;
5785
5786 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5787
5788 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5789 if (btc->cx.bt.link_info.profile_cnt.now == 0)
5790 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
5791 BTC_ACT_WL_2G_MCC);
5792 else
5793 _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
5794 BTC_ACT_WL_2G_MCC);
5795 } else { /* dedicated-antenna */
5796 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC);
5797 }
5798 }
5799
_action_wl_2g_scc(struct rtw89_dev * rtwdev)5800 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev)
5801 {
5802 struct rtw89_btc *btc = &rtwdev->btc;
5803
5804 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5805
5806 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5807 if (btc->cx.bt.link_info.profile_cnt.now == 0)
5808 _set_policy(rtwdev,
5809 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC);
5810 else
5811 _set_policy(rtwdev,
5812 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC);
5813 } else { /* dedicated-antenna */
5814 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC);
5815 }
5816 }
5817
_action_wl_2g_scc_v1(struct rtw89_dev * rtwdev)5818 static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev)
5819 {
5820 struct rtw89_btc *btc = &rtwdev->btc;
5821 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5822 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5823 struct rtw89_btc_dm *dm = &btc->dm;
5824 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
5825 u16 policy_type = BTC_CXP_OFF_BT;
5826 u32 dur;
5827
5828 if (btc->ant_type == BTC_ANT_DEDICATED) {
5829 policy_type = BTC_CXP_OFF_EQ0;
5830 } else {
5831 /* shared-antenna */
5832 switch (wl_rinfo->mrole_type) {
5833 case BTC_WLMROLE_STA_GC:
5834 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5835 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
5836 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5837 _action_by_bt(rtwdev);
5838 return;
5839 case BTC_WLMROLE_STA_STA:
5840 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5841 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
5842 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5843 _action_by_bt(rtwdev);
5844 return;
5845 case BTC_WLMROLE_STA_GC_NOA:
5846 case BTC_WLMROLE_STA_GO:
5847 case BTC_WLMROLE_STA_GO_NOA:
5848 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5849 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
5850 dur = wl_rinfo->mrole_noa_duration;
5851
5852 if (wl->status.map._4way) {
5853 dm->wl_scc.ebt_null = 0;
5854 policy_type = BTC_CXP_OFFE_WL;
5855 } else if (bt->link_info.status.map.connect == 0) {
5856 dm->wl_scc.ebt_null = 0;
5857 policy_type = BTC_CXP_OFFE_2GISOB;
5858 } else if (bt->link_info.a2dp_desc.exist &&
5859 dur < btc->bt_req_len) {
5860 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5861 policy_type = BTC_CXP_OFFE_2GBWMIXB2;
5862 } else if (bt->link_info.a2dp_desc.exist ||
5863 bt->link_info.pan_desc.exist) {
5864 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5865 policy_type = BTC_CXP_OFFE_2GBWISOB;
5866 } else {
5867 dm->wl_scc.ebt_null = 0;
5868 policy_type = BTC_CXP_OFFE_2GBWISOB;
5869 }
5870 break;
5871 default:
5872 break;
5873 }
5874 }
5875
5876 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5877 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5878 }
5879
_action_wl_2g_scc_v2(struct rtw89_dev * rtwdev)5880 static void _action_wl_2g_scc_v2(struct rtw89_dev *rtwdev)
5881 {
5882 struct rtw89_btc *btc = &rtwdev->btc;
5883 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5884 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5885 struct rtw89_btc_dm *dm = &btc->dm;
5886 struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2;
5887 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
5888 u32 dur, mrole_type, mrole_noa_duration;
5889 u16 policy_type = BTC_CXP_OFF_BT;
5890
5891 if (btc->ver->fwlrole == 2) {
5892 mrole_type = rinfo_v2->mrole_type;
5893 mrole_noa_duration = rinfo_v2->mrole_noa_duration;
5894 } else if (btc->ver->fwlrole == 7) {
5895 mrole_type = rinfo_v7->mrole_type;
5896 mrole_noa_duration = rinfo_v7->mrole_noa_duration;
5897 } else {
5898 return;
5899 }
5900
5901 if (btc->ant_type == BTC_ANT_DEDICATED) {
5902 policy_type = BTC_CXP_OFF_EQ0;
5903 } else {
5904 /* shared-antenna */
5905 switch (mrole_type) {
5906 case BTC_WLMROLE_STA_GC:
5907 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5908 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
5909 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5910 _action_by_bt(rtwdev);
5911 return;
5912 case BTC_WLMROLE_STA_STA:
5913 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5914 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
5915 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5916 _action_by_bt(rtwdev);
5917 return;
5918 case BTC_WLMROLE_STA_GC_NOA:
5919 case BTC_WLMROLE_STA_GO:
5920 case BTC_WLMROLE_STA_GO_NOA:
5921 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5922 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
5923 dur = mrole_noa_duration;
5924
5925 if (wl->status.map._4way) {
5926 dm->wl_scc.ebt_null = 0;
5927 policy_type = BTC_CXP_OFFE_WL;
5928 } else if (bt->link_info.status.map.connect == 0) {
5929 dm->wl_scc.ebt_null = 0;
5930 policy_type = BTC_CXP_OFFE_2GISOB;
5931 } else if (bt->link_info.a2dp_desc.exist &&
5932 dur < btc->bt_req_len) {
5933 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5934 policy_type = BTC_CXP_OFFE_2GBWMIXB2;
5935 } else if (bt->link_info.a2dp_desc.exist ||
5936 bt->link_info.pan_desc.exist) {
5937 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5938 policy_type = BTC_CXP_OFFE_2GBWISOB;
5939 } else {
5940 dm->wl_scc.ebt_null = 0;
5941 policy_type = BTC_CXP_OFFE_2GBWISOB;
5942 }
5943 break;
5944 default:
5945 break;
5946 }
5947 }
5948
5949 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5950 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5951 }
5952
_action_wl_2g_scc_v8(struct rtw89_dev * rtwdev)5953 static void _action_wl_2g_scc_v8(struct rtw89_dev *rtwdev)
5954 {
5955 struct rtw89_btc *btc = &rtwdev->btc;
5956 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5957 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5958 struct rtw89_btc_dm *dm = &btc->dm;
5959 u16 policy_type = BTC_CXP_OFF_BT;
5960
5961 if (btc->ant_type == BTC_ANT_SHARED) {
5962 if (wl->status.map._4way)
5963 policy_type = BTC_CXP_OFFE_WL;
5964 else if (bt->link_info.status.map.connect == 0)
5965 policy_type = BTC_CXP_OFFE_2GISOB;
5966 else
5967 policy_type = BTC_CXP_OFFE_2GBWISOB;
5968 } else {
5969 policy_type = BTC_CXP_OFF_EQ0;
5970 }
5971
5972 dm->e2g_slot_limit = BTC_E2G_LIMIT_DEF;
5973
5974 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5975 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5976 }
5977
_action_wl_2g_ap(struct rtw89_dev * rtwdev)5978 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
5979 {
5980 struct rtw89_btc *btc = &rtwdev->btc;
5981
5982 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5983
5984 if (btc->ant_type == BTC_ANT_SHARED) {
5985 if (btc->cx.bt.link_info.profile_cnt.now == 0)
5986 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
5987 BTC_ACT_WL_2G_AP);
5988 else
5989 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP);
5990 } else {/* dedicated-antenna */
5991 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP);
5992 }
5993 }
5994
_action_wl_2g_go(struct rtw89_dev * rtwdev)5995 static void _action_wl_2g_go(struct rtw89_dev *rtwdev)
5996 {
5997 struct rtw89_btc *btc = &rtwdev->btc;
5998
5999 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6000
6001 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6002 if (btc->cx.bt.link_info.profile_cnt.now == 0)
6003 _set_policy(rtwdev,
6004 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO);
6005 else
6006 _set_policy(rtwdev,
6007 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO);
6008 } else { /* dedicated-antenna */
6009 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO);
6010 }
6011 }
6012
_action_wl_2g_gc(struct rtw89_dev * rtwdev)6013 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev)
6014 {
6015 struct rtw89_btc *btc = &rtwdev->btc;
6016
6017 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6018
6019 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6020 _action_by_bt(rtwdev);
6021 } else {/* dedicated-antenna */
6022 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC);
6023 }
6024 }
6025
_action_wl_2g_nan(struct rtw89_dev * rtwdev)6026 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev)
6027 {
6028 struct rtw89_btc *btc = &rtwdev->btc;
6029
6030 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6031
6032 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6033 if (btc->cx.bt.link_info.profile_cnt.now == 0)
6034 _set_policy(rtwdev,
6035 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN);
6036 else
6037 _set_policy(rtwdev,
6038 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN);
6039 } else { /* dedicated-antenna */
6040 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN);
6041 }
6042 }
6043
_read_scbd(struct rtw89_dev * rtwdev)6044 static u32 _read_scbd(struct rtw89_dev *rtwdev)
6045 {
6046 const struct rtw89_chip_info *chip = rtwdev->chip;
6047 struct rtw89_btc *btc = &rtwdev->btc;
6048 u32 scbd_val = 0;
6049
6050 if (!chip->scbd)
6051 return 0;
6052
6053 scbd_val = rtw89_mac_get_sb(rtwdev);
6054 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n",
6055 scbd_val);
6056
6057 btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++;
6058 return scbd_val;
6059 }
6060
_write_scbd(struct rtw89_dev * rtwdev,u32 val,bool state)6061 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state)
6062 {
6063 const struct rtw89_chip_info *chip = rtwdev->chip;
6064 struct rtw89_btc *btc = &rtwdev->btc;
6065 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6066 u32 scbd_val = 0;
6067 u8 force_exec = false;
6068
6069 if (!chip->scbd)
6070 return;
6071
6072 scbd_val = state ? wl->scbd | val : wl->scbd & ~val;
6073
6074 if (val & BTC_WSCB_ACTIVE || val & BTC_WSCB_ON)
6075 force_exec = true;
6076
6077 if (scbd_val != wl->scbd || force_exec) {
6078 wl->scbd = scbd_val;
6079 wl->scbd_change = true;
6080 }
6081 }
6082
6083 static u8
_update_rssi_state(struct rtw89_dev * rtwdev,u8 pre_state,u8 rssi,u8 thresh)6084 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh)
6085 {
6086 const struct rtw89_chip_info *chip = rtwdev->chip;
6087 u8 next_state, tol = chip->rssi_tol;
6088
6089 if (pre_state == BTC_RSSI_ST_LOW ||
6090 pre_state == BTC_RSSI_ST_STAY_LOW) {
6091 if (rssi >= (thresh + tol))
6092 next_state = BTC_RSSI_ST_HIGH;
6093 else
6094 next_state = BTC_RSSI_ST_STAY_LOW;
6095 } else {
6096 if (rssi < thresh)
6097 next_state = BTC_RSSI_ST_LOW;
6098 else
6099 next_state = BTC_RSSI_ST_STAY_HIGH;
6100 }
6101
6102 return next_state;
6103 }
6104
6105 static
_update_dbcc_band(struct rtw89_dev * rtwdev,enum rtw89_phy_idx phy_idx)6106 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
6107 {
6108 struct rtw89_btc *btc = &rtwdev->btc;
6109
6110 btc->cx.wl.dbcc_info.real_band[phy_idx] =
6111 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ?
6112 btc->cx.wl.dbcc_info.scan_band[phy_idx] :
6113 btc->cx.wl.dbcc_info.op_band[phy_idx];
6114 }
6115
_update_wl_info(struct rtw89_dev * rtwdev)6116 static void _update_wl_info(struct rtw89_dev *rtwdev)
6117 {
6118 struct rtw89_btc *btc = &rtwdev->btc;
6119 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6120 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6121 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
6122 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6123 u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
6124 u8 cnt_2g = 0, cnt_5g = 0, phy;
6125 u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0};
6126 bool b2g = false, b5g = false, client_joined = false;
6127
6128 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6129
6130 for (i = 0; i < RTW89_PORT_NUM; i++) {
6131 /* check if role active? */
6132 if (!wl_linfo[i].active)
6133 continue;
6134
6135 cnt_active++;
6136 wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role;
6137 wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid;
6138 wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy;
6139 wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band;
6140 wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
6141 wl_rinfo->active_role[cnt_active - 1].connected = 0;
6142
6143 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
6144
6145 phy = wl_linfo[i].phy;
6146
6147 /* check dbcc role */
6148 if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) {
6149 wl_dinfo->role[phy] = wl_linfo[i].role;
6150 wl_dinfo->op_band[phy] = wl_linfo[i].band;
6151 _update_dbcc_band(rtwdev, phy);
6152 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6153 }
6154
6155 if (wl_linfo[i].connected == MLME_NO_LINK) {
6156 continue;
6157 } else if (wl_linfo[i].connected == MLME_LINKING) {
6158 cnt_connecting++;
6159 } else {
6160 cnt_connect++;
6161 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6162 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6163 wl_linfo[i].client_cnt > 1)
6164 client_joined = true;
6165 }
6166
6167 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
6168 wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch;
6169 wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw;
6170 wl_rinfo->active_role[cnt_active - 1].connected = 1;
6171
6172 /* only care 2 roles + BT coex */
6173 if (wl_linfo[i].band != RTW89_BAND_2G) {
6174 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
6175 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
6176 cnt_5g++;
6177 b5g = true;
6178 } else {
6179 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
6180 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
6181 cnt_2g++;
6182 b2g = true;
6183 }
6184 }
6185
6186 wl_rinfo->connect_cnt = cnt_connect;
6187
6188 /* Be careful to change the following sequence!! */
6189 if (cnt_connect == 0) {
6190 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6191 wl_rinfo->role_map.role.none = 1;
6192 } else if (!b2g && b5g) {
6193 wl_rinfo->link_mode = BTC_WLINK_5G;
6194 } else if (wl_rinfo->role_map.role.nan) {
6195 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
6196 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
6197 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6198 } else if (b2g && b5g && cnt_connect == 2) {
6199 if (rtwdev->dbcc_en) {
6200 switch (wl_dinfo->role[RTW89_PHY_0]) {
6201 case RTW89_WIFI_ROLE_STATION:
6202 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6203 break;
6204 case RTW89_WIFI_ROLE_P2P_GO:
6205 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6206 break;
6207 case RTW89_WIFI_ROLE_P2P_CLIENT:
6208 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6209 break;
6210 case RTW89_WIFI_ROLE_AP:
6211 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6212 break;
6213 default:
6214 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6215 break;
6216 }
6217 } else {
6218 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
6219 }
6220 } else if (!b5g && cnt_connect == 2) {
6221 if (wl_rinfo->role_map.role.station &&
6222 (wl_rinfo->role_map.role.p2p_go ||
6223 wl_rinfo->role_map.role.p2p_gc ||
6224 wl_rinfo->role_map.role.ap)) {
6225 if (wl_2g_ch[0] == wl_2g_ch[1])
6226 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
6227 else
6228 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6229 } else {
6230 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6231 }
6232 } else if (!b5g && cnt_connect == 1) {
6233 if (wl_rinfo->role_map.role.station)
6234 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6235 else if (wl_rinfo->role_map.role.ap)
6236 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6237 else if (wl_rinfo->role_map.role.p2p_go)
6238 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6239 else if (wl_rinfo->role_map.role.p2p_gc)
6240 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6241 else
6242 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6243 }
6244
6245 /* if no client_joined, don't care P2P-GO/AP role */
6246 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6247 if (!client_joined) {
6248 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6249 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6250 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6251 wl_rinfo->connect_cnt = 1;
6252 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6253 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6254 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6255 wl_rinfo->connect_cnt = 0;
6256 }
6257 }
6258 }
6259
6260 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6261 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6262 cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6263
6264 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6265 }
6266
_update_wl_info_v1(struct rtw89_dev * rtwdev)6267 static void _update_wl_info_v1(struct rtw89_dev *rtwdev)
6268 {
6269 struct rtw89_btc *btc = &rtwdev->btc;
6270 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6271 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6272 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
6273 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6274 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
6275 u8 cnt_2g = 0, cnt_5g = 0, phy;
6276 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
6277 bool b2g = false, b5g = false, client_joined = false;
6278 u8 i;
6279
6280 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6281
6282 for (i = 0; i < RTW89_PORT_NUM; i++) {
6283 if (!wl_linfo[i].active)
6284 continue;
6285
6286 cnt_active++;
6287 wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role;
6288 wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid;
6289 wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy;
6290 wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band;
6291 wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
6292 wl_rinfo->active_role_v1[cnt_active - 1].connected = 0;
6293
6294 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
6295
6296 phy = wl_linfo[i].phy;
6297
6298 if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) {
6299 wl_dinfo->role[phy] = wl_linfo[i].role;
6300 wl_dinfo->op_band[phy] = wl_linfo[i].band;
6301 _update_dbcc_band(rtwdev, phy);
6302 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6303 }
6304
6305 if (wl_linfo[i].connected == MLME_NO_LINK) {
6306 continue;
6307 } else if (wl_linfo[i].connected == MLME_LINKING) {
6308 cnt_connecting++;
6309 } else {
6310 cnt_connect++;
6311 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6312 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6313 wl_linfo[i].client_cnt > 1)
6314 client_joined = true;
6315 }
6316
6317 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
6318 wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch;
6319 wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw;
6320 wl_rinfo->active_role_v1[cnt_active - 1].connected = 1;
6321
6322 /* only care 2 roles + BT coex */
6323 if (wl_linfo[i].band != RTW89_BAND_2G) {
6324 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
6325 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
6326 cnt_5g++;
6327 b5g = true;
6328 } else {
6329 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
6330 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
6331 cnt_2g++;
6332 b2g = true;
6333 }
6334 }
6335
6336 wl_rinfo->connect_cnt = cnt_connect;
6337
6338 /* Be careful to change the following sequence!! */
6339 if (cnt_connect == 0) {
6340 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6341 wl_rinfo->role_map.role.none = 1;
6342 } else if (!b2g && b5g) {
6343 wl_rinfo->link_mode = BTC_WLINK_5G;
6344 } else if (wl_rinfo->role_map.role.nan) {
6345 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
6346 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
6347 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6348 } else if (b2g && b5g && cnt_connect == 2) {
6349 if (rtwdev->dbcc_en) {
6350 switch (wl_dinfo->role[RTW89_PHY_0]) {
6351 case RTW89_WIFI_ROLE_STATION:
6352 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6353 break;
6354 case RTW89_WIFI_ROLE_P2P_GO:
6355 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6356 break;
6357 case RTW89_WIFI_ROLE_P2P_CLIENT:
6358 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6359 break;
6360 case RTW89_WIFI_ROLE_AP:
6361 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6362 break;
6363 default:
6364 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6365 break;
6366 }
6367 } else {
6368 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
6369 }
6370 } else if (!b5g && cnt_connect == 2) {
6371 if (wl_rinfo->role_map.role.station &&
6372 (wl_rinfo->role_map.role.p2p_go ||
6373 wl_rinfo->role_map.role.p2p_gc ||
6374 wl_rinfo->role_map.role.ap)) {
6375 if (wl_2g_ch[0] == wl_2g_ch[1])
6376 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
6377 else
6378 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6379 } else {
6380 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6381 }
6382 } else if (!b5g && cnt_connect == 1) {
6383 if (wl_rinfo->role_map.role.station)
6384 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6385 else if (wl_rinfo->role_map.role.ap)
6386 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6387 else if (wl_rinfo->role_map.role.p2p_go)
6388 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6389 else if (wl_rinfo->role_map.role.p2p_gc)
6390 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6391 else
6392 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6393 }
6394
6395 /* if no client_joined, don't care P2P-GO/AP role */
6396 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6397 if (!client_joined) {
6398 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6399 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6400 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6401 wl_rinfo->connect_cnt = 1;
6402 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6403 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6404 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6405 wl_rinfo->connect_cnt = 0;
6406 }
6407 }
6408 }
6409
6410 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6411 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6412 cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6413
6414 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6415 }
6416
_update_wl_info_v2(struct rtw89_dev * rtwdev)6417 static void _update_wl_info_v2(struct rtw89_dev *rtwdev)
6418 {
6419 struct rtw89_btc *btc = &rtwdev->btc;
6420 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6421 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6422 struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2;
6423 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6424 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
6425 u8 cnt_2g = 0, cnt_5g = 0, phy;
6426 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
6427 bool b2g = false, b5g = false, client_joined = false;
6428 u8 i;
6429
6430 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6431
6432 for (i = 0; i < RTW89_PORT_NUM; i++) {
6433 if (!wl_linfo[i].active)
6434 continue;
6435
6436 cnt_active++;
6437 wl_rinfo->active_role_v2[cnt_active - 1].role = wl_linfo[i].role;
6438 wl_rinfo->active_role_v2[cnt_active - 1].pid = wl_linfo[i].pid;
6439 wl_rinfo->active_role_v2[cnt_active - 1].phy = wl_linfo[i].phy;
6440 wl_rinfo->active_role_v2[cnt_active - 1].band = wl_linfo[i].band;
6441 wl_rinfo->active_role_v2[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
6442 wl_rinfo->active_role_v2[cnt_active - 1].connected = 0;
6443
6444 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
6445
6446 phy = wl_linfo[i].phy;
6447
6448 if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) {
6449 wl_dinfo->role[phy] = wl_linfo[i].role;
6450 wl_dinfo->op_band[phy] = wl_linfo[i].band;
6451 _update_dbcc_band(rtwdev, phy);
6452 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6453 }
6454
6455 if (wl_linfo[i].connected == MLME_NO_LINK) {
6456 continue;
6457 } else if (wl_linfo[i].connected == MLME_LINKING) {
6458 cnt_connecting++;
6459 } else {
6460 cnt_connect++;
6461 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6462 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6463 wl_linfo[i].client_cnt > 1)
6464 client_joined = true;
6465 }
6466
6467 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
6468 wl_rinfo->active_role_v2[cnt_active - 1].ch = wl_linfo[i].ch;
6469 wl_rinfo->active_role_v2[cnt_active - 1].bw = wl_linfo[i].bw;
6470 wl_rinfo->active_role_v2[cnt_active - 1].connected = 1;
6471
6472 /* only care 2 roles + BT coex */
6473 if (wl_linfo[i].band != RTW89_BAND_2G) {
6474 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
6475 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
6476 cnt_5g++;
6477 b5g = true;
6478 } else {
6479 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
6480 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
6481 cnt_2g++;
6482 b2g = true;
6483 }
6484 }
6485
6486 wl_rinfo->connect_cnt = cnt_connect;
6487
6488 /* Be careful to change the following sequence!! */
6489 if (cnt_connect == 0) {
6490 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6491 wl_rinfo->role_map.role.none = 1;
6492 } else if (!b2g && b5g) {
6493 wl_rinfo->link_mode = BTC_WLINK_5G;
6494 } else if (wl_rinfo->role_map.role.nan) {
6495 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
6496 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
6497 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6498 } else if (b2g && b5g && cnt_connect == 2) {
6499 if (rtwdev->dbcc_en) {
6500 switch (wl_dinfo->role[RTW89_PHY_0]) {
6501 case RTW89_WIFI_ROLE_STATION:
6502 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6503 break;
6504 case RTW89_WIFI_ROLE_P2P_GO:
6505 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6506 break;
6507 case RTW89_WIFI_ROLE_P2P_CLIENT:
6508 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6509 break;
6510 case RTW89_WIFI_ROLE_AP:
6511 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6512 break;
6513 default:
6514 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6515 break;
6516 }
6517 } else {
6518 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
6519 }
6520 } else if (!b5g && cnt_connect == 2) {
6521 if (wl_rinfo->role_map.role.station &&
6522 (wl_rinfo->role_map.role.p2p_go ||
6523 wl_rinfo->role_map.role.p2p_gc ||
6524 wl_rinfo->role_map.role.ap)) {
6525 if (wl_2g_ch[0] == wl_2g_ch[1])
6526 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
6527 else
6528 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6529 } else {
6530 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6531 }
6532 } else if (!b5g && cnt_connect == 1) {
6533 if (wl_rinfo->role_map.role.station)
6534 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6535 else if (wl_rinfo->role_map.role.ap)
6536 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6537 else if (wl_rinfo->role_map.role.p2p_go)
6538 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6539 else if (wl_rinfo->role_map.role.p2p_gc)
6540 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6541 else
6542 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6543 }
6544
6545 /* if no client_joined, don't care P2P-GO/AP role */
6546 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6547 if (!client_joined) {
6548 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6549 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6550 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6551 wl_rinfo->connect_cnt = 1;
6552 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6553 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6554 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6555 wl_rinfo->connect_cnt = 0;
6556 }
6557 }
6558 }
6559
6560 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6561 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6562 cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6563
6564 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6565 }
6566
6567 #define BTC_CHK_HANG_MAX 3
6568 #define BTC_SCB_INV_VALUE GENMASK(31, 0)
6569
_get_role_link_mode(u8 role)6570 static u8 _get_role_link_mode(u8 role)
6571 {
6572 switch (role) {
6573 case RTW89_WIFI_ROLE_STATION:
6574 return BTC_WLINK_2G_STA;
6575 case RTW89_WIFI_ROLE_P2P_GO:
6576 return BTC_WLINK_2G_GO;
6577 case RTW89_WIFI_ROLE_P2P_CLIENT:
6578 return BTC_WLINK_2G_GC;
6579 case RTW89_WIFI_ROLE_AP:
6580 return BTC_WLINK_2G_AP;
6581 default:
6582 return BTC_WLINK_OTHER;
6583 }
6584 }
6585
_chk_role_ch_group(const struct rtw89_btc_chdef * r1,const struct rtw89_btc_chdef * r2)6586 static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1,
6587 const struct rtw89_btc_chdef *r2)
6588 {
6589 if (r1->chan != r2->chan) { /* primary ch is different */
6590 return false;
6591 } else if (r1->bw == RTW89_CHANNEL_WIDTH_40 &&
6592 r2->bw == RTW89_CHANNEL_WIDTH_40) {
6593 if (r1->offset != r2->offset)
6594 return false;
6595 }
6596 return true;
6597 }
6598
_chk_dbcc(struct rtw89_dev * rtwdev,struct rtw89_btc_chdef * ch,u8 * phy,u8 * role,u8 link_cnt)6599 static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch,
6600 u8 *phy, u8 *role, u8 link_cnt)
6601 {
6602 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6603 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
6604 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8;
6605 bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false;
6606 u8 j, k, dbcc_2g_cid, dbcc_2g_cid2, dbcc_2g_phy, pta_req_band;
6607
6608 /* find out the 2G-PHY by connect-id ->ch */
6609 for (j = 0; j < link_cnt; j++) {
6610 if (ch[j].center_ch <= 14) {
6611 is_2g_ch_exist = true;
6612 break;
6613 }
6614 }
6615
6616 /* If no any 2G-port exist, it's impossible because 5G-exclude */
6617 if (!is_2g_ch_exist)
6618 return BTC_WLINK_5G;
6619
6620 dbcc_2g_cid = j;
6621 dbcc_2g_phy = phy[dbcc_2g_cid];
6622
6623 if (dbcc_2g_phy == RTW89_PHY_1)
6624 pta_req_band = RTW89_PHY_1;
6625 else
6626 pta_req_band = RTW89_PHY_0;
6627
6628 if (rtwdev->btc.ver->fwlrole == 7) {
6629 rinfo_v7->dbcc_2g_phy = dbcc_2g_phy;
6630 } else if (rtwdev->btc.ver->fwlrole == 8) {
6631 rinfo_v8->dbcc_2g_phy = dbcc_2g_phy;
6632 rinfo_v8->pta_req_band = pta_req_band;
6633 }
6634
6635 /* connect_cnt <= 2 */
6636 if (link_cnt < BTC_TDMA_WLROLE_MAX)
6637 return (_get_role_link_mode((role[dbcc_2g_cid])));
6638
6639 /* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */
6640 for (k = 0; k < link_cnt; k++) {
6641 if (k == dbcc_2g_cid)
6642 continue;
6643
6644 if (phy[k] == dbcc_2g_phy) {
6645 is_multi_role_in_2g_phy = true;
6646 dbcc_2g_cid2 = k;
6647 break;
6648 }
6649 }
6650
6651 /* Single-role in 2G-PHY */
6652 if (!is_multi_role_in_2g_phy)
6653 return (_get_role_link_mode(role[dbcc_2g_cid]));
6654
6655 /* 2-role in 2G-PHY */
6656 if (ch[dbcc_2g_cid2].center_ch > 14)
6657 return BTC_WLINK_25G_MCC;
6658 else if (_chk_role_ch_group(&ch[dbcc_2g_cid], &ch[dbcc_2g_cid2]))
6659 return BTC_WLINK_2G_SCC;
6660 else
6661 return BTC_WLINK_2G_MCC;
6662 }
6663
_update_role_link_mode(struct rtw89_dev * rtwdev,bool client_joined,u32 noa)6664 static void _update_role_link_mode(struct rtw89_dev *rtwdev,
6665 bool client_joined, u32 noa)
6666 {
6667 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &rtwdev->btc.cx.wl.role_info_v8;
6668 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &rtwdev->btc.cx.wl.role_info_v7;
6669 u8 role_ver = rtwdev->btc.ver->fwlrole;
6670 u32 type = BTC_WLMROLE_NONE, dur = 0;
6671 u8 link_mode, connect_cnt;
6672 u32 wl_role;
6673
6674 if (role_ver == 7) {
6675 wl_role = rinfo_v7->role_map;
6676 link_mode = rinfo_v7->link_mode;
6677 connect_cnt = rinfo_v7->connect_cnt;
6678 } else if (role_ver == 8) {
6679 wl_role = rinfo_v8->role_map;
6680 link_mode = rinfo_v8->link_mode;
6681 connect_cnt = rinfo_v8->connect_cnt;
6682 } else {
6683 return;
6684 }
6685
6686 /* if no client_joined, don't care P2P-GO/AP role */
6687 if (((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
6688 (wl_role & BIT(RTW89_WIFI_ROLE_AP))) && !client_joined) {
6689 if (link_mode == BTC_WLINK_2G_SCC) {
6690 if (role_ver == 7) {
6691 rinfo_v7->link_mode = BTC_WLINK_2G_STA;
6692 rinfo_v7->connect_cnt--;
6693 } else if (role_ver == 8) {
6694 rinfo_v8->link_mode = BTC_WLINK_2G_STA;
6695 rinfo_v8->connect_cnt--;
6696 }
6697 } else if (link_mode == BTC_WLINK_2G_GO ||
6698 link_mode == BTC_WLINK_2G_AP) {
6699 if (role_ver == 7) {
6700 rinfo_v7->link_mode = BTC_WLINK_NOLINK;
6701 rinfo_v7->connect_cnt--;
6702 } else if (role_ver == 8) {
6703 rinfo_v8->link_mode = BTC_WLINK_NOLINK;
6704 rinfo_v8->connect_cnt--;
6705 }
6706 }
6707 }
6708
6709 /* Identify 2-Role type */
6710 if (connect_cnt >= 2 &&
6711 (link_mode == BTC_WLINK_2G_SCC ||
6712 link_mode == BTC_WLINK_2G_MCC ||
6713 link_mode == BTC_WLINK_25G_MCC ||
6714 link_mode == BTC_WLINK_5G)) {
6715 if ((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
6716 (wl_role & BIT(RTW89_WIFI_ROLE_AP)))
6717 type = noa ? BTC_WLMROLE_STA_GO_NOA : BTC_WLMROLE_STA_GO;
6718 else if (wl_role & BIT(RTW89_WIFI_ROLE_P2P_CLIENT))
6719 type = noa ? BTC_WLMROLE_STA_GC_NOA : BTC_WLMROLE_STA_GC;
6720 else
6721 type = BTC_WLMROLE_STA_STA;
6722
6723 dur = noa;
6724 }
6725
6726 if (role_ver == 7) {
6727 rinfo_v7->mrole_type = type;
6728 rinfo_v7->mrole_noa_duration = dur;
6729 } else if (role_ver == 8) {
6730 rinfo_v8->mrole_type = type;
6731 rinfo_v8->mrole_noa_duration = dur;
6732 }
6733 }
6734
_update_wl_info_v7(struct rtw89_dev * rtwdev,u8 rid)6735 static void _update_wl_info_v7(struct rtw89_dev *rtwdev, u8 rid)
6736 {
6737 struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER];
6738 struct rtw89_btc *btc = &rtwdev->btc;
6739 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6740 struct rtw89_btc_wl_role_info_v7 *wl_rinfo = &wl->role_info_v7;
6741 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6742 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6743 struct rtw89_btc_wl_active_role_v7 *act_role = NULL;
6744 u8 i, mode, cnt = 0, cnt_2g = 0, cnt_5g = 0, phy_now = RTW89_PHY_NUM, phy_dbcc;
6745 bool b2g = false, b5g = false, client_joined = false, client_inc_2g = false;
6746 u8 client_cnt_last[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6747 u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6748 u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6749 u8 mac = RTW89_MAC_0, dbcc_2g_phy = RTW89_PHY_0;
6750 u32 noa_duration = 0;
6751
6752 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6753
6754 for (i = 0; i < RTW89_PORT_NUM; i++) {
6755 if (!wl_linfo[i].active || wl_linfo[i].phy >= RTW89_PHY_NUM)
6756 continue;
6757
6758 act_role = &wl_rinfo->active_role[i];
6759 act_role->role = wl_linfo[i].role;
6760
6761 /* check if role connect? */
6762 if (wl_linfo[i].connected == MLME_NO_LINK) {
6763 act_role->connected = 0;
6764 continue;
6765 } else if (wl_linfo[i].connected == MLME_LINKING) {
6766 continue;
6767 }
6768
6769 cnt++;
6770 act_role->connected = 1;
6771 act_role->pid = wl_linfo[i].pid;
6772 act_role->phy = wl_linfo[i].phy;
6773 act_role->band = wl_linfo[i].band;
6774 act_role->ch = wl_linfo[i].ch;
6775 act_role->bw = wl_linfo[i].bw;
6776 act_role->noa = wl_linfo[i].noa;
6777 act_role->noa_dur = wl_linfo[i].noa_duration;
6778 cid_ch[cnt - 1] = wl_linfo[i].chdef;
6779 cid_phy[cnt - 1] = wl_linfo[i].phy;
6780 cid_role[cnt - 1] = wl_linfo[i].role;
6781 wl_rinfo->role_map |= BIT(wl_linfo[i].role);
6782
6783 if (rid == i)
6784 phy_now = act_role->phy;
6785
6786 if (wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6787 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) {
6788 if (wl_linfo[i].client_cnt > 1)
6789 client_joined = true;
6790 if (client_cnt_last[i] < wl_linfo[i].client_cnt &&
6791 wl_linfo[i].chdef.band == RTW89_BAND_2G)
6792 client_inc_2g = true;
6793 act_role->client_cnt = wl_linfo[i].client_cnt;
6794 } else {
6795 act_role->client_cnt = 0;
6796 }
6797
6798 if (act_role->noa && act_role->noa_dur > 0)
6799 noa_duration = act_role->noa_dur;
6800
6801 if (rtwdev->dbcc_en) {
6802 phy_dbcc = wl_linfo[i].phy;
6803 wl_dinfo->role[phy_dbcc] |= BIT(wl_linfo[i].role);
6804 wl_dinfo->op_band[phy_dbcc] = wl_linfo[i].chdef.band;
6805 }
6806
6807 if (wl_linfo[i].chdef.band != RTW89_BAND_2G) {
6808 cnt_5g++;
6809 b5g = true;
6810 } else {
6811 if (((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6812 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6813 client_joined) ||
6814 wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_CLIENT)
6815 wl_rinfo->p2p_2g = 1;
6816
6817 if ((wl_linfo[i].mode & BIT(BTC_WL_MODE_11B)) ||
6818 (wl_linfo[i].mode & BIT(BTC_WL_MODE_11G)))
6819 wl->bg_mode = 1;
6820 else if (wl_linfo[i].mode & BIT(BTC_WL_MODE_HE))
6821 wl->he_mode = true;
6822
6823 cnt_2g++;
6824 b2g = true;
6825 }
6826
6827 if (act_role->band == RTW89_BAND_5G && act_role->ch >= 100)
6828 wl->is_5g_hi_channel = 1;
6829 else
6830 wl->is_5g_hi_channel = 0;
6831 }
6832
6833 wl_rinfo->connect_cnt = cnt;
6834 wl->client_cnt_inc_2g = client_inc_2g;
6835
6836 if (cnt == 0) {
6837 mode = BTC_WLINK_NOLINK;
6838 wl_rinfo->role_map = BIT(RTW89_WIFI_ROLE_NONE);
6839 } else if (!b2g && b5g) {
6840 mode = BTC_WLINK_5G;
6841 } else if (wl_rinfo->role_map & BIT(RTW89_WIFI_ROLE_NAN)) {
6842 mode = BTC_WLINK_2G_NAN;
6843 } else if (cnt > BTC_TDMA_WLROLE_MAX) {
6844 mode = BTC_WLINK_OTHER;
6845 } else if (rtwdev->dbcc_en) {
6846 mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt);
6847
6848 /* correct 2G-located PHY band for gnt ctrl */
6849 if (dbcc_2g_phy < RTW89_PHY_NUM)
6850 wl_dinfo->op_band[dbcc_2g_phy] = RTW89_BAND_2G;
6851 } else if (b2g && b5g && cnt == 2) {
6852 mode = BTC_WLINK_25G_MCC;
6853 } else if (!b5g && cnt == 2) { /* cnt_connect = 2 */
6854 if (_chk_role_ch_group(&cid_ch[0], &cid_ch[cnt - 1]))
6855 mode = BTC_WLINK_2G_SCC;
6856 else
6857 mode = BTC_WLINK_2G_MCC;
6858 } else if (!b5g && cnt == 1) { /* cnt_connect = 1 */
6859 mode = _get_role_link_mode(cid_role[0]);
6860 } else {
6861 mode = BTC_WLINK_NOLINK;
6862 }
6863
6864 wl_rinfo->link_mode = mode;
6865 _update_role_link_mode(rtwdev, client_joined, noa_duration);
6866
6867 /* todo DBCC related event */
6868 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] wl_info phy_now=%d\n", phy_now);
6869 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6870 "[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g);
6871
6872 if (wl_rinfo->dbcc_en != rtwdev->dbcc_en) {
6873 wl_rinfo->dbcc_chg = 1;
6874 wl_rinfo->dbcc_en = rtwdev->dbcc_en;
6875 btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++;
6876 }
6877
6878 if (rtwdev->dbcc_en) {
6879 wl_rinfo->dbcc_2g_phy = dbcc_2g_phy;
6880
6881 if (dbcc_2g_phy == RTW89_PHY_1)
6882 mac = RTW89_MAC_1;
6883
6884 _update_dbcc_band(rtwdev, RTW89_PHY_0);
6885 _update_dbcc_band(rtwdev, RTW89_PHY_1);
6886 }
6887 _wl_req_mac(rtwdev, mac);
6888 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6889 }
6890
_update_wl_link_mode(struct rtw89_dev * rtwdev,u8 hw_band,u8 type)6891 static u8 _update_wl_link_mode(struct rtw89_dev *rtwdev, u8 hw_band, u8 type)
6892 {
6893 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6894 struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info;
6895 u8 mode = BTC_WLINK_NOLINK;
6896
6897 switch (type) {
6898 case RTW89_MR_WTYPE_NONE: /* no-link */
6899 mode = BTC_WLINK_NOLINK;
6900 break;
6901 case RTW89_MR_WTYPE_NONMLD: /* Non_MLO 1-role 2+0/0+2 */
6902 case RTW89_MR_WTYPE_MLD1L1R: /* MLO only-1 link 2+0/0+2 */
6903 if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) {
6904 mode = BTC_WLINK_5G;
6905 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) {
6906 mode = BTC_WLINK_2G_GO;
6907 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT) {
6908 if (wl->role_info_v8.p2p_2g)
6909 mode = BTC_WLINK_2G_GC;
6910 else
6911 mode = BTC_WLINK_2G_STA;
6912 }
6913 break;
6914 case RTW89_MR_WTYPE_NONMLD_NONMLD: /* Non_MLO 2-role 2+0/0+2 */
6915 case RTW89_MR_WTYPE_MLD1L1R_NONMLD: /* MLO only-1 link + P2P 2+0/0+2 */
6916 if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) {
6917 mode = BTC_WLINK_5G;
6918 } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_5GHZ ||
6919 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_6GHZ) {
6920 mode = BTC_WLINK_25G_MCC;
6921 } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ) {
6922 mode = BTC_WLINK_2G_MCC;
6923 } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_2GHZ) {
6924 mode = BTC_WLINK_2G_SCC;
6925 }
6926 break;
6927 case RTW89_MR_WTYPE_MLD2L1R: /* MLO_MLSR 2+0/0+2 */
6928 if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G)
6929 mode = BTC_WLINK_5G;
6930 else if (wl->role_info_v8.p2p_2g)
6931 mode = BTC_WLINK_2G_GC;
6932 else
6933 mode = BTC_WLINK_2G_STA;
6934 break;
6935 case RTW89_MR_WTYPE_MLD2L1R_NONMLD: /* MLO_MLSR + P2P 2+0/0+2 */
6936 case RTW89_MR_WTYPE_MLD2L2R_NONMLD: /* MLO_MLMR + P2P 1+1/2+2 */
6937 /* driver may doze 1-link to
6938 * 2G+5G -> TDMA slot switch by E2G/E5G
6939 * 5G only -> TDMA slot switch by E5G
6940 */
6941 mode = BTC_WLINK_25G_MCC;
6942 break;
6943 case RTW89_MR_WTYPE_MLD2L2R: /* MLO_MLMR 1+1/2+2 */
6944 if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) {
6945 mode = BTC_WLINK_5G;
6946 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) {
6947 mode = BTC_WLINK_2G_GO;
6948 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT) {
6949 if (wl->role_info_v8.p2p_2g)
6950 mode = BTC_WLINK_2G_GC;
6951 else
6952 mode = BTC_WLINK_2G_STA;
6953 }
6954 break;
6955 }
6956 return mode;
6957 }
6958
_update_wl_mlo_info(struct rtw89_dev * rtwdev)6959 static void _update_wl_mlo_info(struct rtw89_dev *rtwdev)
6960 {
6961 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6962 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
6963 struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info;
6964 struct rtw89_mr_chanctx_info qinfo;
6965 u8 track_band = RTW89_PHY_0;
6966 u8 rf_band = RTW89_BAND_2G;
6967 u8 i, type;
6968
6969 /* parse MLO info form PHL API for each HW-band */
6970 for (i = RTW89_MAC_0; i <= RTW89_MAC_1; i++) {
6971 memset(&qinfo, 0, sizeof(qinfo));
6972
6973 rtw89_query_mr_chanctx_info(rtwdev, i, &qinfo);
6974 mlo_info->wmode[i] = qinfo.wmode;
6975 mlo_info->ch_type[i] = qinfo.ctxtype;
6976 mlo_info->wtype = qinfo.wtype;
6977
6978 if (mlo_info->ch_type[i] == RTW89_MR_CTX1_5GHZ ||
6979 mlo_info->ch_type[i] == RTW89_MR_CTX2_5GHZ ||
6980 mlo_info->ch_type[i] == RTW89_MR_CTX2_5GHZ_6GHZ)
6981 mlo_info->hwb_rf_band[i] = RTW89_BAND_5G;
6982 else if (mlo_info->ch_type[i] == RTW89_MR_CTX1_6GHZ ||
6983 mlo_info->ch_type[i] == RTW89_MR_CTX2_6GHZ)
6984 mlo_info->hwb_rf_band[i] = RTW89_BAND_6G;
6985 else /* check if "2G-included" or unknown in each HW-band */
6986 mlo_info->hwb_rf_band[i] = RTW89_BAND_2G;
6987 }
6988
6989 mlo_info->link_status = rtwdev->mlo_dbcc_mode;
6990 type = mlo_info->wtype;
6991
6992 if (mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R ||
6993 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R ||
6994 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R ||
6995 mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R_NONMLD ||
6996 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD ||
6997 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R_NONMLD)
6998 mlo_info->mlo_en = 1;
6999 else
7000 mlo_info->mlo_en = 0;
7001
7002 if (mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_NONE &&
7003 mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_UNKNOWN &&
7004 mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_NONE &&
7005 mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_UNKNOWN)
7006 mlo_info->dual_hw_band_en = 1; /* two HW-hand link exist */
7007 else
7008 mlo_info->dual_hw_band_en = 0;
7009
7010 if (mlo_info->link_status == MLO_2_PLUS_0_2RF ||
7011 mlo_info->link_status == MLO_0_PLUS_2_2RF ||
7012 mlo_info->link_status == MLO_2_PLUS_2_2RF)
7013 mlo_info->mlo_adie = 2;
7014 else
7015 mlo_info->mlo_adie = 1;
7016
7017 switch (mlo_info->link_status) {
7018 default:
7019 case MLO_2_PLUS_0_1RF: /* 2+0 */
7020 case MLO_2_PLUS_0_2RF:
7021 mlo_info->rf_combination = BTC_MLO_RF_2_PLUS_0;
7022 track_band = RTW89_MAC_0;
7023 rf_band = mlo_info->hwb_rf_band[RTW89_MAC_0];
7024 mlo_info->path_rf_band[BTC_RF_S0] = rf_band;
7025 mlo_info->path_rf_band[BTC_RF_S1] = rf_band;
7026
7027 wl_rinfo->pta_req_band = RTW89_MAC_0;
7028 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0;
7029 wl_rinfo->dbcc_en = 0;
7030 break;
7031 case MLO_0_PLUS_2_1RF: /* 0+2 */
7032 case MLO_0_PLUS_2_2RF:
7033 mlo_info->rf_combination = BTC_MLO_RF_0_PLUS_2;
7034 track_band = RTW89_MAC_1;
7035 rf_band = mlo_info->hwb_rf_band[RTW89_MAC_1];
7036 mlo_info->path_rf_band[BTC_RF_S0] = rf_band;
7037 mlo_info->path_rf_band[BTC_RF_S1] = rf_band;
7038
7039 wl_rinfo->pta_req_band = RTW89_MAC_1;
7040 wl_rinfo->dbcc_2g_phy = RTW89_PHY_1;
7041 wl_rinfo->dbcc_en = 0;
7042 break;
7043 case MLO_1_PLUS_1_1RF: /* 1+1 */
7044 case MLO_1_PLUS_1_2RF: /* 1+1 */
7045 case MLO_2_PLUS_2_2RF: /* 2+2 */
7046 case DBCC_LEGACY: /* DBCC 1+1 */
7047 if (mlo_info->link_status == MLO_2_PLUS_2_2RF)
7048 mlo_info->rf_combination = BTC_MLO_RF_2_PLUS_2;
7049 else
7050 mlo_info->rf_combination = BTC_MLO_RF_1_PLUS_1;
7051
7052 if (mlo_info->hwb_rf_band[RTW89_MAC_0] == RTW89_BAND_2G)
7053 track_band = RTW89_MAC_0;
7054 else
7055 track_band = RTW89_MAC_1;
7056
7057 mlo_info->path_rf_band[BTC_RF_S0] =
7058 mlo_info->hwb_rf_band[RTW89_MAC_0];
7059 mlo_info->path_rf_band[BTC_RF_S1] =
7060 mlo_info->hwb_rf_band[RTW89_MAC_1];
7061
7062 /* Check ch count from ch_type @ 2.4G HW-band, and modify type */
7063 if (mlo_info->ch_type[track_band] == RTW89_MR_CTX1_2GHZ)
7064 type = RTW89_MR_WTYPE_NONMLD; /* only 1-role at 2G */
7065 else
7066 type = RTW89_MR_WTYPE_NONMLD_NONMLD;
7067
7068 if (mlo_info->hwb_rf_band[RTW89_MAC_0] == RTW89_BAND_2G) {
7069 wl_rinfo->pta_req_band = RTW89_MAC_0;
7070 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0;
7071 } else {
7072 wl_rinfo->pta_req_band = RTW89_MAC_1;
7073 wl_rinfo->dbcc_2g_phy = RTW89_PHY_1;
7074 }
7075
7076 if (mlo_info->wmode[RTW89_MAC_0] == RTW89_MR_WMODE_NONE &&
7077 mlo_info->wmode[RTW89_MAC_1] == RTW89_MR_WMODE_NONE)
7078 wl_rinfo->dbcc_en = 0;
7079 else
7080 wl_rinfo->dbcc_en = 1;
7081 break;
7082 }
7083
7084 wl_rinfo->link_mode = _update_wl_link_mode(rtwdev, track_band, type);
7085
7086 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(), mode=%s, pta_band=%d",
7087 __func__, id_to_linkmode(wl_rinfo->link_mode),
7088 wl_rinfo->pta_req_band);
7089 }
7090
_update_wl_non_mlo_info(struct rtw89_dev * rtwdev)7091 static void _update_wl_non_mlo_info(struct rtw89_dev *rtwdev)
7092 {
7093 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
7094 struct rtw89_btc_wl_rlink *rlink = NULL;
7095 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
7096 struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7097 u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7098 u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7099 bool b2g = false, b5g = false, outloop = false;
7100 u8 mode = BTC_WLINK_NOLINK;
7101 u8 cnt_2g = 0, cnt_5g = 0;
7102 u8 i, j, cnt = 0;
7103
7104 for (j = RTW89_PHY_0; j < RTW89_PHY_NUM; j++) {
7105 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
7106 rlink = &wl_rinfo->rlink[i][j];
7107
7108 if (!rlink->active || !rlink->connected)
7109 continue;
7110
7111 if (cnt >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER) {
7112 outloop = true;
7113 break;
7114 }
7115
7116 cid_ch[cnt] = wl->rlink_info[i][j].chdef;
7117 cid_phy[cnt] = rlink->phy;
7118 cid_role[cnt] = rlink->role;
7119 cnt++;
7120
7121 if (rlink->rf_band != RTW89_BAND_2G) {
7122 cnt_5g++;
7123 b5g = true;
7124 } else {
7125 cnt_2g++;
7126 b2g = true;
7127 }
7128 }
7129 if (outloop)
7130 break;
7131 }
7132
7133 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7134 "[BTC], %s(): cnt_2g=%d, cnt_5g=%d\n", __func__, cnt_2g, cnt_5g);
7135
7136 wl_rinfo->dbcc_en = rtwdev->dbcc_en;
7137 /* Be careful to change the following sequence!! */
7138 if (cnt == 0) {
7139 mode = BTC_WLINK_NOLINK;
7140 } else if (!b2g && b5g) {
7141 mode = BTC_WLINK_5G;
7142 } else if (wl_rinfo->dbcc_en) {
7143 mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt);
7144 } else if (b2g && b5g) {
7145 mode = BTC_WLINK_25G_MCC;
7146 } else if (!b5g && cnt >= 2) {
7147 if (_chk_role_ch_group(&cid_ch[0], &cid_ch[1]))
7148 mode = BTC_WLINK_2G_SCC;
7149 else
7150 mode = BTC_WLINK_2G_MCC;
7151 } else if (!b5g) { /* cnt_connect = 1 */
7152 mode = _get_role_link_mode(cid_role[0]);
7153 }
7154
7155 wl_rinfo->link_mode = mode;
7156 }
7157
_modify_role_link_mode(struct rtw89_dev * rtwdev)7158 static void _modify_role_link_mode(struct rtw89_dev *rtwdev)
7159 {
7160 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
7161 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
7162 u8 go_cleint_exist = wl->go_client_exist;
7163 u8 link_mode = wl_rinfo->link_mode;
7164 u32 role_map = wl_rinfo->role_map;
7165 u8 noa_exist = wl->noa_exist;
7166 u32 mrole = BTC_WLMROLE_NONE;
7167
7168 /* if no client_joined, don't care P2P-GO/AP role */
7169 if (((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
7170 (role_map & BIT(RTW89_WIFI_ROLE_AP))) && !go_cleint_exist) {
7171 if (link_mode == BTC_WLINK_2G_SCC) {
7172 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
7173 } else if (link_mode == BTC_WLINK_2G_GO ||
7174 link_mode == BTC_WLINK_2G_AP) {
7175 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
7176 }
7177 }
7178
7179 /* Identify 2-Role type */
7180 if (link_mode == BTC_WLINK_2G_SCC ||
7181 link_mode == BTC_WLINK_2G_MCC ||
7182 link_mode == BTC_WLINK_25G_MCC ||
7183 link_mode == BTC_WLINK_5G) {
7184 if ((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
7185 (role_map & BIT(RTW89_WIFI_ROLE_AP))) {
7186 if (noa_exist)
7187 mrole = BTC_WLMROLE_STA_GO_NOA;
7188 else
7189 mrole = BTC_WLMROLE_STA_GO;
7190 } else if (role_map & BIT(RTW89_WIFI_ROLE_P2P_CLIENT)) {
7191 if (noa_exist)
7192 mrole = BTC_WLMROLE_STA_GC_NOA;
7193 else
7194 mrole = BTC_WLMROLE_STA_GC;
7195 } else {
7196 mrole = BTC_WLMROLE_STA_STA;
7197 }
7198 }
7199
7200 wl_rinfo->mrole_type = mrole;
7201
7202 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7203 "[BTC], %s(): link_mode=%s, mrole_type=%d\n", __func__,
7204 id_to_linkmode(wl_rinfo->link_mode), wl_rinfo->mrole_type);
7205 }
7206
_update_wl_info_v8(struct rtw89_dev * rtwdev,u8 role_id,u8 rlink_id,enum btc_role_state state)7207 static void _update_wl_info_v8(struct rtw89_dev *rtwdev, u8 role_id, u8 rlink_id,
7208 enum btc_role_state state)
7209 {
7210 struct rtw89_btc_wl_rlink *rlink = NULL;
7211 struct rtw89_btc_wl_link_info *wl_linfo;
7212 struct rtw89_btc *btc = &rtwdev->btc;
7213 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7214 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
7215 bool client_joined = false, noa_exist = false, p2p_exist = false;
7216 bool is_5g_hi_channel = false, bg_mode = false, dbcc_en_ori;
7217 u8 i, j, link_mode_ori;
7218 u32 role_map = 0;
7219
7220 if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id >= RTW89_MAC_NUM)
7221 return;
7222
7223 /* Extract wl->link_info[role_id][rlink_id] to wl->role_info
7224 * role_id: role index
7225 * rlink_id: rlink index (= HW-band index)
7226 * pid: port_index
7227 */
7228
7229 wl_linfo = &wl->rlink_info[role_id][rlink_id];
7230 rlink = &wl_rinfo->rlink[role_id][rlink_id];
7231
7232 rlink->role = wl_linfo->role;
7233 rlink->active = wl_linfo->active; /* Doze or not */
7234 rlink->pid = wl_linfo->pid;
7235 rlink->phy = wl_linfo->phy;
7236 rlink->rf_band = wl_linfo->band;
7237 rlink->ch = wl_linfo->ch;
7238 rlink->bw = wl_linfo->bw;
7239 rlink->noa = wl_linfo->noa;
7240 rlink->noa_dur = wl_linfo->noa_duration / 1000;
7241 rlink->client_cnt = wl_linfo->client_cnt;
7242 rlink->mode = wl_linfo->mode;
7243
7244 switch (wl_linfo->connected) {
7245 case MLME_NO_LINK:
7246 rlink->connected = 0;
7247 break;
7248 case MLME_LINKED:
7249 rlink->connected = 1;
7250 break;
7251 default:
7252 return;
7253 }
7254
7255 for (j = RTW89_MAC_0; j <= RTW89_MAC_1; j++) {
7256 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
7257 rlink = &wl_rinfo->rlink[i][j];
7258
7259 if (!rlink->active || !rlink->connected)
7260 continue;
7261
7262 role_map |= BIT(rlink->role);
7263
7264 /* only one noa-role exist */
7265 if (rlink->noa && rlink->noa_dur > 0)
7266 noa_exist = true;
7267
7268 /* for WL 5G-Rx interfered with BT issue */
7269 if (rlink->rf_band == RTW89_BAND_5G) {
7270 if (rlink->ch >= 100)
7271 is_5g_hi_channel = true;
7272
7273 continue;
7274 }
7275
7276 /* only if client connect for p2p-Go/AP */
7277 if ((rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
7278 rlink->role == RTW89_WIFI_ROLE_AP) &&
7279 rlink->client_cnt > 1) {
7280 p2p_exist = true;
7281 client_joined = true;
7282 }
7283
7284 /* Identify if P2P-Go (GO/GC/AP) exist at 2G band */
7285 if (rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)
7286 p2p_exist = true;
7287
7288 if ((rlink->mode & BIT(BTC_WL_MODE_11B)) ||
7289 (rlink->mode & BIT(BTC_WL_MODE_11G)))
7290 bg_mode = true;
7291 }
7292 }
7293
7294 link_mode_ori = wl_rinfo->link_mode;
7295 wl->is_5g_hi_channel = is_5g_hi_channel;
7296 wl->bg_mode = bg_mode;
7297 wl->go_client_exist = client_joined;
7298 wl->noa_exist = noa_exist;
7299 wl_rinfo->p2p_2g = p2p_exist;
7300 wl_rinfo->role_map = role_map;
7301
7302 dbcc_en_ori = wl_rinfo->dbcc_en;
7303
7304 if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) {
7305 /* for MLO-supported, link-mode from driver directly */
7306 _update_wl_mlo_info(rtwdev);
7307 } else {
7308 /* for non-MLO-supported, link-mode by BTC */
7309 _update_wl_non_mlo_info(rtwdev);
7310 }
7311
7312 _modify_role_link_mode(rtwdev);
7313
7314 if (link_mode_ori != wl_rinfo->link_mode)
7315 wl->link_mode_chg = true;
7316
7317 if (wl_rinfo->dbcc_en != dbcc_en_ori) {
7318 wl->dbcc_chg = true;
7319 btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++;
7320 }
7321 }
7322
rtw89_coex_act1_work(struct wiphy * wiphy,struct wiphy_work * work)7323 void rtw89_coex_act1_work(struct wiphy *wiphy, struct wiphy_work *work)
7324 {
7325 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7326 coex_act1_work.work);
7327 struct rtw89_btc *btc = &rtwdev->btc;
7328 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7329 struct rtw89_btc_cx *cx = &btc->cx;
7330 struct rtw89_btc_wl_info *wl = &cx->wl;
7331
7332 lockdep_assert_wiphy(wiphy);
7333
7334 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7335 dm->cnt_notify[BTC_NCNT_TIMER]++;
7336 if (wl->status.map._4way)
7337 wl->status.map._4way = false;
7338 if (wl->status.map.connecting)
7339 wl->status.map.connecting = false;
7340
7341 _run_coex(rtwdev, BTC_RSN_ACT1_WORK);
7342 }
7343
rtw89_coex_bt_devinfo_work(struct wiphy * wiphy,struct wiphy_work * work)7344 void rtw89_coex_bt_devinfo_work(struct wiphy *wiphy, struct wiphy_work *work)
7345 {
7346 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7347 coex_bt_devinfo_work.work);
7348 struct rtw89_btc *btc = &rtwdev->btc;
7349 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7350 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
7351
7352 lockdep_assert_wiphy(wiphy);
7353
7354 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7355 dm->cnt_notify[BTC_NCNT_TIMER]++;
7356 a2dp->play_latency = 0;
7357 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK);
7358 }
7359
rtw89_coex_rfk_chk_work(struct wiphy * wiphy,struct wiphy_work * work)7360 void rtw89_coex_rfk_chk_work(struct wiphy *wiphy, struct wiphy_work *work)
7361 {
7362 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7363 coex_rfk_chk_work.work);
7364 struct rtw89_btc *btc = &rtwdev->btc;
7365 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7366 struct rtw89_btc_cx *cx = &btc->cx;
7367 struct rtw89_btc_wl_info *wl = &cx->wl;
7368
7369 lockdep_assert_wiphy(wiphy);
7370
7371 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7372 dm->cnt_notify[BTC_NCNT_TIMER]++;
7373 if (wl->rfk_info.state != BTC_WRFK_STOP) {
7374 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7375 "[BTC], %s(): RFK timeout\n", __func__);
7376 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++;
7377 dm->error.map.wl_rfk_timeout = true;
7378 wl->rfk_info.state = BTC_WRFK_STOP;
7379 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
7380 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK);
7381 }
7382 }
7383
_update_bt_scbd(struct rtw89_dev * rtwdev,bool only_update)7384 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update)
7385 {
7386 const struct rtw89_chip_info *chip = rtwdev->chip;
7387 struct rtw89_btc *btc = &rtwdev->btc;
7388 struct rtw89_btc_cx *cx = &btc->cx;
7389 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
7390 u32 val;
7391 bool status_change = false;
7392
7393 if (!chip->scbd)
7394 return;
7395
7396 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
7397
7398 val = _read_scbd(rtwdev);
7399 if (val == BTC_SCB_INV_VALUE) {
7400 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7401 "[BTC], %s(): return by invalid scbd value\n",
7402 __func__);
7403 return;
7404 }
7405
7406 if (!(val & BTC_BSCB_ON))
7407 bt->enable.now = 0;
7408 else
7409 bt->enable.now = 1;
7410
7411 if (bt->enable.now != bt->enable.last)
7412 status_change = true;
7413
7414 /* reset bt info if bt re-enable */
7415 if (bt->enable.now && !bt->enable.last) {
7416 _reset_btc_var(rtwdev, BTC_RESET_BTINFO);
7417 cx->cnt_bt[BTC_BCNT_REENABLE]++;
7418 bt->enable.now = 1;
7419 }
7420
7421 bt->enable.last = bt->enable.now;
7422 bt->scbd = val;
7423 bt->mbx_avl = !!(val & BTC_BSCB_ACT);
7424
7425 if (bt->whql_test != !!(val & BTC_BSCB_WHQL))
7426 status_change = true;
7427
7428 bt->whql_test = !!(val & BTC_BSCB_WHQL);
7429 bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE;
7430 bt->link_info.a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT);
7431
7432 bt->lna_constrain = !!(val & BTC_BSCB_BT_LNAB0) +
7433 !!(val & BTC_BSCB_BT_LNAB1) * 2 + 4;
7434
7435 /* if rfk run 1->0 */
7436 if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN))
7437 status_change = true;
7438
7439 bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN);
7440 bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ);
7441 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
7442 bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT);
7443 if (bt->run_patch_code != !!(val & BTC_BSCB_PATCH_CODE))
7444 status_change = true;
7445 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
7446
7447 if (!only_update && status_change)
7448 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
7449 }
7450
7451 #define BTC_BTINFO_PWR_LEN 5
_update_bt_txpwr_info(struct rtw89_dev * rtwdev,u8 * buf,u32 len)7452 static void _update_bt_txpwr_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
7453 {
7454 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt;
7455 struct rtw89_btc_bt_link_info *b = &bt->link_info;
7456
7457 if (len != BTC_BTINFO_PWR_LEN)
7458 return;
7459
7460 if (!memcmp(bt->txpwr_info, buf, sizeof(bt->txpwr_info))) {
7461 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7462 "[BTC], %s return by info duplicate!\n", __func__);
7463 return;
7464 }
7465
7466 memcpy(bt->txpwr_info, buf, BTC_BTINFO_MAX);
7467 memcpy(&b->bt_txpwr_desc, &buf[2], sizeof(b->bt_txpwr_desc));
7468 }
7469
_chk_wl_rfk_request(struct rtw89_dev * rtwdev)7470 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev)
7471 {
7472 struct rtw89_btc *btc = &rtwdev->btc;
7473 struct rtw89_btc_cx *cx = &btc->cx;
7474 struct rtw89_btc_bt_info *bt = &cx->bt;
7475
7476 _update_bt_scbd(rtwdev, true);
7477
7478 cx->cnt_wl[BTC_WCNT_RFK_REQ]++;
7479
7480 if ((bt->rfk_info.map.run || bt->rfk_info.map.req) &&
7481 !bt->rfk_info.map.timeout) {
7482 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++;
7483 } else {
7484 cx->cnt_wl[BTC_WCNT_RFK_GO]++;
7485 return true;
7486 }
7487 return false;
7488 }
7489
7490 static
_run_coex(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason)7491 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
7492 {
7493 struct rtw89_btc *btc = &rtwdev->btc;
7494 const struct rtw89_btc_ver *ver = btc->ver;
7495 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7496 struct rtw89_btc_cx *cx = &btc->cx;
7497 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7498 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
7499 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
7500 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
7501 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
7502 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
7503 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
7504 u8 mode, igno_bt, always_freerun;
7505
7506 lockdep_assert_wiphy(rtwdev->hw->wiphy);
7507
7508 dm->run_reason = reason;
7509 _update_dm_step(rtwdev, reason);
7510 _update_btc_state_map(rtwdev);
7511
7512 if (ver->fwlrole == 0)
7513 mode = wl_rinfo->link_mode;
7514 else if (ver->fwlrole == 1)
7515 mode = wl_rinfo_v1->link_mode;
7516 else if (ver->fwlrole == 2)
7517 mode = wl_rinfo_v2->link_mode;
7518 else if (ver->fwlrole == 7)
7519 mode = wl_rinfo_v7->link_mode;
7520 else if (ver->fwlrole == 8)
7521 mode = wl_rinfo_v8->link_mode;
7522 else
7523 return;
7524
7525 if (ver->fcxctrl == 7) {
7526 igno_bt = btc->ctrl.ctrl_v7.igno_bt;
7527 always_freerun = btc->ctrl.ctrl_v7.always_freerun;
7528 } else {
7529 igno_bt = btc->ctrl.ctrl.igno_bt;
7530 always_freerun = btc->ctrl.ctrl.always_freerun;
7531 }
7532
7533 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
7534 __func__, reason, mode);
7535 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
7536 __func__, dm->wl_only, dm->bt_only);
7537
7538 /* Be careful to change the following function sequence!! */
7539 if (btc->manual_ctrl) {
7540 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7541 "[BTC], %s(): return for Manual CTRL!!\n",
7542 __func__);
7543 return;
7544 }
7545
7546 if (igno_bt &&
7547 (reason == BTC_RSN_UPDATE_BT_INFO ||
7548 reason == BTC_RSN_UPDATE_BT_SCBD)) {
7549 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7550 "[BTC], %s(): return for Stop Coex DM!!\n",
7551 __func__);
7552 return;
7553 }
7554
7555 if (!wl->status.map.init_ok) {
7556 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7557 "[BTC], %s(): return for WL init fail!!\n",
7558 __func__);
7559 return;
7560 }
7561
7562 if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
7563 wl->status.map.lps_pre == wl->status.map.lps) {
7564 if (reason == BTC_RSN_NTFY_POWEROFF ||
7565 reason == BTC_RSN_NTFY_RADIO_STATE) {
7566 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7567 "[BTC], %s(): return for WL rf off state no change!!\n",
7568 __func__);
7569 return;
7570 }
7571 if (wl->status.map.rf_off == 1 ||
7572 wl->status.map.lps == BTC_LPS_RF_OFF) {
7573 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7574 "[BTC], %s(): return for WL rf off state!!\n",
7575 __func__);
7576 return;
7577 }
7578 }
7579
7580 dm->freerun = false;
7581 dm->cnt_dm[BTC_DCNT_RUN]++;
7582 dm->fddt_train = BTC_FDDT_DISABLE;
7583 bt->scan_rx_low_pri = false;
7584 igno_bt = false;
7585
7586 dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */
7587
7588 if (always_freerun) {
7589 _action_freerun(rtwdev);
7590 igno_bt = true;
7591 goto exit;
7592 }
7593
7594 if (dm->wl_only) {
7595 _action_wl_only(rtwdev);
7596 igno_bt = true;
7597 goto exit;
7598 }
7599
7600 if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) {
7601 _action_wl_off(rtwdev, mode);
7602 igno_bt = true;
7603 goto exit;
7604 }
7605
7606 if (reason == BTC_RSN_NTFY_INIT) {
7607 _action_wl_init(rtwdev);
7608 goto exit;
7609 }
7610
7611 if (!cx->bt.enable.now && !cx->other.type) {
7612 _action_bt_off(rtwdev);
7613 goto exit;
7614 }
7615
7616 if (cx->bt.whql_test) {
7617 _action_bt_whql(rtwdev);
7618 goto exit;
7619 }
7620
7621 if (wl->rfk_info.state != BTC_WRFK_STOP) {
7622 _action_wl_rfk(rtwdev);
7623 goto exit;
7624 }
7625
7626 if (wl->status.val & btc_scanning_map.val && !wl->rfk_info.con_rfk) {
7627 _action_wl_scan(rtwdev);
7628 bt->scan_rx_low_pri = true;
7629 goto exit;
7630 }
7631
7632 switch (mode) {
7633 case BTC_WLINK_NOLINK:
7634 _action_wl_nc(rtwdev);
7635 break;
7636 case BTC_WLINK_2G_STA:
7637 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
7638 bt->scan_rx_low_pri = true;
7639 _action_wl_2g_sta(rtwdev);
7640 break;
7641 case BTC_WLINK_2G_AP:
7642 bt->scan_rx_low_pri = true;
7643 _action_wl_2g_ap(rtwdev);
7644 break;
7645 case BTC_WLINK_2G_GO:
7646 bt->scan_rx_low_pri = true;
7647 _action_wl_2g_go(rtwdev);
7648 break;
7649 case BTC_WLINK_2G_GC:
7650 bt->scan_rx_low_pri = true;
7651 _action_wl_2g_gc(rtwdev);
7652 break;
7653 case BTC_WLINK_2G_SCC:
7654 bt->scan_rx_low_pri = true;
7655 if (ver->fwlrole == 0)
7656 _action_wl_2g_scc(rtwdev);
7657 else if (ver->fwlrole == 1)
7658 _action_wl_2g_scc_v1(rtwdev);
7659 else if (ver->fwlrole == 2 || ver->fwlrole == 7)
7660 _action_wl_2g_scc_v2(rtwdev);
7661 else if (ver->fwlrole == 8)
7662 _action_wl_2g_scc_v8(rtwdev);
7663 break;
7664 case BTC_WLINK_2G_MCC:
7665 bt->scan_rx_low_pri = true;
7666 _action_wl_2g_mcc(rtwdev);
7667 break;
7668 case BTC_WLINK_25G_MCC:
7669 bt->scan_rx_low_pri = true;
7670 _action_wl_25g_mcc(rtwdev);
7671 break;
7672 case BTC_WLINK_5G:
7673 _action_wl_5g(rtwdev);
7674 break;
7675 case BTC_WLINK_2G_NAN:
7676 _action_wl_2g_nan(rtwdev);
7677 break;
7678 default:
7679 _action_wl_other(rtwdev);
7680 break;
7681 }
7682
7683 exit:
7684 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__);
7685 if (ver->fcxctrl == 7)
7686 btc->ctrl.ctrl_v7.igno_bt = igno_bt;
7687 else
7688 btc->ctrl.ctrl.igno_bt = igno_bt;
7689 _action_common(rtwdev);
7690 }
7691
rtw89_btc_ntfy_poweron(struct rtw89_dev * rtwdev)7692 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
7693 {
7694 struct rtw89_btc *btc = &rtwdev->btc;
7695
7696 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
7697 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++;
7698 }
7699
rtw89_btc_ntfy_poweroff(struct rtw89_dev * rtwdev)7700 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
7701 {
7702 struct rtw89_btc *btc = &rtwdev->btc;
7703 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7704
7705 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
7706 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
7707
7708 btc->cx.wl.status.map.rf_off = 1;
7709 btc->cx.wl.status.map.busy = 0;
7710 wl->status.map.lps = BTC_LPS_OFF;
7711
7712 _write_scbd(rtwdev, BTC_WSCB_ALL, false);
7713 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
7714
7715 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
7716
7717 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
7718 }
7719
_set_init_info(struct rtw89_dev * rtwdev)7720 static void _set_init_info(struct rtw89_dev *rtwdev)
7721 {
7722 const struct rtw89_chip_info *chip = rtwdev->chip;
7723 struct rtw89_btc *btc = &rtwdev->btc;
7724 const struct rtw89_btc_ver *ver = btc->ver;
7725 struct rtw89_btc_dm *dm = &btc->dm;
7726 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7727
7728 if (ver->fcxinit == 7) {
7729 dm->init_info.init_v7.wl_only = (u8)dm->wl_only;
7730 dm->init_info.init_v7.bt_only = (u8)dm->bt_only;
7731 dm->init_info.init_v7.wl_init_ok = (u8)wl->status.map.init_ok;
7732 dm->init_info.init_v7.cx_other = btc->cx.other.type;
7733 dm->init_info.init_v7.wl_guard_ch = chip->afh_guard_ch;
7734 dm->init_info.init_v7.module = btc->mdinfo.md_v7;
7735 } else {
7736 dm->init_info.init.wl_only = (u8)dm->wl_only;
7737 dm->init_info.init.bt_only = (u8)dm->bt_only;
7738 dm->init_info.init.wl_init_ok = (u8)wl->status.map.init_ok;
7739 dm->init_info.init.dbcc_en = rtwdev->dbcc_en;
7740 dm->init_info.init.cx_other = btc->cx.other.type;
7741 dm->init_info.init.wl_guard_ch = chip->afh_guard_ch;
7742 dm->init_info.init.module = btc->mdinfo.md;
7743 }
7744 }
7745
rtw89_btc_ntfy_init(struct rtw89_dev * rtwdev,u8 mode)7746 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
7747 {
7748 struct rtw89_btc *btc = &rtwdev->btc;
7749 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7750 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7751 const struct rtw89_chip_info *chip = rtwdev->chip;
7752 const struct rtw89_btc_ver *ver = btc->ver;
7753
7754 _reset_btc_var(rtwdev, BTC_RESET_ALL);
7755 btc->dm.run_reason = BTC_RSN_NONE;
7756 btc->dm.run_action = BTC_ACT_NONE;
7757 if (ver->fcxctrl == 7)
7758 btc->ctrl.ctrl_v7.igno_bt = true;
7759 else
7760 btc->ctrl.ctrl.igno_bt = true;
7761
7762 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7763 "[BTC], %s(): mode=%d\n", __func__, mode);
7764
7765 wl->coex_mode = mode;
7766 dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
7767 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0;
7768 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0;
7769 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0;
7770
7771 chip->ops->btc_set_rfe(rtwdev);
7772 chip->ops->btc_init_cfg(rtwdev);
7773
7774 if (!wl->status.map.init_ok) {
7775 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7776 "[BTC], %s(): return for WL init fail!!\n",
7777 __func__);
7778 dm->error.map.init = true;
7779 return;
7780 }
7781
7782 _write_scbd(rtwdev,
7783 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
7784 _update_bt_scbd(rtwdev, true);
7785 if (rtw89_mac_get_ctrl_path(rtwdev)) {
7786 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7787 "[BTC], %s(): PTA owner warning!!\n",
7788 __func__);
7789 dm->error.map.pta_owner = true;
7790 }
7791
7792 _set_init_info(rtwdev);
7793 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR);
7794 btc_fw_set_monreg(rtwdev);
7795 rtw89_btc_fw_set_slots(rtwdev);
7796 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
7797 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
7798
7799 _run_coex(rtwdev, BTC_RSN_NTFY_INIT);
7800 }
7801
rtw89_btc_ntfy_scan_start(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)7802 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
7803 {
7804 struct rtw89_btc *btc = &rtwdev->btc;
7805 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7806
7807 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7808 "[BTC], %s(): phy_idx=%d, band=%d\n",
7809 __func__, phy_idx, band);
7810
7811 if (phy_idx >= RTW89_PHY_NUM)
7812 return;
7813
7814 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
7815 wl->status.map.scan = true;
7816 wl->scan_info.band[phy_idx] = band;
7817 wl->scan_info.phy_map |= BIT(phy_idx);
7818 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
7819
7820 if (rtwdev->dbcc_en) {
7821 wl->dbcc_info.scan_band[phy_idx] = band;
7822 _update_dbcc_band(rtwdev, phy_idx);
7823 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7824 }
7825
7826 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START);
7827 }
7828
rtw89_btc_ntfy_scan_finish(struct rtw89_dev * rtwdev,u8 phy_idx)7829 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
7830 {
7831 struct rtw89_btc *btc = &rtwdev->btc;
7832 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7833
7834 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7835 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
7836 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
7837
7838 wl->status.map.scan = false;
7839 wl->scan_info.phy_map &= ~BIT(phy_idx);
7840 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
7841
7842 if (rtwdev->dbcc_en) {
7843 _update_dbcc_band(rtwdev, phy_idx);
7844 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7845 }
7846
7847 btc->dm.tdma_instant_excute = 1;
7848
7849 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
7850 }
7851
rtw89_btc_ntfy_switch_band(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)7852 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
7853 {
7854 struct rtw89_btc *btc = &rtwdev->btc;
7855 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7856
7857 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7858 "[BTC], %s(): phy_idx=%d, band=%d\n",
7859 __func__, phy_idx, band);
7860
7861 if (phy_idx >= RTW89_PHY_NUM)
7862 return;
7863
7864 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
7865
7866 if (rtwdev->dbcc_en) {
7867 wl->dbcc_info.scan_band[phy_idx] = band;
7868 _update_dbcc_band(rtwdev, phy_idx);
7869 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7870 }
7871 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND);
7872 }
7873
rtw89_btc_ntfy_specific_packet(struct rtw89_dev * rtwdev,enum btc_pkt_type pkt_type)7874 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev,
7875 enum btc_pkt_type pkt_type)
7876 {
7877 struct rtw89_btc *btc = &rtwdev->btc;
7878 struct rtw89_btc_cx *cx = &btc->cx;
7879 struct rtw89_btc_wl_info *wl = &cx->wl;
7880 struct rtw89_btc_bt_link_info *b = &cx->bt.link_info;
7881 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
7882 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
7883 u32 cnt;
7884 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD;
7885 bool delay_work = false;
7886
7887 switch (pkt_type) {
7888 case PACKET_DHCP:
7889 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP];
7890 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7891 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt);
7892 wl->status.map.connecting = true;
7893 delay_work = true;
7894 break;
7895 case PACKET_EAPOL:
7896 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
7897 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7898 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt);
7899 wl->status.map._4way = true;
7900 delay_work = true;
7901 if (hfp->exist || hid->exist)
7902 delay /= 2;
7903 break;
7904 case PACKET_EAPOL_END:
7905 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
7906 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7907 "[BTC], %s(): EAPOL_End cnt=%d\n",
7908 __func__, cnt);
7909 wl->status.map._4way = false;
7910 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work);
7911 break;
7912 case PACKET_ARP:
7913 cnt = ++cx->cnt_wl[BTC_WCNT_ARP];
7914 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7915 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt);
7916 return;
7917 case PACKET_ICMP:
7918 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7919 "[BTC], %s(): ICMP pkt\n", __func__);
7920 return;
7921 default:
7922 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7923 "[BTC], %s(): unknown packet type %d\n",
7924 __func__, pkt_type);
7925 return;
7926 }
7927
7928 if (delay_work) {
7929 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work);
7930 wiphy_delayed_work_queue(rtwdev->hw->wiphy,
7931 &rtwdev->coex_act1_work, delay);
7932 }
7933
7934 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
7935 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET);
7936 }
7937
rtw89_btc_ntfy_eapol_packet_work(struct wiphy * wiphy,struct wiphy_work * work)7938 void rtw89_btc_ntfy_eapol_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7939 {
7940 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7941 btc.eapol_notify_work);
7942
7943 lockdep_assert_wiphy(wiphy);
7944
7945 rtw89_leave_ps_mode(rtwdev);
7946 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL);
7947 }
7948
rtw89_btc_ntfy_arp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)7949 void rtw89_btc_ntfy_arp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7950 {
7951 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7952 btc.arp_notify_work);
7953
7954 lockdep_assert_wiphy(wiphy);
7955
7956 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP);
7957 }
7958
rtw89_btc_ntfy_dhcp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)7959 void rtw89_btc_ntfy_dhcp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7960 {
7961 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7962 btc.dhcp_notify_work);
7963
7964 lockdep_assert_wiphy(wiphy);
7965
7966 rtw89_leave_ps_mode(rtwdev);
7967 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP);
7968 }
7969
rtw89_btc_ntfy_icmp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)7970 void rtw89_btc_ntfy_icmp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7971 {
7972 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7973 btc.icmp_notify_work);
7974
7975 lockdep_assert_wiphy(wiphy);
7976
7977 rtw89_leave_ps_mode(rtwdev);
7978 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP);
7979 }
7980
_update_bt_rssi_level(struct rtw89_dev * rtwdev,u8 rssi)7981 static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi)
7982 {
7983 const struct rtw89_chip_info *chip = rtwdev->chip;
7984 struct rtw89_btc *btc = &rtwdev->btc;
7985 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
7986 u8 *rssi_st, rssi_th, rssi_level = 0;
7987 u8 i;
7988
7989 /* for rssi locate in which {40, 36, 31, 28}
7990 * if rssi >= 40% (-60dBm) --> rssi_level = 4
7991 * if 36% <= rssi < 40% --> rssi_level = 3
7992 * if 31% <= rssi < 36% --> rssi_level = 2
7993 * if 28% <= rssi < 31% --> rssi_level = 1
7994 * if rssi < 28% --> rssi_level = 0
7995 */
7996
7997 /* check if rssi across bt_rssi_thres boundary */
7998 for (i = 0; i < BTC_BT_RSSI_THMAX; i++) {
7999 rssi_th = chip->bt_rssi_thres[i];
8000 rssi_st = &bt->link_info.rssi_state[i];
8001
8002 *rssi_st = _update_rssi_state(rtwdev, *rssi_st, rssi, rssi_th);
8003
8004 if (BTC_RSSI_HIGH(*rssi_st)) {
8005 rssi_level = BTC_BT_RSSI_THMAX - i;
8006 break;
8007 }
8008 }
8009 return rssi_level;
8010 }
8011
_update_zb_coex_tbl(struct rtw89_dev * rtwdev)8012 static void _update_zb_coex_tbl(struct rtw89_dev *rtwdev)
8013 {
8014 u8 mode = rtwdev->btc.cx.wl.role_info.link_mode;
8015 u32 zb_tbl0 = 0xda5a5a5a, zb_tbl1 = 0xda5a5a5a;
8016
8017 if (mode == BTC_WLINK_5G || rtwdev->btc.dm.freerun) {
8018 zb_tbl0 = 0xffffffff;
8019 zb_tbl1 = 0xffffffff;
8020 } else if (mode == BTC_WLINK_25G_MCC) {
8021 zb_tbl0 = 0xffffffff; /* for E5G slot */
8022 zb_tbl1 = 0xda5a5a5a; /* for E2G slot */
8023 }
8024 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_0, zb_tbl0);
8025 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_1, zb_tbl1);
8026 }
8027
8028 #define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4)
8029
_update_bt_info(struct rtw89_dev * rtwdev,u8 * buf,u32 len)8030 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
8031 {
8032 const struct rtw89_chip_info *chip = rtwdev->chip;
8033 struct rtw89_btc *btc = &rtwdev->btc;
8034 struct rtw89_btc_cx *cx = &btc->cx;
8035 struct rtw89_btc_bt_info *bt = &cx->bt;
8036 struct rtw89_btc_bt_link_info *b = &bt->link_info;
8037 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
8038 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
8039 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
8040 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc;
8041 union btc_btinfo btinfo;
8042
8043 if (buf[BTC_BTINFO_L1] != 6)
8044 return;
8045
8046 if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) {
8047 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8048 "[BTC], %s(): return by bt-info duplicate!!\n",
8049 __func__);
8050 cx->cnt_bt[BTC_BCNT_INFOSAME]++;
8051 return;
8052 }
8053
8054 memcpy(bt->raw_info, buf, BTC_BTINFO_MAX);
8055
8056 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8057 "[BTC], %s(): bt_info[2]=0x%02x\n",
8058 __func__, bt->raw_info[2]);
8059
8060 b->profile_cnt.last = b->profile_cnt.now;
8061 b->profile_cnt.now = 0;
8062 hid->type = 0;
8063
8064 /* parse raw info low-Byte2 */
8065 btinfo.val = bt->raw_info[BTC_BTINFO_L2];
8066 b->status.map.connect = btinfo.lb2.connect;
8067 b->status.map.sco_busy = btinfo.lb2.sco_busy;
8068 b->status.map.acl_busy = btinfo.lb2.acl_busy;
8069 b->status.map.inq_pag = btinfo.lb2.inq_pag;
8070 bt->inq_pag.now = btinfo.lb2.inq_pag;
8071 cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
8072
8073 hfp->exist = btinfo.lb2.hfp;
8074 b->profile_cnt.now += (u8)hfp->exist;
8075 hid->exist = btinfo.lb2.hid;
8076 b->profile_cnt.now += (u8)hid->exist;
8077 a2dp->exist = btinfo.lb2.a2dp;
8078 b->profile_cnt.now += (u8)a2dp->exist;
8079 pan->exist = btinfo.lb2.pan;
8080 b->profile_cnt.now += (u8)pan->exist;
8081 btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK);
8082
8083 /* parse raw info low-Byte3 */
8084 btinfo.val = bt->raw_info[BTC_BTINFO_L3];
8085 if (btinfo.lb3.retry != 0)
8086 cx->cnt_bt[BTC_BCNT_RETRY]++;
8087 b->cqddr = btinfo.lb3.cqddr;
8088 cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
8089 bt->inq = btinfo.lb3.inq;
8090 cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
8091 bt->pag = btinfo.lb3.pag;
8092
8093 b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
8094 /* parse raw info high-Byte0 */
8095 btinfo.val = bt->raw_info[BTC_BTINFO_H0];
8096 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/
8097 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi);
8098 bt->rssi_level = _update_bt_rssi_level(rtwdev, b->rssi);
8099 btc->dm.trx_info.bt_rssi = bt->rssi_level;
8100
8101 /* parse raw info high-Byte1 */
8102 btinfo.val = bt->raw_info[BTC_BTINFO_H1];
8103 b->status.map.ble_connect = btinfo.hb1.ble_connect;
8104 if (btinfo.hb1.ble_connect) {
8105 if (hid->exist)
8106 hid->type |= BTC_HID_BLE;
8107 else if (btinfo.hb1.voice)
8108 hid->type |= BTC_HID_RCU_VOICE;
8109 else
8110 hid->type |= BTC_HID_RCU;
8111 }
8112
8113 cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
8114 bt->reinit = btinfo.hb1.reinit;
8115 cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
8116 b->relink.now = btinfo.hb1.relink;
8117 cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
8118 bt->igno_wl = btinfo.hb1.igno_wl;
8119
8120 if (bt->igno_wl && !cx->wl.status.map.rf_off)
8121 _set_bt_ignore_wlan_act(rtwdev, false);
8122
8123 bt->ble_scan_en = btinfo.hb1.ble_scan;
8124
8125 cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
8126 b->role_sw = btinfo.hb1.role_sw;
8127
8128 b->multi_link.now = btinfo.hb1.multi_link;
8129
8130 /* parse raw info high-Byte2 */
8131 btinfo.val = bt->raw_info[BTC_BTINFO_H2];
8132 pan->active = !!btinfo.hb2.pan_active;
8133
8134 cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
8135 b->afh_update = btinfo.hb2.afh_update;
8136 a2dp->active = btinfo.hb2.a2dp_active;
8137 b->slave_role = btinfo.hb2.slave;
8138 hid->slot_info = btinfo.hb2.hid_slot;
8139 hid->pair_cnt = btinfo.hb2.hid_cnt;
8140 if (!b->status.map.ble_connect || hid->pair_cnt > 1)
8141 hid->type |= (hid->slot_info == BTC_HID_218 ?
8142 BTC_HID_218 : BTC_HID_418);
8143 /* parse raw info high-Byte3 */
8144 btinfo.val = bt->raw_info[BTC_BTINFO_H3];
8145 a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
8146
8147 if (b->tx_3m != (u32)btinfo.hb3.tx_3m)
8148 cx->cnt_bt[BTC_BCNT_RATECHG]++;
8149 b->tx_3m = (u32)btinfo.hb3.tx_3m;
8150
8151 a2dp->sink = btinfo.hb3.a2dp_sink;
8152
8153 if (!a2dp->exist_last && a2dp->exist) {
8154 a2dp->vendor_id = 0;
8155 a2dp->flush_time = 0;
8156 a2dp->play_latency = 1;
8157 wiphy_delayed_work_queue(rtwdev->hw->wiphy,
8158 &rtwdev->coex_bt_devinfo_work,
8159 RTW89_COEX_BT_DEVINFO_WORK_PERIOD);
8160 }
8161
8162 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
8163 }
8164
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)8165 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev,
8166 struct rtw89_vif_link *rtwvif_link,
8167 struct rtw89_sta_link *rtwsta_link,
8168 enum btc_role_state state)
8169 {
8170 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
8171 rtwvif_link->chanctx_idx);
8172 struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
8173 struct ieee80211_bss_conf *bss_conf;
8174 struct ieee80211_link_sta *link_sta;
8175 struct rtw89_btc *btc = &rtwdev->btc;
8176 const struct rtw89_btc_ver *ver = btc->ver;
8177 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8178 struct rtw89_btc_wl_link_info r = {0};
8179 struct rtw89_btc_wl_link_info *wlinfo = NULL;
8180 u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type;
8181
8182 rcu_read_lock();
8183
8184 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
8185
8186 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
8187 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8188 "[BTC], role is STA=%d\n",
8189 vif->type == NL80211_IFTYPE_STATION);
8190 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif_link->port);
8191 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
8192 chan->band_type, chan->channel, chan->band_width);
8193 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
8194 state == BTC_ROLE_MSTS_STA_CONN_END);
8195 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8196 "[BTC], bcn_period=%d dtim_period=%d\n",
8197 bss_conf->beacon_int, bss_conf->dtim_period);
8198
8199 if (rtwsta_link) {
8200 link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
8201
8202 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
8203 rtwsta_link->mac_id);
8204
8205 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8206 "[BTC], STA support HE=%d VHT=%d HT=%d\n",
8207 link_sta->he_cap.has_he,
8208 link_sta->vht_cap.vht_supported,
8209 link_sta->ht_cap.ht_supported);
8210 if (link_sta->he_cap.has_he)
8211 mode |= BIT(BTC_WL_MODE_HE);
8212 if (link_sta->vht_cap.vht_supported)
8213 mode |= BIT(BTC_WL_MODE_VHT);
8214 if (link_sta->ht_cap.ht_supported)
8215 mode |= BIT(BTC_WL_MODE_HT);
8216
8217 r.mode = mode;
8218 }
8219
8220 if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) {
8221 rcu_read_unlock();
8222 return;
8223 }
8224
8225 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8226 "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role);
8227
8228 r.role = rtwvif_link->wifi_role;
8229 r.phy = rtwvif_link->phy_idx;
8230 r.pid = rtwvif_link->port;
8231 r.active = true;
8232 r.connected = MLME_LINKED;
8233 r.bcn_period = bss_conf->beacon_int;
8234 r.dtim_period = bss_conf->dtim_period;
8235 r.band = chan->band_type;
8236 r.ch = chan->channel;
8237 r.bw = chan->band_width;
8238 r.chdef.band = chan->band_type;
8239 r.chdef.center_ch = chan->channel;
8240 r.chdef.bw = chan->band_width;
8241 r.chdef.chan = chan->primary_channel;
8242 ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr);
8243
8244 rcu_read_unlock();
8245
8246 if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION)
8247 r.mac_id = rtwsta_link->mac_id;
8248
8249 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
8250
8251 wlinfo = &wl->link_info[r.pid];
8252
8253 if (ver->fwlrole == 0) {
8254 *wlinfo = r;
8255 _update_wl_info(rtwdev);
8256 } else if (ver->fwlrole == 1) {
8257 *wlinfo = r;
8258 _update_wl_info_v1(rtwdev);
8259 } else if (ver->fwlrole == 2) {
8260 *wlinfo = r;
8261 _update_wl_info_v2(rtwdev);
8262 } else if (ver->fwlrole == 7) {
8263 *wlinfo = r;
8264 _update_wl_info_v7(rtwdev, r.pid);
8265 } else if (ver->fwlrole == 8) {
8266 rlink_id = rtwvif_link->mac_idx;
8267 wlinfo = &wl->rlink_info[r.pid][rlink_id];
8268 *wlinfo = r;
8269 link_mode_ori = wl->role_info_v8.link_mode;
8270 pta_req_mac_ori = wl->pta_req_mac;
8271 _update_wl_info_v8(rtwdev, r.pid, rlink_id, state);
8272
8273 if (wl->role_info_v8.link_mode != link_mode_ori) {
8274 wl->role_info_v8.link_mode_chg = 1;
8275 if (ver->fcxinit == 7)
8276 wa_type = btc->mdinfo.md_v7.wa_type;
8277 else
8278 wa_type = btc->mdinfo.md.wa_type;
8279
8280 if (wa_type & BTC_WA_HFP_ZB)
8281 _update_zb_coex_tbl(rtwdev);
8282 }
8283
8284 if (wl->pta_req_mac != pta_req_mac_ori)
8285 wl->pta_reg_mac_chg = 1;
8286 }
8287
8288 if (wlinfo->role == RTW89_WIFI_ROLE_STATION &&
8289 wlinfo->connected == MLME_NO_LINK)
8290 btc->dm.leak_ap = 0;
8291
8292 if (state == BTC_ROLE_MSTS_STA_CONN_START)
8293 wl->status.map.connecting = 1;
8294 else
8295 wl->status.map.connecting = 0;
8296
8297 if (state == BTC_ROLE_MSTS_STA_DIS_CONN ||
8298 state == BTC_ROLE_MSTS_STA_CONN_END)
8299 wl->status.map._4way = false;
8300
8301 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
8302 }
8303
rtw89_btc_ntfy_radio_state(struct rtw89_dev * rtwdev,enum btc_rfctrl rf_state)8304 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state)
8305 {
8306 const struct rtw89_chip_info *chip = rtwdev->chip;
8307 struct rtw89_btc *btc = &rtwdev->btc;
8308 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8309 u32 val;
8310
8311 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
8312 __func__, rf_state);
8313 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
8314
8315 switch (rf_state) {
8316 case BTC_RFCTRL_WL_OFF:
8317 wl->status.map.rf_off = 1;
8318 wl->status.map.lps = BTC_LPS_OFF;
8319 wl->status.map.busy = 0;
8320 break;
8321 case BTC_RFCTRL_FW_CTRL:
8322 wl->status.map.rf_off = 0;
8323 wl->status.map.lps = BTC_LPS_RF_OFF;
8324 wl->status.map.busy = 0;
8325 break;
8326 case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */
8327 wl->status.map.rf_off = 0;
8328 wl->status.map.lps = BTC_LPS_RF_ON;
8329 wl->status.map.busy = 0;
8330 break;
8331 case BTC_RFCTRL_WL_ON:
8332 default:
8333 wl->status.map.rf_off = 0;
8334 wl->status.map.lps = BTC_LPS_OFF;
8335 break;
8336 }
8337
8338 if (rf_state == BTC_RFCTRL_WL_ON) {
8339 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, true);
8340 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG;
8341 _write_scbd(rtwdev, val, true);
8342 _update_bt_scbd(rtwdev, true);
8343 chip->ops->btc_init_cfg(rtwdev);
8344 } else {
8345 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false);
8346 if (rf_state == BTC_RFCTRL_FW_CTRL)
8347 _write_scbd(rtwdev, BTC_WSCB_ACTIVE, false);
8348 else if (rf_state == BTC_RFCTRL_WL_OFF)
8349 _write_scbd(rtwdev, BTC_WSCB_ALL, false);
8350 else
8351 _write_scbd(rtwdev, BTC_WSCB_ACTIVE, false);
8352
8353 if (rf_state == BTC_RFCTRL_LPS_WL_ON &&
8354 wl->status.map.lps_pre != BTC_LPS_OFF)
8355 _update_bt_scbd(rtwdev, true);
8356 }
8357
8358 btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
8359 btc->dm.tdma_instant_excute = 1;
8360
8361 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
8362 wl->status.map.rf_off_pre = wl->status.map.rf_off;
8363 wl->status.map.lps_pre = wl->status.map.lps;
8364 }
8365
_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_path,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)8366 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path,
8367 enum btc_wl_rfk_type type,
8368 enum btc_wl_rfk_state state)
8369 {
8370 struct rtw89_btc *btc = &rtwdev->btc;
8371 struct rtw89_btc_cx *cx = &btc->cx;
8372 struct rtw89_btc_wl_info *wl = &cx->wl;
8373 bool result = BTC_WRFK_REJECT;
8374
8375 wl->rfk_info.type = type;
8376 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path);
8377 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path);
8378 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path);
8379
8380 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8381 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
8382 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
8383 type, state);
8384
8385 switch (state) {
8386 case BTC_WRFK_START:
8387 result = _chk_wl_rfk_request(rtwdev);
8388 wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP;
8389
8390 _write_scbd(rtwdev, BTC_WSCB_WLRFK, result);
8391
8392 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
8393 break;
8394 case BTC_WRFK_ONESHOT_START:
8395 case BTC_WRFK_ONESHOT_STOP:
8396 if (wl->rfk_info.state == BTC_WRFK_STOP) {
8397 result = BTC_WRFK_REJECT;
8398 } else {
8399 result = BTC_WRFK_ALLOW;
8400 wl->rfk_info.state = state;
8401 }
8402 break;
8403 case BTC_WRFK_STOP:
8404 result = BTC_WRFK_ALLOW;
8405 wl->rfk_info.state = BTC_WRFK_STOP;
8406
8407 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
8408 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_rfk_chk_work);
8409 break;
8410 default:
8411 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8412 "[BTC], %s() warning state=%d\n", __func__, state);
8413 break;
8414 }
8415
8416 if (result == BTC_WRFK_ALLOW) {
8417 if (wl->rfk_info.state == BTC_WRFK_START ||
8418 wl->rfk_info.state == BTC_WRFK_STOP)
8419 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK);
8420
8421 if (wl->rfk_info.state == BTC_WRFK_START)
8422 wiphy_delayed_work_queue(rtwdev->hw->wiphy,
8423 &rtwdev->coex_rfk_chk_work,
8424 RTW89_COEX_RFK_CHK_WORK_PERIOD);
8425 }
8426
8427 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8428 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
8429 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
8430
8431 return result == BTC_WRFK_ALLOW;
8432 }
8433
rtw89_btc_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_map,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)8434 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
8435 enum btc_wl_rfk_type type,
8436 enum btc_wl_rfk_state state)
8437 {
8438 u8 band;
8439 bool allow;
8440 int ret;
8441
8442 lockdep_assert_wiphy(rtwdev->hw->wiphy);
8443
8444 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map);
8445
8446 rtw89_debug(rtwdev, RTW89_DBG_RFK,
8447 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n",
8448 band == RTW89_BAND_2G ? "2G" :
8449 band == RTW89_BAND_5G ? "5G" : "6G",
8450 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)),
8451 type,
8452 FIELD_GET(BTC_RFK_PATH_MAP, phy_map),
8453 state == BTC_WRFK_STOP ? "RFK_STOP" :
8454 state == BTC_WRFK_START ? "RFK_START" :
8455 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" :
8456 "ONE-SHOT_STOP");
8457
8458 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) {
8459 _ntfy_wl_rfk(rtwdev, phy_map, type, state);
8460 return;
8461 }
8462
8463 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false,
8464 rtwdev, phy_map, type, state);
8465 if (ret) {
8466 rtw89_warn(rtwdev, "RFK notify timeout\n");
8467 rtwdev->is_bt_iqk_timeout = true;
8468 }
8469 }
8470 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk);
8471
8472 struct rtw89_btc_wl_sta_iter_data {
8473 struct rtw89_dev *rtwdev;
8474 u8 busy_all;
8475 u8 dir_all;
8476 u8 rssi_map_all;
8477 bool is_sta_change;
8478 bool is_traffic_change;
8479 };
8480
8481 static
__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)8482 void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link,
8483 struct rtw89_sta_link *rtwsta_link,
8484 struct rtw89_btc_wl_sta_iter_data *iter_data)
8485 {
8486 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
8487 struct rtw89_dev *rtwdev = iter_data->rtwdev;
8488 struct rtw89_btc *btc = &rtwdev->btc;
8489 struct rtw89_btc_dm *dm = &btc->dm;
8490 const struct rtw89_btc_ver *ver = btc->ver;
8491 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8492 struct rtw89_btc_wl_link_info *link_info = NULL;
8493 struct rtw89_traffic_stats *link_info_t = NULL;
8494 struct rtw89_traffic_stats *stats = &rtwvif->stats;
8495 const struct rtw89_chip_info *chip = rtwdev->chip;
8496 struct rtw89_btc_wl_role_info *r;
8497 struct rtw89_btc_wl_role_info_v1 *r1;
8498 u32 last_tx_rate, last_rx_rate;
8499 u16 last_tx_lvl, last_rx_lvl;
8500 u8 port = rtwvif_link->port;
8501 u8 rssi;
8502 u8 busy = 0;
8503 u8 dir = 0;
8504 u8 rssi_map = 0;
8505 u8 i = 0;
8506 bool is_sta_change = false, is_traffic_change = false;
8507
8508 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR;
8509 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
8510
8511 if (btc->ver->fwlrole != 8)
8512 link_info = &wl->link_info[port];
8513 else
8514 link_info = &wl->rlink_info[port][rtwvif_link->mac_idx];
8515
8516 link_info->stat.traffic = *stats;
8517 link_info_t = &link_info->stat.traffic;
8518
8519 if (link_info->connected == MLME_NO_LINK) {
8520 link_info->rx_rate_drop_cnt = 0;
8521 return;
8522 }
8523
8524 link_info->stat.rssi = rssi;
8525 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) {
8526 link_info->rssi_state[i] =
8527 _update_rssi_state(rtwdev,
8528 link_info->rssi_state[i],
8529 link_info->stat.rssi,
8530 chip->wl_rssi_thres[i]);
8531 if (BTC_RSSI_LOW(link_info->rssi_state[i]))
8532 rssi_map |= BIT(i);
8533
8534 if (btc->ant_type == BTC_ANT_DEDICATED &&
8535 BTC_RSSI_CHANGE(link_info->rssi_state[i]))
8536 is_sta_change = true;
8537 }
8538 iter_data->rssi_map_all |= rssi_map;
8539
8540 last_tx_rate = link_info_t->tx_rate;
8541 last_rx_rate = link_info_t->rx_rate;
8542 last_tx_lvl = (u16)link_info_t->tx_tfc_lv;
8543 last_rx_lvl = (u16)link_info_t->rx_tfc_lv;
8544
8545 if (stats->tx_tfc_lv != RTW89_TFC_IDLE ||
8546 stats->rx_tfc_lv != RTW89_TFC_IDLE)
8547 busy = 1;
8548
8549 if (stats->tx_tfc_lv > stats->rx_tfc_lv)
8550 dir = RTW89_TFC_UL;
8551 else
8552 dir = RTW89_TFC_DL;
8553
8554 link_info = &wl->link_info[port];
8555 if (link_info->busy != busy || link_info->dir != dir) {
8556 is_sta_change = true;
8557 link_info->busy = busy;
8558 link_info->dir = dir;
8559 }
8560
8561 iter_data->busy_all |= busy;
8562 iter_data->dir_all |= BIT(dir);
8563
8564 if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
8565 last_rx_rate > RTW89_HW_RATE_CCK2 &&
8566 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
8567 link_info->rx_rate_drop_cnt++;
8568
8569 if (last_tx_rate != rtwsta_link->ra_report.hw_rate ||
8570 last_rx_rate != rtwsta_link->rx_hw_rate ||
8571 last_tx_lvl != link_info_t->tx_tfc_lv ||
8572 last_rx_lvl != link_info_t->rx_tfc_lv)
8573 is_traffic_change = true;
8574
8575 link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate;
8576 link_info_t->rx_rate = rtwsta_link->rx_hw_rate;
8577
8578 if (link_info->role == RTW89_WIFI_ROLE_STATION ||
8579 link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) {
8580 dm->trx_info.tx_rate = link_info_t->tx_rate;
8581 dm->trx_info.rx_rate = link_info_t->rx_rate;
8582 }
8583
8584 if (ver->fwlrole == 0) {
8585 r = &wl->role_info;
8586 r->active_role[port].tx_lvl = stats->tx_tfc_lv;
8587 r->active_role[port].rx_lvl = stats->rx_tfc_lv;
8588 r->active_role[port].tx_rate = rtwsta_link->ra_report.hw_rate;
8589 r->active_role[port].rx_rate = rtwsta_link->rx_hw_rate;
8590 } else if (ver->fwlrole == 1) {
8591 r1 = &wl->role_info_v1;
8592 r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv;
8593 r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv;
8594 r1->active_role_v1[port].tx_rate = rtwsta_link->ra_report.hw_rate;
8595 r1->active_role_v1[port].rx_rate = rtwsta_link->rx_hw_rate;
8596 }
8597
8598 dm->trx_info.tx_lvl = stats->tx_tfc_lv;
8599 dm->trx_info.rx_lvl = stats->rx_tfc_lv;
8600 dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate;
8601 dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate;
8602 dm->trx_info.tx_tp = link_info_t->tx_throughput;
8603 dm->trx_info.rx_tp = link_info_t->rx_throughput;
8604
8605 /* Trigger coex-run if 0x10980 reg-value is diff with coex setup */
8606 if ((dm->wl_btg_rx_rb != dm->wl_btg_rx &&
8607 dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) ||
8608 (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
8609 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND))
8610 iter_data->is_sta_change = true;
8611
8612 if (is_sta_change)
8613 iter_data->is_sta_change = true;
8614
8615 if (is_traffic_change)
8616 iter_data->is_traffic_change = true;
8617 }
8618
rtw89_btc_ntfy_wl_sta_iter(void * data,struct ieee80211_sta * sta)8619 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
8620 {
8621 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
8622 struct rtw89_btc_wl_sta_iter_data *iter_data =
8623 (struct rtw89_btc_wl_sta_iter_data *)data;
8624 struct rtw89_vif_link *rtwvif_link;
8625 struct rtw89_sta_link *rtwsta_link;
8626 unsigned int link_id;
8627
8628 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
8629 rtwvif_link = rtwsta_link->rtwvif_link;
8630 __rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data);
8631 }
8632 }
8633
8634 #define BTC_NHM_CHK_INTVL 20
8635
rtw89_btc_ntfy_wl_sta(struct rtw89_dev * rtwdev)8636 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
8637 {
8638 struct rtw89_btc *btc = &rtwdev->btc;
8639 struct rtw89_btc_dm *dm = &btc->dm;
8640 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8641 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev};
8642 u8 i;
8643
8644 ieee80211_iterate_stations_atomic(rtwdev->hw,
8645 rtw89_btc_ntfy_wl_sta_iter,
8646 &data);
8647
8648 wl->rssi_level = 0;
8649 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++;
8650 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) {
8651 /* set RSSI level 4 ~ 0 if rssi bit map match */
8652 if (data.rssi_map_all & BIT(i - 1)) {
8653 wl->rssi_level = i;
8654 break;
8655 }
8656 }
8657
8658 if (dm->trx_info.wl_rssi != wl->rssi_level)
8659 dm->trx_info.wl_rssi = wl->rssi_level;
8660
8661 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n",
8662 __func__, !!wl->status.map.busy);
8663
8664 _write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy));
8665
8666 if (data.is_traffic_change)
8667 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
8668 if (data.is_sta_change) {
8669 wl->status.map.busy = data.busy_all;
8670 wl->status.map.traffic_dir = data.dir_all;
8671 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA);
8672 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >=
8673 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) {
8674 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
8675 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
8676 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] <
8677 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) {
8678 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
8679 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
8680 }
8681 }
8682
rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev * rtwdev,u8 func)8683 static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func)
8684 {
8685 struct rtw89_btc *btc = &rtwdev->btc;
8686 const struct rtw89_btc_ver *ver = btc->ver;
8687
8688 switch (func) {
8689 case BTF_EVNT_RPT:
8690 case BTF_EVNT_BT_INFO:
8691 case BTF_EVNT_BT_SCBD:
8692 case BTF_EVNT_BT_REG:
8693 case BTF_EVNT_CX_RUNINFO:
8694 case BTF_EVNT_BT_PSD:
8695 return func;
8696 case BTF_EVNT_BT_DEV_INFO:
8697 if (ver->fwc2hfunc == 0)
8698 return BTF_EVNT_BUF_OVERFLOW;
8699 else
8700 return BTF_EVNT_BT_DEV_INFO;
8701 case BTF_EVNT_BT_LEAUDIO_INFO:
8702 if (ver->fwc2hfunc == 0)
8703 return BTF_EVNT_C2H_LOOPBACK;
8704 else if (ver->fwc2hfunc == 1)
8705 return BTF_EVNT_BUF_OVERFLOW;
8706 else if (ver->fwc2hfunc == 2)
8707 return func;
8708 else if (ver->fwc2hfunc == 3)
8709 return BTF_EVNT_BUF_OVERFLOW;
8710 else
8711 return BTF_EVNT_MAX;
8712 case BTF_EVNT_BUF_OVERFLOW:
8713 if (ver->fwc2hfunc == 0)
8714 return BTF_EVNT_MAX;
8715 else if (ver->fwc2hfunc == 1)
8716 return BTF_EVNT_C2H_LOOPBACK;
8717 else if (ver->fwc2hfunc == 2)
8718 return func;
8719 else if (ver->fwc2hfunc == 3)
8720 return BTF_EVNT_C2H_LOOPBACK;
8721 else
8722 return BTF_EVNT_MAX;
8723 case BTF_EVNT_C2H_LOOPBACK:
8724 if (ver->fwc2hfunc == 2)
8725 return func;
8726 else if (ver->fwc2hfunc == 3)
8727 return BTF_EVNT_BT_LEAUDIO_INFO;
8728 else
8729 return BTF_EVNT_MAX;
8730 case BTF_EVNT_BT_QUERY_TXPWR:
8731 if (ver->fwc2hfunc == 3)
8732 return func;
8733 else
8734 return BTF_EVNT_MAX;
8735 case BTF_EVNT_MAX:
8736 default:
8737 return BTF_EVNT_MAX;
8738 }
8739 }
8740
rtw89_btc_c2h_handle(struct rtw89_dev * rtwdev,struct sk_buff * skb,u32 len,u8 class,u8 func)8741 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
8742 u32 len, u8 class, u8 func)
8743 {
8744 struct rtw89_btc *btc = &rtwdev->btc;
8745 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
8746 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN];
8747
8748 len -= RTW89_C2H_HEADER_LEN;
8749
8750 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8751 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n",
8752 __func__, len, class, func);
8753
8754 if (class != BTFC_FW_EVENT)
8755 return;
8756
8757 func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func);
8758 pfwinfo->cnt_c2h++;
8759
8760 switch (func) {
8761 case BTF_EVNT_BUF_OVERFLOW:
8762 pfwinfo->event[func]++;
8763 break;
8764 case BTF_EVNT_RPT:
8765 pfwinfo->event[func]++;
8766 /* Don't need rtw89_leave_ps_mode() */
8767 btc_fw_event(rtwdev, func, buf, len);
8768 break;
8769 case BTF_EVNT_BT_INFO:
8770 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8771 "[BTC], handle C2H BT INFO with data %8ph\n", buf);
8772 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++;
8773 _update_bt_info(rtwdev, buf, len);
8774 break;
8775 case BTF_EVNT_BT_SCBD:
8776 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8777 "[BTC], handle C2H BT SCBD with data %8ph\n", buf);
8778 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++;
8779 _update_bt_scbd(rtwdev, false);
8780 break;
8781 case BTF_EVNT_BT_PSD:
8782 break;
8783 case BTF_EVNT_BT_REG:
8784 btc->dbg.rb_done = true;
8785 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf));
8786
8787 break;
8788 case BTF_EVNT_C2H_LOOPBACK:
8789 btc->dbg.rb_done = true;
8790 btc->dbg.rb_val = buf[0];
8791 break;
8792 case BTF_EVNT_CX_RUNINFO:
8793 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
8794 break;
8795 case BTF_EVNT_BT_QUERY_TXPWR:
8796 btc->cx.cnt_bt[BTC_BCNT_BTTXPWR_UPDATE]++;
8797 _update_bt_txpwr_info(rtwdev, buf, len);
8798 }
8799 }
8800
8801 #define BTC_CX_FW_OFFLOAD 0
8802
_show_cx_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)8803 static int _show_cx_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
8804 {
8805 union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo;
8806 const struct rtw89_chip_info *chip = rtwdev->chip;
8807 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
8808 struct rtw89_hal *hal = &rtwdev->hal;
8809 struct rtw89_btc *btc = &rtwdev->btc;
8810 struct rtw89_btc_dm *dm = &btc->dm;
8811 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
8812 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8813 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
8814 u8 cv, rfe, iso, ant_num, ant_single_pos;
8815 char *p = buf, *end = buf + bufsz;
8816
8817 if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
8818 return 0;
8819
8820 p += scnprintf(p, end - p,
8821 "\n========== [BTC COEX INFO (%s)] ==========\n",
8822 chip_id_str(chip->chip_id));
8823
8824 ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION);
8825 ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION);
8826 ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION);
8827 id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION);
8828 p += scnprintf(p, end - p, " %-15s : Coex:%d.%d.%d(branch:%d), ",
8829 "[coex_version]", ver_main, ver_sub, ver_hotfix,
8830 id_branch);
8831
8832 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
8833 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex);
8834 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex);
8835 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex);
8836 p += scnprintf(p, end - p, "WL_FW_coex:%d.%d.%d(branch:%d)",
8837 ver_main, ver_sub, ver_hotfix, id_branch);
8838
8839 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired);
8840 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired);
8841 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
8842 p += scnprintf(p, end - p, "(%s, desired:%d.%d.%d), ",
8843 (wl->ver_info.fw_coex >= chip->wlcx_desired ?
8844 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
8845
8846 p += scnprintf(p, end - p, "BT_FW_coex:%d(%s, desired:%d)\n",
8847 bt->ver_info.fw_coex,
8848 (bt->ver_info.fw_coex >= ver->bt_desired ?
8849 "Match" : "Mismatch"), ver->bt_desired);
8850
8851 if (bt->enable.now && bt->ver_info.fw == 0)
8852 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true);
8853 else
8854 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false);
8855
8856 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw);
8857 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw);
8858 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw);
8859 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw);
8860 p += scnprintf(p, end - p,
8861 " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n",
8862 "[sub_module]",
8863 ver_main, ver_sub, ver_hotfix, id_branch,
8864 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM");
8865
8866 if (ver->fcxinit == 7) {
8867 cv = md->md_v7.kt_ver;
8868 rfe = md->md_v7.rfe_type;
8869 iso = md->md_v7.ant.isolation;
8870 ant_num = md->md_v7.ant.num;
8871 ant_single_pos = md->md_v7.ant.single_pos;
8872 } else {
8873 cv = md->md.cv;
8874 rfe = md->md.rfe_type;
8875 iso = md->md.ant.isolation;
8876 ant_num = md->md.ant.num;
8877 ant_single_pos = md->md.ant.single_pos;
8878 }
8879
8880 p += scnprintf(p, end - p,
8881 " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s",
8882 "[hw_info]", cv, rfe, iso, ant_num,
8883 ant_num > 1 ? "" :
8884 ant_single_pos ? "1Ant_Pos:S1, " : "1Ant_Pos:S0, ");
8885
8886 p += scnprintf(p, end - p,
8887 "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n",
8888 btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss,
8889 hal->rx_nss);
8890
8891 return p - buf;
8892 }
8893
_show_wl_role_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)8894 static int _show_wl_role_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
8895 {
8896 struct rtw89_btc *btc = &rtwdev->btc;
8897 struct rtw89_btc_wl_link_info *plink = NULL;
8898 struct rtw89_traffic_stats *t;
8899 char *p = buf, *end = buf + bufsz;
8900 u8 i, j;
8901
8902 for (i = 0; i < btc->ver->max_role_num; i++) {
8903 for (j = 0; j < RTW89_MAC_NUM; j++) {
8904 if (btc->ver->fwlrole == 8)
8905 plink = &btc->cx.wl.rlink_info[i][j];
8906 else
8907 plink = &btc->cx.wl.link_info[i];
8908
8909 if (!plink->active)
8910 continue;
8911
8912 p += scnprintf(p, end - p,
8913 " [port_%d] : role=%d(phy-%d), connect=%s(client_cnt=%d), mode=%d, center_ch=%d, bw=%d",
8914 plink->pid, plink->role, plink->phy,
8915 id_to_mlme_state(plink->connected),
8916 plink->client_cnt - 1, plink->mode,
8917 plink->ch, plink->bw);
8918
8919 if (plink->connected == MLME_NO_LINK)
8920 continue;
8921
8922 p += scnprintf(p, end - p,
8923 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n",
8924 plink->mac_id, plink->tx_time, plink->tx_retry);
8925
8926 p += scnprintf(p, end - p,
8927 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
8928 plink->pid, 110 - plink->stat.rssi,
8929 plink->stat.rssi, plink->busy,
8930 plink->dir == RTW89_TFC_UL ? "UL" : "DL");
8931
8932 t = &plink->stat.traffic;
8933
8934 p += scnprintf(p, end - p,
8935 "tx[rate:%d/busy_level:%d], ",
8936 t->tx_rate, t->tx_tfc_lv);
8937
8938 p += scnprintf(p, end - p,
8939 "rx[rate:%d/busy_level:%d/drop:%d]\n",
8940 t->rx_rate,
8941 t->rx_tfc_lv, plink->rx_rate_drop_cnt);
8942 }
8943 }
8944 return p - buf;
8945 }
8946
_show_wl_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)8947 static int _show_wl_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
8948 {
8949 struct rtw89_btc *btc = &rtwdev->btc;
8950 const struct rtw89_btc_ver *ver = btc->ver;
8951 struct rtw89_btc_cx *cx = &btc->cx;
8952 struct rtw89_btc_wl_info *wl = &cx->wl;
8953 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
8954 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
8955 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
8956 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
8957 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
8958 char *p = buf, *end = buf + bufsz;
8959 u8 mode;
8960
8961 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
8962 return 0;
8963
8964 p += scnprintf(p, end - p, "========== [WL Status] ==========\n");
8965
8966 if (ver->fwlrole == 0)
8967 mode = wl_rinfo->link_mode;
8968 else if (ver->fwlrole == 1)
8969 mode = wl_rinfo_v1->link_mode;
8970 else if (ver->fwlrole == 2)
8971 mode = wl_rinfo_v2->link_mode;
8972 else if (ver->fwlrole == 7)
8973 mode = wl_rinfo_v7->link_mode;
8974 else if (ver->fwlrole == 8)
8975 mode = wl_rinfo_v8->link_mode;
8976 else
8977 goto out;
8978
8979 p += scnprintf(p, end - p, " %-15s : link_mode:%s, ", "[status]",
8980 id_to_linkmode(mode));
8981
8982 p += scnprintf(p, end - p,
8983 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ",
8984 wl->status.map.rf_off, wl->status.map.lps,
8985 wl->status.map.scan ? "Y" : "N",
8986 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
8987
8988 p += scnprintf(p, end - p,
8989 "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n",
8990 wl->status.map.connecting ? "Y" : "N",
8991 wl->status.map.roaming ? "Y" : "N",
8992 wl->status.map._4way ? "Y" : "N",
8993 wl->status.map.init_ok ? "Y" : "N");
8994
8995 p += _show_wl_role_info(rtwdev, p, end - p);
8996
8997 out:
8998 return p - buf;
8999 }
9000
9001 enum btc_bt_a2dp_type {
9002 BTC_A2DP_LEGACY = 0,
9003 BTC_A2DP_TWS_SNIFF = 1,
9004 BTC_A2DP_TWS_RELAY = 2,
9005 };
9006
_show_bt_profile_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9007 static int _show_bt_profile_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9008 {
9009 struct rtw89_btc *btc = &rtwdev->btc;
9010 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
9011 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
9012 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
9013 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
9014 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
9015 char *p = buf, *end = buf + bufsz;
9016
9017 if (hfp.exist) {
9018 p += scnprintf(p, end - p,
9019 " %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
9020 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"),
9021 bt_linfo->sut_pwr_level[0],
9022 bt_linfo->golden_rx_shift[0]);
9023 }
9024
9025 if (hid.exist) {
9026 p += scnprintf(p, end - p,
9027 "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n",
9028 "[HID]",
9029 hid.type & BTC_HID_218 ? "2/18," : "",
9030 hid.type & BTC_HID_418 ? "4/18," : "",
9031 hid.type & BTC_HID_BLE ? "BLE," : "",
9032 hid.type & BTC_HID_RCU ? "RCU," : "",
9033 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "",
9034 hid.pair_cnt, bt_linfo->sut_pwr_level[1],
9035 bt_linfo->golden_rx_shift[1]);
9036 }
9037
9038 if (a2dp.exist) {
9039 p += scnprintf(p, end - p,
9040 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
9041 "[A2DP]",
9042 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS",
9043 a2dp.bitpool, a2dp.flush_time);
9044
9045 p += scnprintf(p, end - p,
9046 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n",
9047 a2dp.vendor_id, a2dp.device_name,
9048 bt_linfo->sut_pwr_level[2],
9049 bt_linfo->golden_rx_shift[2]);
9050 }
9051
9052 if (pan.exist) {
9053 p += scnprintf(p, end - p,
9054 " %-15s : sut_pwr:%d, golden-rx:%d\n",
9055 "[PAN]",
9056 bt_linfo->sut_pwr_level[3],
9057 bt_linfo->golden_rx_shift[3]);
9058 }
9059
9060 return p - buf;
9061 }
9062
_show_bt_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9063 static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9064 {
9065 struct rtw89_btc *btc = &rtwdev->btc;
9066 const struct rtw89_btc_ver *ver = btc->ver;
9067 struct rtw89_btc_cx *cx = &btc->cx;
9068 struct rtw89_btc_bt_info *bt = &cx->bt;
9069 struct rtw89_btc_wl_info *wl = &cx->wl;
9070 u32 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
9071 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
9072 union rtw89_btc_module_info *md = &btc->mdinfo;
9073 s8 br_dbm = bt->link_info.bt_txpwr_desc.br_dbm;
9074 s8 le_dbm = bt->link_info.bt_txpwr_desc.le_dbm;
9075 char *p = buf, *end = buf + bufsz;
9076 u8 *afh = bt_linfo->afh_map;
9077 u8 *afh_le = bt_linfo->afh_map_le;
9078 u8 bt_pos;
9079
9080 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
9081 return 0;
9082
9083 if (ver->fcxinit == 7)
9084 bt_pos = md->md_v7.bt_pos;
9085 else
9086 bt_pos = md->md.bt_pos;
9087
9088 p += scnprintf(p, end - p, "========== [BT Status] ==========\n");
9089
9090 p += scnprintf(p, end - p,
9091 " %-15s : enable:%s, btg:%s%s, connect:%s, ",
9092 "[status]", bt->enable.now ? "Y" : "N",
9093 bt->btg_type ? "Y" : "N",
9094 (bt->enable.now && (bt->btg_type != bt_pos) ?
9095 "(efuse-mismatch!!)" : ""),
9096 (bt_linfo->status.map.connect ? "Y" : "N"));
9097
9098 p += scnprintf(p, end - p,
9099 "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n",
9100 bt->igno_wl ? "Y" : "N",
9101 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val);
9102
9103 p += scnprintf(p, end - p, " %-15s : profile:%s%s%s%s%s ",
9104 "[profile]",
9105 (bt_linfo->profile_cnt.now == 0) ? "None," : "",
9106 bt_linfo->hfp_desc.exist ? "HFP," : "",
9107 bt_linfo->hid_desc.exist ? "HID," : "",
9108 bt_linfo->a2dp_desc.exist ?
9109 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "",
9110 bt_linfo->pan_desc.exist ? "PAN," : "");
9111
9112 p += scnprintf(p, end - p,
9113 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n",
9114 bt_linfo->multi_link.now ? "Y" : "N",
9115 bt_linfo->slave_role ? "Slave" : "Master",
9116 bt_linfo->status.map.ble_connect ? "Y" : "N",
9117 bt_linfo->cqddr ? "Y" : "N",
9118 bt_linfo->a2dp_desc.active ? "Y" : "N",
9119 bt_linfo->pan_desc.active ? "Y" : "N");
9120
9121 p += scnprintf(p, end - p,
9122 " %-15s : rssi:%ddBm(lvl:%d), tx_rate:%dM, %s%s%s",
9123 "[link]", bt_linfo->rssi - 100,
9124 bt->rssi_level,
9125 bt_linfo->tx_3m ? 3 : 2,
9126 bt_linfo->status.map.inq_pag ? " inq-page!!" : "",
9127 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "",
9128 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : "");
9129
9130 p += scnprintf(p, end - p,
9131 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
9132 bt_linfo->relink.now ? " ReLink!!" : "",
9133 afh[0], afh[1], afh[2], afh[3], afh[4],
9134 afh[5], afh[6], afh[7], afh[8], afh[9]);
9135
9136 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
9137 p += scnprintf(p, end - p,
9138 "LE[%02x%02x_%02x_%02x%02x]",
9139 afh_le[0], afh_le[1], afh_le[2],
9140 afh_le[3], afh_le[4]);
9141
9142 p += scnprintf(p, end - p, "wl_ch_map[en:%d/ch:%d/bw:%d]\n",
9143 wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw);
9144
9145 p += scnprintf(p, end - p,
9146 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
9147 "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY],
9148 cx->cnt_bt[BTC_BCNT_RELINK],
9149 cx->cnt_bt[BTC_BCNT_RATECHG],
9150 cx->cnt_bt[BTC_BCNT_REINIT],
9151 cx->cnt_bt[BTC_BCNT_REENABLE]);
9152
9153 p += scnprintf(p, end - p,
9154 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n",
9155 cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH],
9156 cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ],
9157 cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]);
9158
9159 p += _show_bt_profile_info(rtwdev, p, end - p);
9160
9161 p += scnprintf(p, end - p,
9162 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n",
9163 "[bt_info]", bt->raw_info[2], bt->raw_info[3],
9164 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6],
9165 bt->raw_info[7],
9166 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
9167 cx->cnt_bt[BTC_BCNT_INFOUPDATE],
9168 cx->cnt_bt[BTC_BCNT_INFOSAME]);
9169
9170 p += scnprintf(p, end - p,
9171 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)",
9172 "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX],
9173 cx->cnt_bt[BTC_BCNT_HIPRI_TX],
9174 cx->cnt_bt[BTC_BCNT_LOPRI_RX],
9175 cx->cnt_bt[BTC_BCNT_LOPRI_TX],
9176 cx->cnt_bt[BTC_BCNT_POLUT]);
9177
9178 if (!bt->scan_info_update) {
9179 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, true);
9180 p += scnprintf(p, end - p, "\n");
9181 } else {
9182 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, false);
9183 if (ver->fcxbtscan == 1) {
9184 p += scnprintf(p, end - p,
9185 "(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)",
9186 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win),
9187 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl),
9188 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win),
9189 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl),
9190 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win),
9191 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl),
9192 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win),
9193 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl));
9194 } else if (ver->fcxbtscan == 2) {
9195 p += scnprintf(p, end - p,
9196 "(BG:%d-%d/INIT:%d-%d/LE:%d-%d)",
9197 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win),
9198 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl),
9199 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win),
9200 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl),
9201 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win),
9202 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl));
9203 }
9204 p += scnprintf(p, end - p, "\n");
9205 }
9206
9207 if (ver_main >= 9 && bt_linfo->profile_cnt.now)
9208 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_TX_PWR_LVL, true);
9209 else
9210 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_TX_PWR_LVL, false);
9211
9212 if (cx->cnt_bt[BTC_BCNT_BTTXPWR_UPDATE]) {
9213 p += scnprintf(p, end - p,
9214 " %-15s : br_index:0x%x, le_index:0x%x",
9215 "[bt_txpwr_lvl]",
9216 bt->link_info.bt_txpwr_desc.br_gain_index,
9217 bt->link_info.bt_txpwr_desc.le_gain_index);
9218 p += scnprintf(p, end - p, ", br_dbm:%d dBm", br_dbm);
9219 p += scnprintf(p, end - p, ", le_dbm:%d dBm", le_dbm);
9220 } else {
9221 p += scnprintf(p, end - p,
9222 " %-15s : br_index:NA, le_index:NA, br_dbm:%d dBm[def], le_dbm:%d dBm[def]",
9223 "[bt_txpwr_lvl]",
9224 bt->link_info.bt_txpwr_desc.br_dbm,
9225 bt->link_info.bt_txpwr_desc.le_dbm);
9226 }
9227 p += scnprintf(p, end - p, "\n");
9228
9229 if (bt_linfo->profile_cnt.now || bt_linfo->status.map.ble_connect)
9230 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, true);
9231 else
9232 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, false);
9233
9234 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
9235 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, true);
9236 else
9237 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, false);
9238
9239 if (bt_linfo->a2dp_desc.exist &&
9240 (bt_linfo->a2dp_desc.flush_time == 0 ||
9241 bt_linfo->a2dp_desc.vendor_id == 0 ||
9242 bt_linfo->a2dp_desc.play_latency == 1))
9243 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, true);
9244 else
9245 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, false);
9246
9247 return p - buf;
9248 }
9249
9250 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e
9251 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
9252 #define CASE_BTC_POLICY_STR(e) \
9253 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
9254 #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e
9255 #define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e
9256 #define CASE_BTC_INIT(e) case BTC_MODE_## e: return #e
9257 #define CASE_BTC_ANTPATH_STR(e) case BTC_ANT_##e: return #e
9258 #define CASE_BTC_POLUT_STR(e) case BTC_PLT_## e: return #e
9259 #define CASE_BTC_REGTYPE_STR(e) case REG_## e: return #e
9260 #define CASE_BTC_GDBG_STR(e) case BTC_DBG_## e: return #e
9261
id_to_polut(u32 id)9262 static const char *id_to_polut(u32 id)
9263 {
9264 switch (id) {
9265 CASE_BTC_POLUT_STR(NONE);
9266 CASE_BTC_POLUT_STR(GNT_BT_TX);
9267 CASE_BTC_POLUT_STR(GNT_BT_RX);
9268 CASE_BTC_POLUT_STR(GNT_WL);
9269 CASE_BTC_POLUT_STR(BT);
9270 CASE_BTC_POLUT_STR(ALL);
9271 default:
9272 return "unknown";
9273 }
9274 }
9275
id_to_regtype(u32 id)9276 static const char *id_to_regtype(u32 id)
9277 {
9278 switch (id) {
9279 CASE_BTC_REGTYPE_STR(MAC);
9280 CASE_BTC_REGTYPE_STR(BB);
9281 CASE_BTC_REGTYPE_STR(RF);
9282 CASE_BTC_REGTYPE_STR(BT_RF);
9283 CASE_BTC_REGTYPE_STR(BT_MODEM);
9284 CASE_BTC_REGTYPE_STR(BT_BLUEWIZE);
9285 CASE_BTC_REGTYPE_STR(BT_VENDOR);
9286 CASE_BTC_REGTYPE_STR(BT_LE);
9287 default:
9288 return "unknown";
9289 }
9290 }
9291
id_to_gdbg(u32 id)9292 static const char *id_to_gdbg(u32 id)
9293 {
9294 switch (id) {
9295 CASE_BTC_GDBG_STR(GNT_BT);
9296 CASE_BTC_GDBG_STR(GNT_WL);
9297 CASE_BTC_GDBG_STR(BCN_EARLY);
9298 CASE_BTC_GDBG_STR(WL_NULL0);
9299 CASE_BTC_GDBG_STR(WL_NULL1);
9300 CASE_BTC_GDBG_STR(WL_RXISR);
9301 CASE_BTC_GDBG_STR(TDMA_ENTRY);
9302 CASE_BTC_GDBG_STR(A2DP_EMPTY);
9303 CASE_BTC_GDBG_STR(BT_RETRY);
9304 CASE_BTC_GDBG_STR(BT_RELINK);
9305 CASE_BTC_GDBG_STR(SLOT_WL);
9306 CASE_BTC_GDBG_STR(SLOT_BT);
9307 CASE_BTC_GDBG_STR(WL_ERR);
9308 CASE_BTC_GDBG_STR(WL_OK);
9309 CASE_BTC_GDBG_STR(SLOT_B2W);
9310 CASE_BTC_GDBG_STR(SLOT_W1);
9311 CASE_BTC_GDBG_STR(SLOT_W2);
9312 CASE_BTC_GDBG_STR(SLOT_W2B);
9313 CASE_BTC_GDBG_STR(SLOT_B1);
9314 CASE_BTC_GDBG_STR(SLOT_B2);
9315 CASE_BTC_GDBG_STR(SLOT_B3);
9316 CASE_BTC_GDBG_STR(SLOT_B4);
9317 CASE_BTC_GDBG_STR(SLOT_LK);
9318 CASE_BTC_GDBG_STR(SLOT_E2G);
9319 CASE_BTC_GDBG_STR(SLOT_E5G);
9320 CASE_BTC_GDBG_STR(SLOT_EBT);
9321 CASE_BTC_GDBG_STR(SLOT_WLK);
9322 CASE_BTC_GDBG_STR(SLOT_B1FDD);
9323 CASE_BTC_GDBG_STR(BT_CHANGE);
9324 CASE_BTC_GDBG_STR(WL_CCA);
9325 CASE_BTC_GDBG_STR(BT_LEAUDIO);
9326 CASE_BTC_GDBG_STR(USER_DEF);
9327 default:
9328 return "unknown";
9329 }
9330 }
9331
steps_to_str(u16 step)9332 static const char *steps_to_str(u16 step)
9333 {
9334 switch (step) {
9335 CASE_BTC_RSN_STR(NONE);
9336 CASE_BTC_RSN_STR(NTFY_INIT);
9337 CASE_BTC_RSN_STR(NTFY_SWBAND);
9338 CASE_BTC_RSN_STR(NTFY_WL_STA);
9339 CASE_BTC_RSN_STR(NTFY_RADIO_STATE);
9340 CASE_BTC_RSN_STR(UPDATE_BT_SCBD);
9341 CASE_BTC_RSN_STR(NTFY_WL_RFK);
9342 CASE_BTC_RSN_STR(UPDATE_BT_INFO);
9343 CASE_BTC_RSN_STR(NTFY_SCAN_START);
9344 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH);
9345 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET);
9346 CASE_BTC_RSN_STR(NTFY_POWEROFF);
9347 CASE_BTC_RSN_STR(NTFY_ROLE_INFO);
9348 CASE_BTC_RSN_STR(CMD_SET_COEX);
9349 CASE_BTC_RSN_STR(ACT1_WORK);
9350 CASE_BTC_RSN_STR(BT_DEVINFO_WORK);
9351 CASE_BTC_RSN_STR(RFK_CHK_WORK);
9352
9353 CASE_BTC_ACT_STR(NONE);
9354 CASE_BTC_ACT_STR(WL_ONLY);
9355 CASE_BTC_ACT_STR(WL_5G);
9356 CASE_BTC_ACT_STR(WL_OTHER);
9357 CASE_BTC_ACT_STR(WL_IDLE);
9358 CASE_BTC_ACT_STR(WL_NC);
9359 CASE_BTC_ACT_STR(WL_RFK);
9360 CASE_BTC_ACT_STR(WL_INIT);
9361 CASE_BTC_ACT_STR(WL_OFF);
9362 CASE_BTC_ACT_STR(FREERUN);
9363 CASE_BTC_ACT_STR(BT_WHQL);
9364 CASE_BTC_ACT_STR(BT_RFK);
9365 CASE_BTC_ACT_STR(BT_OFF);
9366 CASE_BTC_ACT_STR(BT_IDLE);
9367 CASE_BTC_ACT_STR(BT_HFP);
9368 CASE_BTC_ACT_STR(BT_HID);
9369 CASE_BTC_ACT_STR(BT_A2DP);
9370 CASE_BTC_ACT_STR(BT_A2DPSINK);
9371 CASE_BTC_ACT_STR(BT_PAN);
9372 CASE_BTC_ACT_STR(BT_A2DP_HID);
9373 CASE_BTC_ACT_STR(BT_A2DP_PAN);
9374 CASE_BTC_ACT_STR(BT_PAN_HID);
9375 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID);
9376 CASE_BTC_ACT_STR(WL_25G_MCC);
9377 CASE_BTC_ACT_STR(WL_2G_MCC);
9378 CASE_BTC_ACT_STR(WL_2G_SCC);
9379 CASE_BTC_ACT_STR(WL_2G_AP);
9380 CASE_BTC_ACT_STR(WL_2G_GO);
9381 CASE_BTC_ACT_STR(WL_2G_GC);
9382 CASE_BTC_ACT_STR(WL_2G_NAN);
9383
9384 CASE_BTC_POLICY_STR(OFF_BT);
9385 CASE_BTC_POLICY_STR(OFF_WL);
9386 CASE_BTC_POLICY_STR(OFF_EQ0);
9387 CASE_BTC_POLICY_STR(OFF_EQ1);
9388 CASE_BTC_POLICY_STR(OFF_EQ2);
9389 CASE_BTC_POLICY_STR(OFF_EQ3);
9390 CASE_BTC_POLICY_STR(OFF_EQ4);
9391 CASE_BTC_POLICY_STR(OFF_EQ5);
9392 CASE_BTC_POLICY_STR(OFF_BWB0);
9393 CASE_BTC_POLICY_STR(OFF_BWB1);
9394 CASE_BTC_POLICY_STR(OFF_BWB2);
9395 CASE_BTC_POLICY_STR(OFF_BWB3);
9396 CASE_BTC_POLICY_STR(OFF_WL2);
9397 CASE_BTC_POLICY_STR(OFFB_BWB0);
9398 CASE_BTC_POLICY_STR(OFFE_DEF);
9399 CASE_BTC_POLICY_STR(OFFE_DEF2);
9400 CASE_BTC_POLICY_STR(OFFE_2GBWISOB);
9401 CASE_BTC_POLICY_STR(OFFE_2GISOB);
9402 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB);
9403 CASE_BTC_POLICY_STR(OFFE_WL);
9404 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2);
9405 CASE_BTC_POLICY_STR(FIX_TD3030);
9406 CASE_BTC_POLICY_STR(FIX_TD5050);
9407 CASE_BTC_POLICY_STR(FIX_TD2030);
9408 CASE_BTC_POLICY_STR(FIX_TD4010);
9409 CASE_BTC_POLICY_STR(FIX_TD7010);
9410 CASE_BTC_POLICY_STR(FIX_TD2060);
9411 CASE_BTC_POLICY_STR(FIX_TD3060);
9412 CASE_BTC_POLICY_STR(FIX_TD2080);
9413 CASE_BTC_POLICY_STR(FIX_TDW1B1);
9414 CASE_BTC_POLICY_STR(FIX_TD4010ISO);
9415 CASE_BTC_POLICY_STR(FIX_TD4010ISO_DL);
9416 CASE_BTC_POLICY_STR(FIX_TD4010ISO_UL);
9417 CASE_BTC_POLICY_STR(PFIX_TD3030);
9418 CASE_BTC_POLICY_STR(PFIX_TD5050);
9419 CASE_BTC_POLICY_STR(PFIX_TD2030);
9420 CASE_BTC_POLICY_STR(PFIX_TD2060);
9421 CASE_BTC_POLICY_STR(PFIX_TD3070);
9422 CASE_BTC_POLICY_STR(PFIX_TD2080);
9423 CASE_BTC_POLICY_STR(PFIX_TDW1B1);
9424 CASE_BTC_POLICY_STR(AUTO_TD50B1);
9425 CASE_BTC_POLICY_STR(AUTO_TD60B1);
9426 CASE_BTC_POLICY_STR(AUTO_TD20B1);
9427 CASE_BTC_POLICY_STR(AUTO_TDW1B1);
9428 CASE_BTC_POLICY_STR(PAUTO_TD50B1);
9429 CASE_BTC_POLICY_STR(PAUTO_TD60B1);
9430 CASE_BTC_POLICY_STR(PAUTO_TD20B1);
9431 CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
9432 CASE_BTC_POLICY_STR(AUTO2_TD3050);
9433 CASE_BTC_POLICY_STR(AUTO2_TD3070);
9434 CASE_BTC_POLICY_STR(AUTO2_TD5050);
9435 CASE_BTC_POLICY_STR(AUTO2_TD6060);
9436 CASE_BTC_POLICY_STR(AUTO2_TD2080);
9437 CASE_BTC_POLICY_STR(AUTO2_TDW1B4);
9438 CASE_BTC_POLICY_STR(PAUTO2_TD3050);
9439 CASE_BTC_POLICY_STR(PAUTO2_TD3070);
9440 CASE_BTC_POLICY_STR(PAUTO2_TD5050);
9441 CASE_BTC_POLICY_STR(PAUTO2_TD6060);
9442 CASE_BTC_POLICY_STR(PAUTO2_TD2080);
9443 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4);
9444 default:
9445 return "unknown step";
9446 }
9447 }
9448
id_to_slot(u32 id)9449 static const char *id_to_slot(u32 id)
9450 {
9451 switch (id) {
9452 CASE_BTC_SLOT_STR(OFF);
9453 CASE_BTC_SLOT_STR(B2W);
9454 CASE_BTC_SLOT_STR(W1);
9455 CASE_BTC_SLOT_STR(W2);
9456 CASE_BTC_SLOT_STR(W2B);
9457 CASE_BTC_SLOT_STR(B1);
9458 CASE_BTC_SLOT_STR(B2);
9459 CASE_BTC_SLOT_STR(B3);
9460 CASE_BTC_SLOT_STR(B4);
9461 CASE_BTC_SLOT_STR(LK);
9462 CASE_BTC_SLOT_STR(BLK);
9463 CASE_BTC_SLOT_STR(E2G);
9464 CASE_BTC_SLOT_STR(E5G);
9465 CASE_BTC_SLOT_STR(EBT);
9466 CASE_BTC_SLOT_STR(ENULL);
9467 CASE_BTC_SLOT_STR(WLK);
9468 CASE_BTC_SLOT_STR(W1FDD);
9469 CASE_BTC_SLOT_STR(B1FDD);
9470 default:
9471 return "unknown";
9472 }
9473 }
9474
id_to_evt(u32 id)9475 static const char *id_to_evt(u32 id)
9476 {
9477 switch (id) {
9478 CASE_BTC_EVT_STR(TDMA_ENTRY);
9479 CASE_BTC_EVT_STR(WL_TMR);
9480 CASE_BTC_EVT_STR(B1_TMR);
9481 CASE_BTC_EVT_STR(B2_TMR);
9482 CASE_BTC_EVT_STR(B3_TMR);
9483 CASE_BTC_EVT_STR(B4_TMR);
9484 CASE_BTC_EVT_STR(W2B_TMR);
9485 CASE_BTC_EVT_STR(B2W_TMR);
9486 CASE_BTC_EVT_STR(BCN_EARLY);
9487 CASE_BTC_EVT_STR(A2DP_EMPTY);
9488 CASE_BTC_EVT_STR(LK_END);
9489 CASE_BTC_EVT_STR(RX_ISR);
9490 CASE_BTC_EVT_STR(RX_FC0);
9491 CASE_BTC_EVT_STR(RX_FC1);
9492 CASE_BTC_EVT_STR(BT_RELINK);
9493 CASE_BTC_EVT_STR(BT_RETRY);
9494 CASE_BTC_EVT_STR(E2G);
9495 CASE_BTC_EVT_STR(E5G);
9496 CASE_BTC_EVT_STR(EBT);
9497 CASE_BTC_EVT_STR(ENULL);
9498 CASE_BTC_EVT_STR(DRV_WLK);
9499 CASE_BTC_EVT_STR(BCN_OK);
9500 CASE_BTC_EVT_STR(BT_CHANGE);
9501 CASE_BTC_EVT_STR(EBT_EXTEND);
9502 CASE_BTC_EVT_STR(E2G_NULL1);
9503 CASE_BTC_EVT_STR(B1FDD_TMR);
9504 default:
9505 return "unknown";
9506 }
9507 }
9508
id_to_mode(u8 id)9509 static const char *id_to_mode(u8 id)
9510 {
9511 switch (id) {
9512 CASE_BTC_INIT(NORMAL);
9513 CASE_BTC_INIT(WL);
9514 CASE_BTC_INIT(BT);
9515 CASE_BTC_INIT(WLOFF);
9516 default:
9517 return "unknown";
9518 }
9519 }
9520
id_to_ant(u32 id)9521 static const char *id_to_ant(u32 id)
9522 {
9523 switch (id) {
9524 CASE_BTC_ANTPATH_STR(WPOWERON);
9525 CASE_BTC_ANTPATH_STR(WINIT);
9526 CASE_BTC_ANTPATH_STR(WONLY);
9527 CASE_BTC_ANTPATH_STR(WOFF);
9528 CASE_BTC_ANTPATH_STR(W2G);
9529 CASE_BTC_ANTPATH_STR(W5G);
9530 CASE_BTC_ANTPATH_STR(W25G);
9531 CASE_BTC_ANTPATH_STR(FREERUN);
9532 CASE_BTC_ANTPATH_STR(WRFK);
9533 CASE_BTC_ANTPATH_STR(BRFK);
9534 CASE_BTC_ANTPATH_STR(MAX);
9535 default:
9536 return "unknown";
9537 }
9538 }
9539
9540 static
scnprintf_segment(char * buf,size_t bufsz,const char * prefix,const u16 * data,u8 len,u8 seg_len,u8 start_idx,u8 ring_len)9541 int scnprintf_segment(char *buf, size_t bufsz, const char *prefix, const u16 *data,
9542 u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
9543 {
9544 char *p = buf, *end = buf + bufsz;
9545 u8 cur_index;
9546 u8 i;
9547
9548 for (i = 0; i < len ; i++) {
9549 if ((i % seg_len) == 0)
9550 p += scnprintf(p, end - p, " %-15s : ", prefix);
9551 cur_index = (start_idx + i) % ring_len;
9552 if (i % 3 == 0)
9553 p += scnprintf(p, end - p, "-> %-20s",
9554 steps_to_str(*(data + cur_index)));
9555 else if (i % 3 == 1)
9556 p += scnprintf(p, end - p, "-> %-15s",
9557 steps_to_str(*(data + cur_index)));
9558 else
9559 p += scnprintf(p, end - p, "-> %-13s",
9560 steps_to_str(*(data + cur_index)));
9561 if (i == (len - 1) || (i % seg_len) == (seg_len - 1))
9562 p += scnprintf(p, end - p, "\n");
9563 }
9564
9565 return p - buf;
9566 }
9567
_show_dm_step(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9568 static int _show_dm_step(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9569 {
9570 struct rtw89_btc *btc = &rtwdev->btc;
9571 struct rtw89_btc_dm *dm = &btc->dm;
9572 char *p = buf, *end = buf + bufsz;
9573 u8 start_idx;
9574 u8 len;
9575
9576 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos;
9577 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0;
9578
9579 p += scnprintf_segment(p, end - p, "[dm_steps]", dm->dm_step.step, len,
9580 6, start_idx, ARRAY_SIZE(dm->dm_step.step));
9581
9582 return p - buf;
9583 }
9584
_show_dm_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9585 static int _show_dm_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9586 {
9587 struct rtw89_btc *btc = &rtwdev->btc;
9588 const struct rtw89_btc_ver *ver = btc->ver;
9589 struct rtw89_btc_dm *dm = &btc->dm;
9590 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9591 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
9592 char *p = buf, *end = buf + bufsz;
9593 u8 igno_bt;
9594
9595 if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
9596 return 0;
9597
9598 p += scnprintf(p, end - p,
9599 "========== [Mechanism Status %s] ==========\n",
9600 (btc->manual_ctrl ? "(Manual)" : "(Auto)"));
9601
9602 p += scnprintf(p, end - p,
9603 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, init_mode:%s, run_cnt:%d\n",
9604 "[status]",
9605 btc->ant_type == BTC_ANT_SHARED ? "shared" : "dedicated",
9606 steps_to_str(dm->run_reason),
9607 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT),
9608 id_to_ant(FIELD_GET(GENMASK(7, 0), dm->set_ant_path)),
9609 id_to_mode(wl->coex_mode),
9610 dm->cnt_dm[BTC_DCNT_RUN]);
9611
9612 p += _show_dm_step(rtwdev, p, end - p);
9613
9614 if (ver->fcxctrl == 7)
9615 igno_bt = btc->ctrl.ctrl_v7.igno_bt;
9616 else
9617 igno_bt = btc->ctrl.ctrl.igno_bt;
9618
9619 p += scnprintf(p, end - p,
9620 " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ",
9621 "[dm_flag]", dm->wl_only, dm->bt_only, igno_bt,
9622 dm->freerun, btc->lps, dm->wl_mimo_ps);
9623
9624 p += scnprintf(p, end - p, "leak_ap:%d, fw_offload:%s%s\n",
9625 dm->leak_ap,
9626 (BTC_CX_FW_OFFLOAD ? "Y" : "N"),
9627 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
9628 "" : "(Mismatch!!)"));
9629
9630 if (dm->rf_trx_para.wl_tx_power == 0xff)
9631 p += scnprintf(p, end - p,
9632 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ",
9633 "[trx_ctrl]", wl->rssi_level,
9634 dm->trx_para_level);
9635
9636 else
9637 p += scnprintf(p, end - p,
9638 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ",
9639 "[trx_ctrl]", wl->rssi_level,
9640 dm->trx_para_level,
9641 dm->rf_trx_para.wl_tx_power);
9642
9643 p += scnprintf(p, end - p,
9644 "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n",
9645 dm->rf_trx_para.wl_rx_gain,
9646 dm->rf_trx_para.bt_tx_power,
9647 dm->rf_trx_para.bt_rx_gain,
9648 (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx);
9649
9650 p += scnprintf(p, end - p,
9651 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n",
9652 "[dm_ctrl]", dm->wl_tx_limit.enable,
9653 dm->wl_tx_limit.tx_time,
9654 dm->wl_tx_limit.tx_retry, btc->bt_req_len,
9655 bt->scan_rx_low_pri);
9656
9657 return p - buf;
9658 }
9659
_show_error(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9660 static int _show_error(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9661 {
9662 struct rtw89_btc *btc = &rtwdev->btc;
9663 const struct rtw89_btc_ver *ver = btc->ver;
9664 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9665 union rtw89_btc_fbtc_cysta_info *pcysta;
9666 char *p = buf, *end = buf + bufsz;
9667 u32 except_cnt, exception_map;
9668
9669 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
9670 if (ver->fcxcysta == 2) {
9671 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
9672 except_cnt = le32_to_cpu(pcysta->v2.except_cnt);
9673 exception_map = le32_to_cpu(pcysta->v2.exception);
9674 } else if (ver->fcxcysta == 3) {
9675 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
9676 except_cnt = le32_to_cpu(pcysta->v3.except_cnt);
9677 exception_map = le32_to_cpu(pcysta->v3.except_map);
9678 } else if (ver->fcxcysta == 4) {
9679 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
9680 except_cnt = pcysta->v4.except_cnt;
9681 exception_map = le32_to_cpu(pcysta->v4.except_map);
9682 } else if (ver->fcxcysta == 5) {
9683 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
9684 except_cnt = pcysta->v5.except_cnt;
9685 exception_map = le32_to_cpu(pcysta->v5.except_map);
9686 } else if (ver->fcxcysta == 7) {
9687 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
9688 except_cnt = pcysta->v7.except_cnt;
9689 exception_map = le32_to_cpu(pcysta->v7.except_map);
9690 } else {
9691 return 0;
9692 }
9693
9694 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 &&
9695 !pfwinfo->len_mismch && !pfwinfo->fver_mismch)
9696 return 0;
9697
9698 p += scnprintf(p, end - p, " %-15s : ", "[error]");
9699
9700 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
9701 p += scnprintf(p, end - p,
9702 "overflow-cnt: %d, ",
9703 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
9704 }
9705
9706 if (pfwinfo->len_mismch) {
9707 p += scnprintf(p, end - p,
9708 "len-mismatch: 0x%x, ",
9709 pfwinfo->len_mismch);
9710 }
9711
9712 if (pfwinfo->fver_mismch) {
9713 p += scnprintf(p, end - p,
9714 "fver-mismatch: 0x%x, ",
9715 pfwinfo->fver_mismch);
9716 }
9717
9718 /* cycle statistics exceptions */
9719 if (exception_map || except_cnt) {
9720 p += scnprintf(p, end - p,
9721 "exception-type: 0x%x, exception-cnt = %d",
9722 exception_map, except_cnt);
9723 }
9724 p += scnprintf(p, end - p, "\n");
9725
9726 return p - buf;
9727 }
9728
_show_fbtc_tdma(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9729 static int _show_fbtc_tdma(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9730 {
9731 struct rtw89_btc *btc = &rtwdev->btc;
9732 const struct rtw89_btc_ver *ver = btc->ver;
9733 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9734 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9735 struct rtw89_btc_fbtc_tdma *t = NULL;
9736 char *p = buf, *end = buf + bufsz;
9737
9738 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
9739 if (!pcinfo->valid)
9740 return 0;
9741
9742 if (ver->fcxtdma == 1)
9743 t = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
9744 else
9745 t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma;
9746
9747 p += scnprintf(p, end - p,
9748 " %-15s : ", "[tdma_policy]");
9749 p += scnprintf(p, end - p,
9750 "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ",
9751 (u32)t->type,
9752 t->rxflctrl, t->txpause);
9753
9754 p += scnprintf(p, end - p,
9755 "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ",
9756 t->wtgle_n, t->leak_n, t->ext_ctrl);
9757
9758 p += scnprintf(p, end - p,
9759 "policy_type:%d",
9760 (u32)btc->policy_type);
9761
9762 p += scnprintf(p, end - p, "\n");
9763
9764 return p - buf;
9765 }
9766
_show_fbtc_slots(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9767 static int _show_fbtc_slots(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9768 {
9769 struct rtw89_btc *btc = &rtwdev->btc;
9770 struct rtw89_btc_dm *dm = &btc->dm;
9771 char *p = buf, *end = buf + bufsz;
9772 u16 dur, cxtype;
9773 u32 tbl;
9774 u8 i = 0;
9775
9776 for (i = 0; i < CXST_MAX; i++) {
9777 if (btc->ver->fcxslots == 1) {
9778 dur = le16_to_cpu(dm->slot_now.v1[i].dur);
9779 tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl);
9780 cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype);
9781 } else if (btc->ver->fcxslots == 7) {
9782 dur = le16_to_cpu(dm->slot_now.v7[i].dur);
9783 tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl);
9784 cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype);
9785 } else {
9786 return 0;
9787 }
9788
9789 if (i % 5 == 0)
9790 p += scnprintf(p, end - p,
9791 " %-15s : %5s[%03d/0x%x/%d]",
9792 "[slot_list]",
9793 id_to_slot((u32)i),
9794 dur, tbl, cxtype);
9795 else
9796 p += scnprintf(p, end - p,
9797 ", %5s[%03d/0x%x/%d]",
9798 id_to_slot((u32)i),
9799 dur, tbl, cxtype);
9800
9801 if (i % 5 == 4)
9802 p += scnprintf(p, end - p, "\n");
9803 }
9804
9805 return p - buf;
9806 }
9807
_show_fbtc_cysta_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9808 static int _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9809 {
9810 struct rtw89_btc *btc = &rtwdev->btc;
9811 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9812 struct rtw89_btc_dm *dm = &btc->dm;
9813 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
9814 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9815 struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL;
9816 union rtw89_btc_fbtc_rxflct r;
9817 u16 cycle, c_begin, c_end, store_index;
9818 char *p = buf, *end = buf + bufsz;
9819 u8 i, cnt = 0, slot_pair;
9820
9821 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9822 if (!pcinfo->valid)
9823 return 0;
9824
9825 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
9826 p += scnprintf(p, end - p,
9827 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
9828 "[cycle_cnt]",
9829 le16_to_cpu(pcysta_le32->cycles),
9830 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]),
9831 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]),
9832 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]),
9833 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK]));
9834
9835 for (i = 0; i < CXST_MAX; i++) {
9836 if (!le32_to_cpu(pcysta_le32->slot_cnt[i]))
9837 continue;
9838 p += scnprintf(p, end - p, ", %s:%d", id_to_slot((u32)i),
9839 le32_to_cpu(pcysta_le32->slot_cnt[i]));
9840 }
9841
9842 if (dm->tdma_now.rxflctrl) {
9843 p += scnprintf(p, end - p, ", leak_rx:%d",
9844 le32_to_cpu(pcysta_le32->leakrx_cnt));
9845 }
9846
9847 if (le32_to_cpu(pcysta_le32->collision_cnt)) {
9848 p += scnprintf(p, end - p, ", collision:%d",
9849 le32_to_cpu(pcysta_le32->collision_cnt));
9850 }
9851
9852 if (le32_to_cpu(pcysta_le32->skip_cnt)) {
9853 p += scnprintf(p, end - p, ", skip:%d",
9854 le32_to_cpu(pcysta_le32->skip_cnt));
9855 }
9856 p += scnprintf(p, end - p, "\n");
9857
9858 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9859 "[cycle_time]",
9860 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]),
9861 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]),
9862 le16_to_cpu(pcysta_le32->tavg_lk) / 1000,
9863 le16_to_cpu(pcysta_le32->tavg_lk) % 1000);
9864 p += scnprintf(p, end - p, ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
9865 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]),
9866 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]),
9867 le16_to_cpu(pcysta_le32->tmax_lk) / 1000,
9868 le16_to_cpu(pcysta_le32->tmax_lk) % 1000);
9869 p += scnprintf(p, end - p, ", maxdiff_t[wl:%d/bt:%d]\n",
9870 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]),
9871 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT]));
9872
9873 if (le16_to_cpu(pcysta_le32->cycles) <= 1)
9874 goto out;
9875
9876 /* 1 cycle record 1 wl-slot and 1 bt-slot */
9877 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
9878
9879 if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair)
9880 c_begin = 1;
9881 else
9882 c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1;
9883
9884 c_end = le16_to_cpu(pcysta_le32->cycles);
9885
9886 for (cycle = c_begin; cycle <= c_end; cycle++) {
9887 cnt++;
9888 store_index = ((cycle - 1) % slot_pair) * 2;
9889
9890 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1)
9891 p += scnprintf(p, end - p,
9892 " %-15s : ->b%02d->w%02d",
9893 "[cycle_step]",
9894 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
9895 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
9896 else
9897 p += scnprintf(p, end - p,
9898 "->b%02d->w%02d",
9899 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
9900 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
9901 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
9902 p += scnprintf(p, end - p, "\n");
9903 }
9904
9905 if (a2dp->exist) {
9906 p += scnprintf(p, end - p,
9907 " %-15s : a2dp_ept:%d, a2dp_late:%d",
9908 "[a2dp_t_sta]",
9909 le16_to_cpu(pcysta_le32->a2dpept),
9910 le16_to_cpu(pcysta_le32->a2dpeptto));
9911
9912 p += scnprintf(p, end - p,
9913 ", avg_t:%d, max_t:%d",
9914 le16_to_cpu(pcysta_le32->tavg_a2dpept),
9915 le16_to_cpu(pcysta_le32->tmax_a2dpept));
9916 r.val = dm->tdma_now.rxflctrl;
9917
9918 if (r.type && r.tgln_n) {
9919 p += scnprintf(p, end - p,
9920 ", cycle[PSTDMA:%d/TDMA:%d], ",
9921 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]),
9922 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF]));
9923
9924 p += scnprintf(p, end - p,
9925 "avg_t[PSTDMA:%d/TDMA:%d], ",
9926 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]),
9927 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF]));
9928
9929 p += scnprintf(p, end - p,
9930 "max_t[PSTDMA:%d/TDMA:%d]",
9931 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]),
9932 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF]));
9933 }
9934 p += scnprintf(p, end - p, "\n");
9935 }
9936
9937 out:
9938 return p - buf;
9939 }
9940
_show_fbtc_cysta_v3(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9941 static int _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9942 {
9943 struct rtw89_btc *btc = &rtwdev->btc;
9944 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
9945 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9946 struct rtw89_btc_dm *dm = &btc->dm;
9947 struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx;
9948 struct rtw89_btc_fbtc_cysta_v3 *pcysta;
9949 struct rtw89_btc_rpt_cmn_info *pcinfo;
9950 u8 i, cnt = 0, slot_pair, divide_cnt;
9951 u16 cycle, c_begin, c_end, store_index;
9952 char *p = buf, *end = buf + bufsz;
9953
9954 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9955 if (!pcinfo->valid)
9956 return 0;
9957
9958 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
9959 p += scnprintf(p, end - p,
9960 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
9961 "[cycle_cnt]",
9962 le16_to_cpu(pcysta->cycles),
9963 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
9964 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
9965 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
9966 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
9967
9968 for (i = 0; i < CXST_MAX; i++) {
9969 if (!le32_to_cpu(pcysta->slot_cnt[i]))
9970 continue;
9971
9972 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
9973 le32_to_cpu(pcysta->slot_cnt[i]));
9974 }
9975
9976 if (dm->tdma_now.rxflctrl)
9977 p += scnprintf(p, end - p, ", leak_rx:%d",
9978 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
9979
9980 if (le32_to_cpu(pcysta->collision_cnt))
9981 p += scnprintf(p, end - p, ", collision:%d",
9982 le32_to_cpu(pcysta->collision_cnt));
9983
9984 if (le32_to_cpu(pcysta->skip_cnt))
9985 p += scnprintf(p, end - p, ", skip:%d",
9986 le32_to_cpu(pcysta->skip_cnt));
9987
9988 p += scnprintf(p, end - p, "\n");
9989
9990 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9991 "[cycle_time]",
9992 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
9993 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
9994 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
9995 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
9996 p += scnprintf(p, end - p,
9997 ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
9998 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
9999 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
10000 le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
10001 le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
10002 p += scnprintf(p, end - p,
10003 ", maxdiff_t[wl:%d/bt:%d]\n",
10004 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
10005 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
10006
10007 cycle = le16_to_cpu(pcysta->cycles);
10008 if (cycle <= 1)
10009 goto out;
10010
10011 /* 1 cycle record 1 wl-slot and 1 bt-slot */
10012 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10013
10014 if (cycle <= slot_pair)
10015 c_begin = 1;
10016 else
10017 c_begin = cycle - slot_pair + 1;
10018
10019 c_end = cycle;
10020
10021 if (a2dp->exist)
10022 divide_cnt = 3;
10023 else
10024 divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
10025
10026 for (cycle = c_begin; cycle <= c_end; cycle++) {
10027 cnt++;
10028 store_index = ((cycle - 1) % slot_pair) * 2;
10029
10030 if (cnt % divide_cnt == 1)
10031 p += scnprintf(p, end - p, " %-15s : ",
10032 "[cycle_step]");
10033
10034 p += scnprintf(p, end - p, "->b%02d",
10035 le16_to_cpu(pcysta->slot_step_time[store_index]));
10036 if (a2dp->exist) {
10037 a2dp_trx = &pcysta->a2dp_trx[store_index];
10038 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10039 a2dp_trx->empty_cnt,
10040 a2dp_trx->retry_cnt,
10041 a2dp_trx->tx_rate ? 3 : 2,
10042 a2dp_trx->tx_cnt,
10043 a2dp_trx->ack_cnt,
10044 a2dp_trx->nack_cnt);
10045 }
10046 p += scnprintf(p, end - p, "->w%02d",
10047 le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
10048 if (a2dp->exist) {
10049 a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
10050 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10051 a2dp_trx->empty_cnt,
10052 a2dp_trx->retry_cnt,
10053 a2dp_trx->tx_rate ? 3 : 2,
10054 a2dp_trx->tx_cnt,
10055 a2dp_trx->ack_cnt,
10056 a2dp_trx->nack_cnt);
10057 }
10058 if (cnt % divide_cnt == 0 || cnt == c_end)
10059 p += scnprintf(p, end - p, "\n");
10060 }
10061
10062 if (a2dp->exist) {
10063 p += scnprintf(p, end - p,
10064 " %-15s : a2dp_ept:%d, a2dp_late:%d",
10065 "[a2dp_t_sta]",
10066 le16_to_cpu(pcysta->a2dp_ept.cnt),
10067 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
10068
10069 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10070 le16_to_cpu(pcysta->a2dp_ept.tavg),
10071 le16_to_cpu(pcysta->a2dp_ept.tmax));
10072
10073 p += scnprintf(p, end - p, "\n");
10074 }
10075
10076 out:
10077 return p - buf;
10078 }
10079
_show_fbtc_cysta_v4(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10080 static int _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10081 {
10082 struct rtw89_btc *btc = &rtwdev->btc;
10083 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
10084 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10085 struct rtw89_btc_dm *dm = &btc->dm;
10086 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
10087 struct rtw89_btc_fbtc_cysta_v4 *pcysta;
10088 struct rtw89_btc_rpt_cmn_info *pcinfo;
10089 u8 i, cnt = 0, slot_pair, divide_cnt;
10090 u16 cycle, c_begin, c_end, store_index;
10091 char *p = buf, *end = buf + bufsz;
10092
10093 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10094 if (!pcinfo->valid)
10095 return 0;
10096
10097 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
10098 p += scnprintf(p, end - p,
10099 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
10100 "[cycle_cnt]",
10101 le16_to_cpu(pcysta->cycles),
10102 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
10103 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
10104 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
10105 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
10106
10107 for (i = 0; i < CXST_MAX; i++) {
10108 if (!le16_to_cpu(pcysta->slot_cnt[i]))
10109 continue;
10110
10111 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
10112 le16_to_cpu(pcysta->slot_cnt[i]));
10113 }
10114
10115 if (dm->tdma_now.rxflctrl)
10116 p += scnprintf(p, end - p, ", leak_rx:%d",
10117 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
10118
10119 if (pcysta->collision_cnt)
10120 p += scnprintf(p, end - p, ", collision:%d",
10121 pcysta->collision_cnt);
10122
10123 if (le16_to_cpu(pcysta->skip_cnt))
10124 p += scnprintf(p, end - p, ", skip:%d",
10125 le16_to_cpu(pcysta->skip_cnt));
10126
10127 p += scnprintf(p, end - p, "\n");
10128
10129 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
10130 "[cycle_time]",
10131 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
10132 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
10133 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
10134 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
10135 p += scnprintf(p, end - p,
10136 ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
10137 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
10138 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
10139 le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
10140 le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
10141 p += scnprintf(p, end - p,
10142 ", maxdiff_t[wl:%d/bt:%d]\n",
10143 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
10144 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
10145
10146 cycle = le16_to_cpu(pcysta->cycles);
10147 if (cycle <= 1)
10148 goto out;
10149
10150 /* 1 cycle record 1 wl-slot and 1 bt-slot */
10151 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10152
10153 if (cycle <= slot_pair)
10154 c_begin = 1;
10155 else
10156 c_begin = cycle - slot_pair + 1;
10157
10158 c_end = cycle;
10159
10160 if (a2dp->exist)
10161 divide_cnt = 3;
10162 else
10163 divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
10164
10165 for (cycle = c_begin; cycle <= c_end; cycle++) {
10166 cnt++;
10167 store_index = ((cycle - 1) % slot_pair) * 2;
10168
10169 if (cnt % divide_cnt == 1)
10170 p += scnprintf(p, end - p, " %-15s : ",
10171 "[cycle_step]");
10172
10173 p += scnprintf(p, end - p, "->b%02d",
10174 le16_to_cpu(pcysta->slot_step_time[store_index]));
10175 if (a2dp->exist) {
10176 a2dp_trx = &pcysta->a2dp_trx[store_index];
10177 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10178 a2dp_trx->empty_cnt,
10179 a2dp_trx->retry_cnt,
10180 a2dp_trx->tx_rate ? 3 : 2,
10181 a2dp_trx->tx_cnt,
10182 a2dp_trx->ack_cnt,
10183 a2dp_trx->nack_cnt);
10184 }
10185 p += scnprintf(p, end - p, "->w%02d",
10186 le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
10187 if (a2dp->exist) {
10188 a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
10189 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10190 a2dp_trx->empty_cnt,
10191 a2dp_trx->retry_cnt,
10192 a2dp_trx->tx_rate ? 3 : 2,
10193 a2dp_trx->tx_cnt,
10194 a2dp_trx->ack_cnt,
10195 a2dp_trx->nack_cnt);
10196 }
10197 if (cnt % divide_cnt == 0 || cnt == c_end)
10198 p += scnprintf(p, end - p, "\n");
10199 }
10200
10201 if (a2dp->exist) {
10202 p += scnprintf(p, end - p,
10203 " %-15s : a2dp_ept:%d, a2dp_late:%d",
10204 "[a2dp_t_sta]",
10205 le16_to_cpu(pcysta->a2dp_ept.cnt),
10206 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
10207
10208 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10209 le16_to_cpu(pcysta->a2dp_ept.tavg),
10210 le16_to_cpu(pcysta->a2dp_ept.tmax));
10211
10212 p += scnprintf(p, end - p, "\n");
10213 }
10214
10215 out:
10216 return p - buf;
10217 }
10218
_show_fbtc_cysta_v5(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10219 static int _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10220 {
10221 struct rtw89_btc *btc = &rtwdev->btc;
10222 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
10223 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10224 struct rtw89_btc_dm *dm = &btc->dm;
10225 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
10226 struct rtw89_btc_fbtc_cysta_v5 *pcysta;
10227 struct rtw89_btc_rpt_cmn_info *pcinfo;
10228 u8 i, cnt = 0, slot_pair, divide_cnt;
10229 u16 cycle, c_begin, c_end, store_index;
10230 char *p = buf, *end = buf + bufsz;
10231
10232 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10233 if (!pcinfo->valid)
10234 return 0;
10235
10236 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
10237 p += scnprintf(p, end - p,
10238 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
10239 "[cycle_cnt]",
10240 le16_to_cpu(pcysta->cycles),
10241 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
10242 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
10243 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
10244 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
10245
10246 for (i = 0; i < CXST_MAX; i++) {
10247 if (!le16_to_cpu(pcysta->slot_cnt[i]))
10248 continue;
10249
10250 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
10251 le16_to_cpu(pcysta->slot_cnt[i]));
10252 }
10253
10254 if (dm->tdma_now.rxflctrl)
10255 p += scnprintf(p, end - p, ", leak_rx:%d",
10256 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
10257
10258 if (pcysta->collision_cnt)
10259 p += scnprintf(p, end - p, ", collision:%d",
10260 pcysta->collision_cnt);
10261
10262 if (le16_to_cpu(pcysta->skip_cnt))
10263 p += scnprintf(p, end - p, ", skip:%d",
10264 le16_to_cpu(pcysta->skip_cnt));
10265
10266 p += scnprintf(p, end - p, "\n");
10267
10268 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
10269 "[cycle_time]",
10270 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
10271 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
10272 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
10273 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
10274 p += scnprintf(p, end - p,
10275 ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n",
10276 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
10277 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
10278 le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
10279 le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
10280
10281 cycle = le16_to_cpu(pcysta->cycles);
10282 if (cycle <= 1)
10283 goto out;
10284
10285 /* 1 cycle record 1 wl-slot and 1 bt-slot */
10286 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10287
10288 if (cycle <= slot_pair)
10289 c_begin = 1;
10290 else
10291 c_begin = cycle - slot_pair + 1;
10292
10293 c_end = cycle;
10294
10295 if (a2dp->exist)
10296 divide_cnt = 3;
10297 else
10298 divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
10299
10300 if (c_begin > c_end)
10301 goto out;
10302
10303 for (cycle = c_begin; cycle <= c_end; cycle++) {
10304 cnt++;
10305 store_index = ((cycle - 1) % slot_pair) * 2;
10306
10307 if (cnt % divide_cnt == 1)
10308 p += scnprintf(p, end - p, " %-15s : ",
10309 "[cycle_step]");
10310
10311 p += scnprintf(p, end - p, "->b%02d",
10312 le16_to_cpu(pcysta->slot_step_time[store_index]));
10313 if (a2dp->exist) {
10314 a2dp_trx = &pcysta->a2dp_trx[store_index];
10315 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10316 a2dp_trx->empty_cnt,
10317 a2dp_trx->retry_cnt,
10318 a2dp_trx->tx_rate ? 3 : 2,
10319 a2dp_trx->tx_cnt,
10320 a2dp_trx->ack_cnt,
10321 a2dp_trx->nack_cnt);
10322 }
10323 p += scnprintf(p, end - p, "->w%02d",
10324 le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
10325 if (a2dp->exist) {
10326 a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
10327 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10328 a2dp_trx->empty_cnt,
10329 a2dp_trx->retry_cnt,
10330 a2dp_trx->tx_rate ? 3 : 2,
10331 a2dp_trx->tx_cnt,
10332 a2dp_trx->ack_cnt,
10333 a2dp_trx->nack_cnt);
10334 }
10335 if (cnt % divide_cnt == 0 || cnt == c_end)
10336 p += scnprintf(p, end - p, "\n");
10337 }
10338
10339 if (a2dp->exist) {
10340 p += scnprintf(p, end - p,
10341 " %-15s : a2dp_ept:%d, a2dp_late:%d",
10342 "[a2dp_t_sta]",
10343 le16_to_cpu(pcysta->a2dp_ept.cnt),
10344 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
10345
10346 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10347 le16_to_cpu(pcysta->a2dp_ept.tavg),
10348 le16_to_cpu(pcysta->a2dp_ept.tmax));
10349
10350 p += scnprintf(p, end - p, "\n");
10351 }
10352
10353 out:
10354 return p - buf;
10355 }
10356
_show_fbtc_cysta_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10357 static int _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10358 {
10359 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt;
10360 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc;
10361 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
10362 struct rtw89_btc_fbtc_cysta_v7 *pcysta = NULL;
10363 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
10364 struct rtw89_btc_rpt_cmn_info *pcinfo;
10365 char *p = buf, *end = buf + bufsz;
10366 u16 cycle, c_begin, c_end, s_id;
10367 u8 i, cnt = 0, divide_cnt;
10368 u8 slot_pair;
10369
10370 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10371 if (!pcinfo->valid)
10372 return 0;
10373
10374 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
10375 p += scnprintf(p, end - p, "\n %-15s : cycle:%d", "[slot_stat]",
10376 le16_to_cpu(pcysta->cycles));
10377
10378 for (i = 0; i < CXST_MAX; i++) {
10379 if (!le16_to_cpu(pcysta->slot_cnt[i]))
10380 continue;
10381 p += scnprintf(p, end - p, ", %s:%d",
10382 id_to_slot(i),
10383 le16_to_cpu(pcysta->slot_cnt[i]));
10384 }
10385
10386 if (dm->tdma_now.rxflctrl)
10387 p += scnprintf(p, end - p, ", leak_rx:%d",
10388 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
10389
10390 if (pcysta->collision_cnt)
10391 p += scnprintf(p, end - p, ", collision:%d",
10392 pcysta->collision_cnt);
10393
10394 if (pcysta->skip_cnt)
10395 p += scnprintf(p, end - p, ", skip:%d",
10396 le16_to_cpu(pcysta->skip_cnt));
10397
10398 p += scnprintf(p, end - p,
10399 "\n\r %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
10400 "[cycle_stat]",
10401 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
10402 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
10403 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
10404 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
10405 p += scnprintf(p, end - p,
10406 ", max_t[wl:%d/bt:%d(>%dms:%d)/lk:%d.%03d]",
10407 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
10408 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
10409 dm->bt_slot_flood, dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD],
10410 le16_to_cpu(pcysta->leak_slot.tamx) / 1000,
10411 le16_to_cpu(pcysta->leak_slot.tamx) % 1000);
10412 p += scnprintf(p, end - p, ", bcn[all:%d/ok:%d/in_bt:%d/in_bt_ok:%d]",
10413 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
10414 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
10415 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
10416 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
10417
10418 if (a2dp->exist) {
10419 p += scnprintf(p, end - p,
10420 "\n\r %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)",
10421 "[a2dp_stat]",
10422 le16_to_cpu(pcysta->a2dp_ept.cnt),
10423 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout),
10424 a2dp->no_empty_streak_2s,
10425 a2dp->no_empty_streak_max);
10426
10427 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10428 le16_to_cpu(pcysta->a2dp_ept.tavg),
10429 le16_to_cpu(pcysta->a2dp_ept.tmax));
10430 }
10431
10432 if (le16_to_cpu(pcysta->cycles) <= 1)
10433 goto out;
10434
10435 /* 1 cycle = 1 wl-slot + 1 bt-slot */
10436 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10437
10438 if (le16_to_cpu(pcysta->cycles) <= slot_pair)
10439 c_begin = 1;
10440 else
10441 c_begin = le16_to_cpu(pcysta->cycles) - slot_pair + 1;
10442
10443 c_end = le16_to_cpu(pcysta->cycles);
10444
10445 if (a2dp->exist)
10446 divide_cnt = 2;
10447 else
10448 divide_cnt = 6;
10449
10450 if (c_begin > c_end)
10451 goto out;
10452
10453 for (cycle = c_begin; cycle <= c_end; cycle++) {
10454 cnt++;
10455 s_id = ((cycle - 1) % slot_pair) * 2;
10456
10457 if (cnt % divide_cnt == 1) {
10458 if (a2dp->exist)
10459 p += scnprintf(p, end - p, "\n\r %-15s : ",
10460 "[slotT_wermtan]");
10461 else
10462 p += scnprintf(p, end - p, "\n\r %-15s : ",
10463 "[slotT_rxerr]");
10464 }
10465
10466 p += scnprintf(p, end - p, "->b%d",
10467 le16_to_cpu(pcysta->slot_step_time[s_id]));
10468
10469 if (a2dp->exist)
10470 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)",
10471 pcysta->wl_rx_err_ratio[s_id],
10472 pcysta->a2dp_trx[s_id].empty_cnt,
10473 pcysta->a2dp_trx[s_id].retry_cnt,
10474 (pcysta->a2dp_trx[s_id].tx_rate ? 3 : 2),
10475 pcysta->a2dp_trx[s_id].tx_cnt,
10476 pcysta->a2dp_trx[s_id].ack_cnt,
10477 pcysta->a2dp_trx[s_id].nack_cnt);
10478 else
10479 p += scnprintf(p, end - p, "(%d)",
10480 pcysta->wl_rx_err_ratio[s_id]);
10481
10482 p += scnprintf(p, end - p, "->w%d",
10483 le16_to_cpu(pcysta->slot_step_time[s_id + 1]));
10484
10485 if (a2dp->exist)
10486 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)",
10487 pcysta->wl_rx_err_ratio[s_id + 1],
10488 pcysta->a2dp_trx[s_id + 1].empty_cnt,
10489 pcysta->a2dp_trx[s_id + 1].retry_cnt,
10490 (pcysta->a2dp_trx[s_id + 1].tx_rate ? 3 : 2),
10491 pcysta->a2dp_trx[s_id + 1].tx_cnt,
10492 pcysta->a2dp_trx[s_id + 1].ack_cnt,
10493 pcysta->a2dp_trx[s_id + 1].nack_cnt);
10494 else
10495 p += scnprintf(p, end - p, "(%d)",
10496 pcysta->wl_rx_err_ratio[s_id + 1]);
10497 }
10498
10499 out:
10500 return p - buf;
10501 }
10502
_show_fbtc_nullsta(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10503 static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10504 {
10505 struct rtw89_btc *btc = &rtwdev->btc;
10506 const struct rtw89_btc_ver *ver = btc->ver;
10507 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10508 struct rtw89_btc_rpt_cmn_info *pcinfo;
10509 union rtw89_btc_fbtc_cynullsta_info *ns;
10510 char *p = buf, *end = buf + bufsz;
10511 u8 i = 0;
10512
10513 if (!btc->dm.tdma_now.rxflctrl)
10514 return 0;
10515
10516 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
10517 if (!pcinfo->valid)
10518 return 0;
10519
10520 ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
10521 if (ver->fcxnullsta == 1) {
10522 for (i = 0; i < 2; i++) {
10523 p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]");
10524 p += scnprintf(p, end - p, "null-%d", i);
10525 p += scnprintf(p, end - p, "[ok:%d/",
10526 le32_to_cpu(ns->v1.result[i][1]));
10527 p += scnprintf(p, end - p, "fail:%d/",
10528 le32_to_cpu(ns->v1.result[i][0]));
10529 p += scnprintf(p, end - p, "on_time:%d/",
10530 le32_to_cpu(ns->v1.result[i][2]));
10531 p += scnprintf(p, end - p, "retry:%d/",
10532 le32_to_cpu(ns->v1.result[i][3]));
10533 p += scnprintf(p, end - p, "avg_t:%d.%03d/",
10534 le32_to_cpu(ns->v1.avg_t[i]) / 1000,
10535 le32_to_cpu(ns->v1.avg_t[i]) % 1000);
10536 p += scnprintf(p, end - p, "max_t:%d.%03d]",
10537 le32_to_cpu(ns->v1.max_t[i]) / 1000,
10538 le32_to_cpu(ns->v1.max_t[i]) % 1000);
10539 }
10540 } else if (ver->fcxnullsta == 7) {
10541 for (i = 0; i < 2; i++) {
10542 p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]");
10543 p += scnprintf(p, end - p, "null-%d", i);
10544 p += scnprintf(p, end - p, "[Tx:%d/",
10545 le32_to_cpu(ns->v7.result[i][4]));
10546 p += scnprintf(p, end - p, "[ok:%d/",
10547 le32_to_cpu(ns->v7.result[i][1]));
10548 p += scnprintf(p, end - p, "fail:%d/",
10549 le32_to_cpu(ns->v7.result[i][0]));
10550 p += scnprintf(p, end - p, "on_time:%d/",
10551 le32_to_cpu(ns->v7.result[i][2]));
10552 p += scnprintf(p, end - p, "retry:%d/",
10553 le32_to_cpu(ns->v7.result[i][3]));
10554 p += scnprintf(p, end - p, "avg_t:%d.%03d/",
10555 le32_to_cpu(ns->v7.tavg[i]) / 1000,
10556 le32_to_cpu(ns->v7.tavg[i]) % 1000);
10557 p += scnprintf(p, end - p, "max_t:%d.%03d]",
10558 le32_to_cpu(ns->v7.tmax[i]) / 1000,
10559 le32_to_cpu(ns->v7.tmax[i]) % 1000);
10560 }
10561 } else {
10562 for (i = 0; i < 2; i++) {
10563 p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]");
10564 p += scnprintf(p, end - p, "null-%d", i);
10565 p += scnprintf(p, end - p, "[Tx:%d/",
10566 le32_to_cpu(ns->v2.result[i][4]));
10567 p += scnprintf(p, end - p, "[ok:%d/",
10568 le32_to_cpu(ns->v2.result[i][1]));
10569 p += scnprintf(p, end - p, "fail:%d/",
10570 le32_to_cpu(ns->v2.result[i][0]));
10571 p += scnprintf(p, end - p, "on_time:%d/",
10572 le32_to_cpu(ns->v2.result[i][2]));
10573 p += scnprintf(p, end - p, "retry:%d/",
10574 le32_to_cpu(ns->v2.result[i][3]));
10575 p += scnprintf(p, end - p, "avg_t:%d.%03d/",
10576 le32_to_cpu(ns->v2.avg_t[i]) / 1000,
10577 le32_to_cpu(ns->v2.avg_t[i]) % 1000);
10578 p += scnprintf(p, end - p, "max_t:%d.%03d]",
10579 le32_to_cpu(ns->v2.max_t[i]) / 1000,
10580 le32_to_cpu(ns->v2.max_t[i]) % 1000);
10581 }
10582 }
10583
10584 return p - buf;
10585 }
10586
_show_fbtc_step_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10587 static int _show_fbtc_step_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10588 {
10589 struct rtw89_btc *btc = &rtwdev->btc;
10590 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10591 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10592 struct rtw89_btc_fbtc_steps_v2 *pstep = NULL;
10593 const struct rtw89_btc_ver *ver = btc->ver;
10594 char *p = buf, *end = buf + bufsz;
10595 u8 type, val, cnt = 0, state = 0;
10596 bool outloop = false;
10597 u16 i, diff_t, n_start = 0, n_stop = 0;
10598 u16 pos_old, pos_new, trace_step;
10599
10600 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
10601 if (!pcinfo->valid)
10602 return 0;
10603
10604 pstep = &pfwinfo->rpt_fbtc_step.finfo.v2;
10605 pos_old = le16_to_cpu(pstep->pos_old);
10606 pos_new = le16_to_cpu(pstep->pos_new);
10607
10608 if (pcinfo->req_fver != pstep->fver)
10609 return 0;
10610
10611 /* store step info by using ring instead of FIFO*/
10612 do {
10613 switch (state) {
10614 case 0:
10615 if (ver->fcxctrl == 7 || ver->fcxctrl == 1)
10616 trace_step = 50;
10617 else
10618 trace_step = btc->ctrl.ctrl.trace_step;
10619
10620 n_start = pos_old;
10621 if (pos_new >= pos_old)
10622 n_stop = pos_new;
10623 else
10624 n_stop = trace_step - 1;
10625
10626 state = 1;
10627 break;
10628 case 1:
10629 for (i = n_start; i <= n_stop; i++) {
10630 type = pstep->step[i].type;
10631 val = pstep->step[i].val;
10632 diff_t = le16_to_cpu(pstep->step[i].difft);
10633
10634 if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
10635 continue;
10636
10637 if (cnt % 10 == 0)
10638 p += scnprintf(p, end - p,
10639 " %-15s : ", "[steps]");
10640
10641 p += scnprintf(p, end - p,
10642 "-> %s(%02d)(%02d)",
10643 (type == CXSTEP_SLOT ? "SLT" :
10644 "EVT"), (u32)val, diff_t);
10645 if (cnt % 10 == 9)
10646 p += scnprintf(p, end - p, "\n");
10647 cnt++;
10648 }
10649
10650 state = 2;
10651 break;
10652 case 2:
10653 if (pos_new < pos_old && n_start != 0) {
10654 n_start = 0;
10655 n_stop = pos_new;
10656 state = 1;
10657 } else {
10658 outloop = true;
10659 }
10660 break;
10661 }
10662 } while (!outloop);
10663
10664 return p - buf;
10665 }
10666
_show_fbtc_step_v3(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10667 static int _show_fbtc_step_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10668 {
10669 struct rtw89_btc *btc = &rtwdev->btc;
10670 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10671 struct rtw89_btc_rpt_cmn_info *pcinfo;
10672 struct rtw89_btc_fbtc_steps_v3 *pstep;
10673 u32 i, n_begin, n_end, array_idx, cnt = 0;
10674 char *p = buf, *end = buf + bufsz;
10675 u8 type, val;
10676 u16 diff_t;
10677
10678 if ((pfwinfo->rpt_en_map &
10679 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0)
10680 return 0;
10681
10682 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
10683 if (!pcinfo->valid)
10684 return 0;
10685
10686 pstep = &pfwinfo->rpt_fbtc_step.finfo.v3;
10687 if (pcinfo->req_fver != pstep->fver)
10688 return 0;
10689
10690 if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP)
10691 n_begin = 1;
10692 else
10693 n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1;
10694
10695 n_end = le32_to_cpu(pstep->cnt);
10696
10697 if (n_begin > n_end)
10698 return 0;
10699
10700 /* restore step info by using ring instead of FIFO */
10701 for (i = n_begin; i <= n_end; i++) {
10702 array_idx = (i - 1) % FCXDEF_STEP;
10703 type = pstep->step[array_idx].type;
10704 val = pstep->step[array_idx].val;
10705 diff_t = le16_to_cpu(pstep->step[array_idx].difft);
10706
10707 if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
10708 continue;
10709
10710 if (cnt % 10 == 0)
10711 p += scnprintf(p, end - p, " %-15s : ", "[steps]");
10712
10713 p += scnprintf(p, end - p, "-> %s(%02d)",
10714 (type == CXSTEP_SLOT ?
10715 id_to_slot((u32)val) :
10716 id_to_evt((u32)val)), diff_t);
10717
10718 if (cnt % 10 == 9)
10719 p += scnprintf(p, end - p, "\n");
10720
10721 cnt++;
10722 }
10723
10724 return p - buf;
10725 }
10726
_show_fw_dm_msg(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10727 static int _show_fw_dm_msg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10728 {
10729 struct rtw89_btc *btc = &rtwdev->btc;
10730 const struct rtw89_btc_ver *ver = btc->ver;
10731 char *p = buf, *end = buf + bufsz;
10732
10733 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
10734 goto out;
10735
10736 p += _show_error(rtwdev, p, end - p);
10737 p += _show_fbtc_tdma(rtwdev, p, end - p);
10738 p += _show_fbtc_slots(rtwdev, p, end - p);
10739
10740 if (ver->fcxcysta == 2)
10741 p += _show_fbtc_cysta_v2(rtwdev, p, end - p);
10742 else if (ver->fcxcysta == 3)
10743 p += _show_fbtc_cysta_v3(rtwdev, p, end - p);
10744 else if (ver->fcxcysta == 4)
10745 p += _show_fbtc_cysta_v4(rtwdev, p, end - p);
10746 else if (ver->fcxcysta == 5)
10747 p += _show_fbtc_cysta_v5(rtwdev, p, end - p);
10748 else if (ver->fcxcysta == 7)
10749 p += _show_fbtc_cysta_v7(rtwdev, p, end - p);
10750
10751 p += _show_fbtc_nullsta(rtwdev, p, end - p);
10752
10753 if (ver->fcxstep == 2)
10754 p += _show_fbtc_step_v2(rtwdev, p, end - p);
10755 else if (ver->fcxstep == 3)
10756 p += _show_fbtc_step_v3(rtwdev, p, end - p);
10757
10758 out:
10759 return p - buf;
10760 }
10761
_get_gnt(struct rtw89_dev * rtwdev,struct rtw89_mac_ax_coex_gnt * gnt_cfg)10762 static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg)
10763 {
10764 const struct rtw89_chip_info *chip = rtwdev->chip;
10765 struct rtw89_mac_ax_gnt *gnt;
10766 u32 val, status;
10767
10768 if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B ||
10769 chip->chip_id == RTL8851B || chip->chip_id == RTL8852BT) {
10770 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
10771 rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status);
10772
10773 gnt = &gnt_cfg->band[0];
10774 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL);
10775 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA);
10776 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL);
10777 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA);
10778
10779 gnt = &gnt_cfg->band[1];
10780 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL);
10781 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA);
10782 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL);
10783 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA);
10784 } else if (chip->chip_id == RTL8852C) {
10785 val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL);
10786 status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1);
10787
10788 gnt = &gnt_cfg->band[0];
10789 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL);
10790 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0);
10791 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL);
10792 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0);
10793
10794 gnt = &gnt_cfg->band[1];
10795 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL);
10796 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1);
10797 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL);
10798 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1);
10799 } else {
10800 return;
10801 }
10802 }
10803
_show_gpio_dbg(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10804 static int _show_gpio_dbg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10805 {
10806 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
10807 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
10808 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10809 union rtw89_btc_fbtc_gpio_dbg *gdbg = NULL;
10810 char *p = buf, *end = buf + bufsz;
10811 u8 *gpio_map, i;
10812 u32 en_map;
10813
10814 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
10815 gdbg = &rtwdev->btc.fwinfo.rpt_fbtc_gpio_dbg.finfo;
10816 if (!pcinfo->valid) {
10817 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10818 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n",
10819 __func__);
10820 goto out;
10821 }
10822
10823 if (ver->fcxgpiodbg == 7) {
10824 en_map = le32_to_cpu(gdbg->v7.en_map);
10825 gpio_map = gdbg->v7.gpio_map;
10826 } else {
10827 en_map = le32_to_cpu(gdbg->v1.en_map);
10828 gpio_map = gdbg->v1.gpio_map;
10829 }
10830
10831 if (!en_map)
10832 goto out;
10833
10834 p += scnprintf(p, end - p, " %-15s : enable_map:0x%08x",
10835 "[gpio_dbg]", en_map);
10836
10837 for (i = 0; i < BTC_DBG_MAX1; i++) {
10838 if (!(en_map & BIT(i)))
10839 continue;
10840 p += scnprintf(p, end - p, ", %s->GPIO%d", id_to_gdbg(i),
10841 gpio_map[i]);
10842 }
10843 p += scnprintf(p, end - p, "\n");
10844
10845 out:
10846 return p - buf;
10847 }
10848
_show_mreg_v1(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10849 static int _show_mreg_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10850 {
10851 const struct rtw89_chip_info *chip = rtwdev->chip;
10852 struct rtw89_btc *btc = &rtwdev->btc;
10853 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10854 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10855 struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL;
10856 struct rtw89_btc_cx *cx = &btc->cx;
10857 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
10858 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
10859 struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
10860 struct rtw89_mac_ax_gnt gnt;
10861 char *p = buf, *end = buf + bufsz;
10862 u8 i = 0, type = 0, cnt = 0;
10863 u32 val, offset;
10864
10865 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
10866 return 0;
10867
10868 p += scnprintf(p, end - p, "========== [HW Status] ==========\n");
10869
10870 p += scnprintf(p, end - p,
10871 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
10872 "[scoreboard]", wl->scbd,
10873 cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
10874 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
10875 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
10876
10877 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
10878 _get_gnt(rtwdev, &gnt_cfg);
10879
10880 gnt = gnt_cfg.band[0];
10881 p += scnprintf(p, end - p,
10882 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
10883 "[gnt_status]",
10884 chip->chip_id == RTL8852C ? "HW" :
10885 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
10886 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
10887 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt);
10888
10889 gnt = gnt_cfg.band[1];
10890 p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
10891 gnt.gnt_wl_sw_en ? "SW" : "HW",
10892 gnt.gnt_wl,
10893 gnt.gnt_bt_sw_en ? "SW" : "HW",
10894 gnt.gnt_bt);
10895
10896 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
10897 if (!pcinfo->valid) {
10898 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10899 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
10900 __func__);
10901 goto out;
10902 }
10903
10904 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
10905 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10906 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
10907 __func__, pmreg->reg_num);
10908
10909 for (i = 0; i < pmreg->reg_num; i++) {
10910 type = (u8)le16_to_cpu(chip->mon_reg[i].type);
10911 offset = le32_to_cpu(chip->mon_reg[i].offset);
10912 val = le32_to_cpu(pmreg->mreg_val[i]);
10913
10914 if (cnt % 6 == 0)
10915 p += scnprintf(p, end - p,
10916 " %-15s : %d_0x%04x=0x%08x",
10917 "[reg]", (u32)type, offset, val);
10918 else
10919 p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x",
10920 (u32)type,
10921 offset, val);
10922 if (cnt % 6 == 5)
10923 p += scnprintf(p, end - p, "\n");
10924 cnt++;
10925
10926 if (i >= pmreg->reg_num)
10927 p += scnprintf(p, end - p, "\n");
10928 }
10929
10930 out:
10931 return p - buf;
10932 }
10933
_show_mreg_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10934 static int _show_mreg_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10935 {
10936 const struct rtw89_chip_info *chip = rtwdev->chip;
10937 struct rtw89_btc *btc = &rtwdev->btc;
10938 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10939 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10940 struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL;
10941 struct rtw89_btc_cx *cx = &btc->cx;
10942 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
10943 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
10944 struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
10945 struct rtw89_mac_ax_gnt gnt;
10946 char *p = buf, *end = buf + bufsz;
10947 u8 i = 0, type = 0, cnt = 0;
10948 u32 val, offset;
10949
10950 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
10951 return 0;
10952
10953 p += scnprintf(p, end - p, "========== [HW Status] ==========\n");
10954
10955 p += scnprintf(p, end - p,
10956 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
10957 "[scoreboard]", wl->scbd,
10958 cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
10959 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
10960 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
10961
10962 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
10963 _get_gnt(rtwdev, &gnt_cfg);
10964
10965 gnt = gnt_cfg.band[0];
10966 p += scnprintf(p, end - p,
10967 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], polut_type:%s",
10968 "[gnt_status]",
10969 chip->chip_id == RTL8852C ? "HW" :
10970 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
10971 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
10972 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt,
10973 id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
10974
10975 gnt = gnt_cfg.band[1];
10976 p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
10977 gnt.gnt_wl_sw_en ? "SW" : "HW",
10978 gnt.gnt_wl,
10979 gnt.gnt_bt_sw_en ? "SW" : "HW",
10980 gnt.gnt_bt);
10981
10982 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
10983 if (!pcinfo->valid) {
10984 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10985 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
10986 __func__);
10987 goto out;
10988 }
10989
10990 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
10991 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10992 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
10993 __func__, pmreg->reg_num);
10994
10995 for (i = 0; i < pmreg->reg_num; i++) {
10996 type = (u8)le16_to_cpu(chip->mon_reg[i].type);
10997 offset = le32_to_cpu(chip->mon_reg[i].offset);
10998 val = le32_to_cpu(pmreg->mreg_val[i]);
10999
11000 if (cnt % 6 == 0)
11001 p += scnprintf(p, end - p,
11002 " %-15s : %d_0x%04x=0x%08x",
11003 "[reg]", (u32)type, offset, val);
11004 else
11005 p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x",
11006 (u32)type,
11007 offset, val);
11008 if (cnt % 6 == 5)
11009 p += scnprintf(p, end - p, "\n");
11010 cnt++;
11011
11012 if (i >= pmreg->reg_num)
11013 p += scnprintf(p, end - p, "\n");
11014 }
11015
11016 out:
11017 return p - buf;
11018 }
11019
_show_mreg_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11020 static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11021 {
11022 struct rtw89_btc *btc = &rtwdev->btc;
11023 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11024 struct rtw89_btc_fbtc_mreg_val_v7 *pmreg = NULL;
11025 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11026 struct rtw89_btc_cx *cx = &btc->cx;
11027 struct rtw89_btc_wl_info *wl = &cx->wl;
11028 struct rtw89_btc_bt_info *bt = &cx->bt;
11029 struct rtw89_mac_ax_gnt *gnt = NULL;
11030 struct rtw89_btc_dm *dm = &btc->dm;
11031 char *p = buf, *end = buf + bufsz;
11032 u8 i, type, cnt = 0;
11033 u32 val, offset;
11034
11035 if (!(dm->coex_info_map & BTC_COEX_INFO_MREG))
11036 return 0;
11037
11038 p += scnprintf(p, end - p, "\n\r========== [HW Status] ==========");
11039
11040 p += scnprintf(p, end - p,
11041 "\n\r %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)",
11042 "[scoreboard]", wl->scbd,
11043 cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
11044 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
11045 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
11046
11047 /* To avoid I/O if WL LPS or power-off */
11048 dm->pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
11049
11050 p += scnprintf(p, end - p,
11051 "\n\r %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s",
11052 "[gnt_status]",
11053 rtwdev->chip->para_ver & BTC_FEAT_PTA_ONOFF_CTRL ? "HW" :
11054 dm->pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
11055 wl->pta_req_mac,
11056 id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
11057
11058 gnt = &dm->gnt.band[RTW89_PHY_0];
11059
11060 p += scnprintf(p, end - p, ", phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]",
11061 gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl,
11062 gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt);
11063
11064 if (rtwdev->dbcc_en) {
11065 gnt = &dm->gnt.band[RTW89_PHY_1];
11066 p += scnprintf(p, end - p,
11067 ", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]",
11068 gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl,
11069 gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt);
11070 }
11071
11072 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
11073 if (!pcinfo->valid)
11074 goto out;
11075
11076 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
11077
11078 for (i = 0; i < pmreg->reg_num; i++) {
11079 type = (u8)le16_to_cpu(rtwdev->chip->mon_reg[i].type);
11080 offset = le32_to_cpu(rtwdev->chip->mon_reg[i].offset);
11081 val = le32_to_cpu(pmreg->mreg_val[i]);
11082
11083 if (cnt % 6 == 0)
11084 p += scnprintf(p, end - p,
11085 "\n\r %-15s : %s_0x%x=0x%x", "[reg]",
11086 id_to_regtype(type), offset, val);
11087 else
11088 p += scnprintf(p, end - p, ", %s_0x%x=0x%x",
11089 id_to_regtype(type), offset, val);
11090 cnt++;
11091 }
11092
11093 out:
11094 return p - buf;
11095 }
11096
_show_summary_v1(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11097 static int _show_summary_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11098 {
11099 struct rtw89_btc *btc = &rtwdev->btc;
11100 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11101 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11102 struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL;
11103 struct rtw89_btc_cx *cx = &btc->cx;
11104 struct rtw89_btc_dm *dm = &btc->dm;
11105 struct rtw89_btc_wl_info *wl = &cx->wl;
11106 struct rtw89_btc_bt_info *bt = &cx->bt;
11107 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11108 char *p = buf, *end = buf + bufsz;
11109 u8 i;
11110
11111 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11112 return 0;
11113
11114 p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11115
11116 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11117 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11118 prptctrl = &pfwinfo->rpt_ctrl.finfo.v1;
11119
11120 p += scnprintf(p, end - p,
11121 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
11122 "[summary]", pfwinfo->cnt_h2c,
11123 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt,
11124 pfwinfo->cnt_c2h, prptctrl->c2h_cnt);
11125
11126 p += scnprintf(p, end - p,
11127 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
11128 pfwinfo->event[BTF_EVNT_RPT],
11129 prptctrl->rpt_cnt,
11130 prptctrl->rpt_enable, dm->error.val);
11131
11132 if (dm->error.map.wl_fw_hang)
11133 p += scnprintf(p, end - p, " (WL FW Hang!!)");
11134 p += scnprintf(p, end - p, "\n");
11135 p += scnprintf(p, end - p,
11136 " %-15s : send_ok:%d, send_fail:%d, recv:%d",
11137 "[mailbox]", prptctrl->mb_send_ok_cnt,
11138 prptctrl->mb_send_fail_cnt,
11139 prptctrl->mb_recv_cnt);
11140
11141 p += scnprintf(p, end - p,
11142 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n",
11143 prptctrl->mb_a2dp_empty_cnt,
11144 prptctrl->mb_a2dp_flct_cnt,
11145 prptctrl->mb_a2dp_full_cnt);
11146
11147 p += scnprintf(p, end - p,
11148 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
11149 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11150 cx->cnt_wl[BTC_WCNT_RFK_GO],
11151 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11152 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11153
11154 p += scnprintf(p, end - p,
11155 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
11156 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
11157 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
11158 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
11159 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
11160 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
11161
11162 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
11163 bt->rfk_info.map.timeout = 1;
11164 else
11165 bt->rfk_info.map.timeout = 0;
11166
11167 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
11168 } else {
11169 p += scnprintf(p, end - p,
11170 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
11171 "[summary]", pfwinfo->cnt_h2c,
11172 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
11173 pfwinfo->event[BTF_EVNT_RPT],
11174 btc->fwinfo.rpt_en_map);
11175 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n");
11176 }
11177
11178 for (i = 0; i < BTC_NCNT_NUM; i++)
11179 cnt_sum += dm->cnt_notify[i];
11180
11181 p += scnprintf(p, end - p,
11182 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11183 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11184 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11185
11186 p += scnprintf(p, end - p,
11187 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
11188 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11189 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11190 cnt[BTC_NCNT_WL_STA]);
11191
11192 p += scnprintf(p, end - p,
11193 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11194 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
11195 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
11196 cnt[BTC_NCNT_SPECIAL_PACKET]);
11197
11198 p += scnprintf(p, end - p,
11199 "timer=%d, control=%d, customerize=%d\n",
11200 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11201 cnt[BTC_NCNT_CUSTOMERIZE]);
11202
11203 return p - buf;
11204 }
11205
_show_summary_v4(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11206 static int _show_summary_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11207 {
11208 struct rtw89_btc *btc = &rtwdev->btc;
11209 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11210 struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl;
11211 struct rtw89_btc_rpt_cmn_info *pcinfo;
11212 struct rtw89_btc_cx *cx = &btc->cx;
11213 struct rtw89_btc_dm *dm = &btc->dm;
11214 struct rtw89_btc_wl_info *wl = &cx->wl;
11215 struct rtw89_btc_bt_info *bt = &cx->bt;
11216 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11217 char *p = buf, *end = buf + bufsz;
11218 u8 i;
11219
11220 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11221 return 0;
11222
11223 p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11224
11225 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11226 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11227 prptctrl = &pfwinfo->rpt_ctrl.finfo.v4;
11228
11229 p += scnprintf(p, end - p,
11230 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
11231 "[summary]", pfwinfo->cnt_h2c,
11232 pfwinfo->cnt_h2c_fail,
11233 le32_to_cpu(prptctrl->rpt_info.cnt_h2c),
11234 pfwinfo->cnt_c2h,
11235 le32_to_cpu(prptctrl->rpt_info.cnt_c2h));
11236
11237 p += scnprintf(p, end - p,
11238 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
11239 pfwinfo->event[BTF_EVNT_RPT],
11240 le32_to_cpu(prptctrl->rpt_info.cnt),
11241 le32_to_cpu(prptctrl->rpt_info.en),
11242 dm->error.val);
11243
11244 if (dm->error.map.wl_fw_hang)
11245 p += scnprintf(p, end - p, " (WL FW Hang!!)");
11246 p += scnprintf(p, end - p, "\n");
11247 p += scnprintf(p, end - p,
11248 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11249 "[mailbox]",
11250 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11251 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11252 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11253
11254 p += scnprintf(p, end - p,
11255 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
11256 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11257 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11258 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11259 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11260 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11261
11262 p += scnprintf(p, end - p,
11263 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
11264 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11265 cx->cnt_wl[BTC_WCNT_RFK_GO],
11266 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11267 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11268
11269 p += scnprintf(p, end - p,
11270 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
11271 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]),
11272 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]),
11273 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]),
11274 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]),
11275 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL]));
11276
11277 if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
11278 bt->rfk_info.map.timeout = 1;
11279 else
11280 bt->rfk_info.map.timeout = 0;
11281
11282 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
11283 } else {
11284 p += scnprintf(p, end - p,
11285 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
11286 "[summary]", pfwinfo->cnt_h2c,
11287 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
11288 pfwinfo->event[BTF_EVNT_RPT],
11289 btc->fwinfo.rpt_en_map);
11290 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n");
11291 }
11292
11293 for (i = 0; i < BTC_NCNT_NUM; i++)
11294 cnt_sum += dm->cnt_notify[i];
11295
11296 p += scnprintf(p, end - p,
11297 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11298 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11299 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11300
11301 p += scnprintf(p, end - p,
11302 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
11303 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11304 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11305 cnt[BTC_NCNT_WL_STA]);
11306
11307 p += scnprintf(p, end - p,
11308 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11309 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
11310 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
11311 cnt[BTC_NCNT_SPECIAL_PACKET]);
11312
11313 p += scnprintf(p, end - p,
11314 "timer=%d, control=%d, customerize=%d\n",
11315 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11316 cnt[BTC_NCNT_CUSTOMERIZE]);
11317
11318 return p - buf;
11319 }
11320
_show_summary_v5(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11321 static int _show_summary_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11322 {
11323 struct rtw89_btc *btc = &rtwdev->btc;
11324 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11325 struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl;
11326 struct rtw89_btc_rpt_cmn_info *pcinfo;
11327 struct rtw89_btc_cx *cx = &btc->cx;
11328 struct rtw89_btc_dm *dm = &btc->dm;
11329 struct rtw89_btc_wl_info *wl = &cx->wl;
11330 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11331 char *p = buf, *end = buf + bufsz;
11332 u8 i;
11333
11334 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11335 return 0;
11336
11337 p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11338
11339 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11340 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11341 prptctrl = &pfwinfo->rpt_ctrl.finfo.v5;
11342
11343 p += scnprintf(p, end - p,
11344 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
11345 "[summary]", pfwinfo->cnt_h2c,
11346 pfwinfo->cnt_h2c_fail,
11347 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11348 pfwinfo->cnt_c2h,
11349 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11350 le16_to_cpu(prptctrl->rpt_info.len_c2h));
11351
11352 p += scnprintf(p, end - p,
11353 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11354 pfwinfo->event[BTF_EVNT_RPT],
11355 le16_to_cpu(prptctrl->rpt_info.cnt),
11356 le32_to_cpu(prptctrl->rpt_info.en));
11357
11358 if (dm->error.map.wl_fw_hang)
11359 p += scnprintf(p, end - p, " (WL FW Hang!!)");
11360 p += scnprintf(p, end - p, "\n");
11361 p += scnprintf(p, end - p,
11362 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11363 "[mailbox]",
11364 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11365 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11366 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11367
11368 p += scnprintf(p, end - p,
11369 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
11370 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11371 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11372 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11373 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11374 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11375
11376 p += scnprintf(p, end - p,
11377 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
11378 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11379 cx->cnt_wl[BTC_WCNT_RFK_GO],
11380 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11381 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11382
11383 p += scnprintf(p, end - p,
11384 ", bt_rfk[req:%d]",
11385 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11386
11387 p += scnprintf(p, end - p,
11388 ", AOAC[RF_on:%d/RF_off:%d]",
11389 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11390 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11391 } else {
11392 p += scnprintf(p, end - p,
11393 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
11394 "[summary]", pfwinfo->cnt_h2c,
11395 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
11396 }
11397
11398 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
11399 pfwinfo->err[BTFRE_EXCEPTION]) {
11400 p += scnprintf(p, end - p, "\n");
11401 p += scnprintf(p, end - p,
11402 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
11403 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
11404 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
11405 pfwinfo->fver_mismch,
11406 pfwinfo->err[BTFRE_EXCEPTION],
11407 wl->status.map.lps, wl->status.map.rf_off);
11408 }
11409
11410 for (i = 0; i < BTC_NCNT_NUM; i++)
11411 cnt_sum += dm->cnt_notify[i];
11412
11413 p += scnprintf(p, end - p, "\n");
11414 p += scnprintf(p, end - p,
11415 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11416 "[notify_cnt]",
11417 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11418 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11419
11420 p += scnprintf(p, end - p,
11421 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11422 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11423 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11424 cnt[BTC_NCNT_WL_STA]);
11425
11426 p += scnprintf(p, end - p, "\n");
11427 p += scnprintf(p, end - p,
11428 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11429 "[notify_cnt]",
11430 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11431 cnt[BTC_NCNT_SWITCH_BAND],
11432 cnt[BTC_NCNT_SPECIAL_PACKET]);
11433
11434 p += scnprintf(p, end - p,
11435 "timer=%d, control=%d, customerize=%d",
11436 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11437 cnt[BTC_NCNT_CUSTOMERIZE]);
11438
11439 return p - buf;
11440 }
11441
_show_summary_v105(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11442 static int _show_summary_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11443 {
11444 struct rtw89_btc *btc = &rtwdev->btc;
11445 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11446 struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl;
11447 struct rtw89_btc_rpt_cmn_info *pcinfo;
11448 struct rtw89_btc_cx *cx = &btc->cx;
11449 struct rtw89_btc_dm *dm = &btc->dm;
11450 struct rtw89_btc_wl_info *wl = &cx->wl;
11451 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11452 char *p = buf, *end = buf + bufsz;
11453 u8 i;
11454
11455 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11456 return 0;
11457
11458 p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11459
11460 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11461 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11462 prptctrl = &pfwinfo->rpt_ctrl.finfo.v105;
11463
11464 p += scnprintf(p, end - p,
11465 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
11466 "[summary]", pfwinfo->cnt_h2c,
11467 pfwinfo->cnt_h2c_fail,
11468 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11469 pfwinfo->cnt_c2h,
11470 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11471 le16_to_cpu(prptctrl->rpt_info.len_c2h));
11472
11473 p += scnprintf(p, end - p,
11474 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11475 pfwinfo->event[BTF_EVNT_RPT],
11476 le16_to_cpu(prptctrl->rpt_info.cnt),
11477 le32_to_cpu(prptctrl->rpt_info.en));
11478
11479 if (dm->error.map.wl_fw_hang)
11480 p += scnprintf(p, end - p, " (WL FW Hang!!)");
11481 p += scnprintf(p, end - p, "\n");
11482 p += scnprintf(p, end - p,
11483 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11484 "[mailbox]",
11485 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11486 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11487 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11488
11489 p += scnprintf(p, end - p,
11490 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
11491 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11492 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11493 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11494 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11495 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11496
11497 p += scnprintf(p, end - p,
11498 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
11499 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11500 cx->cnt_wl[BTC_WCNT_RFK_GO],
11501 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11502 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11503
11504 p += scnprintf(p, end - p,
11505 ", bt_rfk[req:%d]",
11506 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11507
11508 p += scnprintf(p, end - p,
11509 ", AOAC[RF_on:%d/RF_off:%d]",
11510 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11511 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11512 } else {
11513 p += scnprintf(p, end - p,
11514 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
11515 "[summary]", pfwinfo->cnt_h2c,
11516 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
11517 }
11518
11519 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
11520 pfwinfo->err[BTFRE_EXCEPTION]) {
11521 p += scnprintf(p, end - p, "\n");
11522 p += scnprintf(p, end - p,
11523 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
11524 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
11525 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
11526 pfwinfo->fver_mismch,
11527 pfwinfo->err[BTFRE_EXCEPTION],
11528 wl->status.map.lps, wl->status.map.rf_off);
11529 }
11530
11531 for (i = 0; i < BTC_NCNT_NUM; i++)
11532 cnt_sum += dm->cnt_notify[i];
11533
11534 p += scnprintf(p, end - p, "\n");
11535 p += scnprintf(p, end - p,
11536 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11537 "[notify_cnt]",
11538 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11539 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11540
11541 p += scnprintf(p, end - p,
11542 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11543 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11544 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11545 cnt[BTC_NCNT_WL_STA]);
11546
11547 p += scnprintf(p, end - p, "\n");
11548 p += scnprintf(p, end - p,
11549 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11550 "[notify_cnt]",
11551 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11552 cnt[BTC_NCNT_SWITCH_BAND],
11553 cnt[BTC_NCNT_SPECIAL_PACKET]);
11554
11555 p += scnprintf(p, end - p,
11556 "timer=%d, control=%d, customerize=%d",
11557 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11558 cnt[BTC_NCNT_CUSTOMERIZE]);
11559
11560 return p - buf;
11561 }
11562
_show_summary_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11563 static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11564 {
11565 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
11566 struct rtw89_btc_fbtc_rpt_ctrl_v7 *prptctrl = NULL;
11567 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11568 struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
11569 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
11570 struct rtw89_btc_wl_info *wl = &cx->wl;
11571 u32 *cnt = rtwdev->btc.dm.cnt_notify;
11572 char *p = buf, *end = buf + bufsz;
11573 u32 cnt_sum = 0;
11574 u8 i;
11575
11576 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11577 return 0;
11578
11579 p += scnprintf(p, end - p, "%s",
11580 "\n\r========== [Statistics] ==========");
11581
11582 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11583 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
11584 !wl->status.map.rf_off) {
11585 prptctrl = &pfwinfo->rpt_ctrl.finfo.v7;
11586
11587 p += scnprintf(p, end - p,
11588 "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d),"
11589 "c2h_cnt=%d(fw_send:%d, len:%d, max:%d), ",
11590 "[summary]", pfwinfo->cnt_h2c,
11591 pfwinfo->cnt_h2c_fail,
11592 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11593 pfwinfo->cnt_c2h,
11594 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11595 le16_to_cpu(prptctrl->rpt_info.len_c2h),
11596 rtwdev->btc.ver->info_buf);
11597
11598 p += scnprintf(p, end - p,
11599 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11600 pfwinfo->event[BTF_EVNT_RPT],
11601 le16_to_cpu(prptctrl->rpt_info.cnt),
11602 le32_to_cpu(prptctrl->rpt_info.en));
11603
11604 if (dm->error.map.wl_fw_hang)
11605 p += scnprintf(p, end - p, " (WL FW Hang!!)");
11606
11607 p += scnprintf(p, end - p,
11608 "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11609 "[mailbox]",
11610 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11611 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11612 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11613
11614 p += scnprintf(p, end - p,
11615 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)",
11616 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11617 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11618 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11619 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11620 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11621
11622 p += scnprintf(p, end - p,
11623 "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
11624 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11625 cx->cnt_wl[BTC_WCNT_RFK_GO],
11626 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11627 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT],
11628 wl->rfk_info.proc_time);
11629
11630 p += scnprintf(p, end - p, ", bt_rfk[req:%d]",
11631 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11632
11633 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]",
11634 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11635 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11636 } else {
11637 p += scnprintf(p, end - p,
11638 "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)",
11639 "[summary]",
11640 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
11641 pfwinfo->cnt_c2h,
11642 wl->status.map.lps, wl->status.map.rf_off);
11643 }
11644
11645 for (i = 0; i < BTC_NCNT_NUM; i++)
11646 cnt_sum += dm->cnt_notify[i];
11647
11648 p += scnprintf(p, end - p,
11649 "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11650 "[notify_cnt]",
11651 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11652 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11653
11654 p += scnprintf(p, end - p,
11655 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11656 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11657 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11658 cnt[BTC_NCNT_WL_STA]);
11659
11660 p += scnprintf(p, end - p,
11661 "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
11662 "[notify_cnt]",
11663 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11664 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
11665 cnt[BTC_NCNT_SPECIAL_PACKET]);
11666
11667 p += scnprintf(p, end - p,
11668 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
11669 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
11670 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
11671 cnt[BTC_NCNT_COUNTRYCODE]);
11672
11673 return p - buf;
11674 }
11675
_show_summary_v8(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11676 static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11677 {
11678 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
11679 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11680 struct rtw89_btc_fbtc_rpt_ctrl_v8 *prptctrl = NULL;
11681 struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
11682 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
11683 struct rtw89_btc_wl_info *wl = &cx->wl;
11684 u32 *cnt = rtwdev->btc.dm.cnt_notify;
11685 char *p = buf, *end = buf + bufsz;
11686 u32 cnt_sum = 0;
11687 u8 i;
11688
11689 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11690 return 0;
11691
11692 p += scnprintf(p, end - p, "%s",
11693 "\n\r========== [Statistics] ==========");
11694
11695 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11696 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
11697 !wl->status.map.rf_off) {
11698 prptctrl = &pfwinfo->rpt_ctrl.finfo.v8;
11699
11700 p += scnprintf(p, end - p,
11701 "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ",
11702 "[summary]", pfwinfo->cnt_h2c,
11703 pfwinfo->cnt_h2c_fail,
11704 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11705 pfwinfo->cnt_c2h,
11706 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11707 le16_to_cpu(prptctrl->rpt_info.len_c2h),
11708 (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l,
11709 rtwdev->btc.ver->info_buf);
11710
11711 p += scnprintf(p, end - p,
11712 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11713 pfwinfo->event[BTF_EVNT_RPT],
11714 le16_to_cpu(prptctrl->rpt_info.cnt),
11715 le32_to_cpu(prptctrl->rpt_info.en));
11716
11717 if (dm->error.map.wl_fw_hang)
11718 p += scnprintf(p, end - p, " (WL FW Hang!!)");
11719
11720 p += scnprintf(p, end - p,
11721 "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11722 "[mailbox]",
11723 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11724 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11725 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11726
11727 p += scnprintf(p, end - p,
11728 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)",
11729 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11730 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11731 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11732 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11733 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11734
11735 p += scnprintf(p, end - p,
11736 "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
11737 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11738 cx->cnt_wl[BTC_WCNT_RFK_GO],
11739 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11740 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT],
11741 wl->rfk_info.proc_time);
11742
11743 p += scnprintf(p, end - p, ", bt_rfk[req:%d]",
11744 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11745
11746 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]",
11747 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11748 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11749 } else {
11750 p += scnprintf(p, end - p,
11751 "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)",
11752 "[summary]",
11753 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
11754 pfwinfo->cnt_c2h,
11755 wl->status.map.lps, wl->status.map.rf_off);
11756 }
11757
11758 for (i = 0; i < BTC_NCNT_NUM; i++)
11759 cnt_sum += dm->cnt_notify[i];
11760
11761 p += scnprintf(p, end - p,
11762 "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11763 "[notify_cnt]",
11764 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11765 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11766
11767 p += scnprintf(p, end - p,
11768 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11769 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11770 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11771 cnt[BTC_NCNT_WL_STA]);
11772
11773 p += scnprintf(p, end - p,
11774 "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
11775 "[notify_cnt]",
11776 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11777 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
11778 cnt[BTC_NCNT_SPECIAL_PACKET]);
11779
11780 p += scnprintf(p, end - p,
11781 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
11782 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
11783 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
11784 cnt[BTC_NCNT_COUNTRYCODE]);
11785
11786 return p - buf;
11787 }
11788
rtw89_btc_dump_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11789 ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11790 {
11791 struct rtw89_btc *btc = &rtwdev->btc;
11792 struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver;
11793 const struct rtw89_btc_ver *ver = btc->ver;
11794 struct rtw89_btc_dm *dm = &btc->dm;
11795 char *p = buf, *end = buf + bufsz;
11796
11797 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
11798
11799 p += scnprintf(p, end - p,
11800 "\n\n\n** Page:%3d/RunCNT:%3d **",
11801 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO],
11802 dm->cnt_dm[BTC_DCNT_RUN]);
11803 p += scnprintf(p, end - p,
11804 "\n========== [BTC FEATURE SUB VER] ==========");
11805 p += scnprintf(p, end - p,
11806 "\n %-15s : fcxbtcrpt[%d/%d], fcxtdma[%d/%d], fcxslots[%d/%d], fcxcysta[%d/%d]",
11807 "[FW/DRV]", fwsubver->fcxbtcrpt, ver->fcxbtcrpt,
11808 fwsubver->fcxtdma, ver->fcxtdma, fwsubver->fcxslots,
11809 ver->fcxslots, fwsubver->fcxcysta, ver->fcxcysta);
11810 p += scnprintf(p, end - p,
11811 "\n %-15s : fcxstep[%d/%d], fcxnullsta[%d/%d], fcxmreg[%d/%d], fcxgpiodbg[%d/%d]",
11812 "[FW/DRV]", fwsubver->fcxstep, ver->fcxstep,
11813 fwsubver->fcxnullsta, ver->fcxnullsta, fwsubver->fcxmreg,
11814 ver->fcxmreg, fwsubver->fcxgpiodbg, ver->fcxgpiodbg);
11815 p += scnprintf(p, end - p,
11816 "\n %-15s : fcxbtver[%d/%d], fcxbtscan[%d/%d], fcxbtafh[%d/%d], fcxbtdevinfo[%d/%d]",
11817 "[FW/DRV]", fwsubver->fcxbtver, ver->fcxbtver,
11818 fwsubver->fcxbtscan, ver->fcxbtscan, fwsubver->fcxbtafh,
11819 ver->fcxbtafh, fwsubver->fcxbtdevinfo, ver->fcxbtdevinfo);
11820 p += scnprintf(p, end - p,
11821 "\n %-15s : fcxosi[%d/%d], fcxmlo[%d/%d],",
11822 "[FW/DRV]", fwsubver->fcxosi, ver->fcxosi,
11823 fwsubver->fcxmlo, ver->fcxmlo);
11824
11825 p += _show_cx_info(rtwdev, p, end - p);
11826 p += _show_wl_info(rtwdev, p, end - p);
11827 p += _show_bt_info(rtwdev, p, end - p);
11828 p += _show_dm_info(rtwdev, p, end - p);
11829 p += _show_fw_dm_msg(rtwdev, p, end - p);
11830
11831 if (ver->fcxmreg == 1)
11832 p += _show_mreg_v1(rtwdev, p, end - p);
11833 else if (ver->fcxmreg == 2)
11834 p += _show_mreg_v2(rtwdev, p, end - p);
11835 else if (ver->fcxmreg == 7)
11836 p += _show_mreg_v7(rtwdev, p, end - p);
11837
11838 p += _show_gpio_dbg(rtwdev, p, end - p);
11839
11840 if (ver->fcxbtcrpt == 1)
11841 p += _show_summary_v1(rtwdev, p, end - p);
11842 else if (ver->fcxbtcrpt == 4)
11843 p += _show_summary_v4(rtwdev, p, end - p);
11844 else if (ver->fcxbtcrpt == 5)
11845 p += _show_summary_v5(rtwdev, p, end - p);
11846 else if (ver->fcxbtcrpt == 105)
11847 p += _show_summary_v105(rtwdev, p, end - p);
11848 else if (ver->fcxbtcrpt == 7)
11849 p += _show_summary_v7(rtwdev, p, end - p);
11850 else if (ver->fcxbtcrpt == 8)
11851 p += _show_summary_v8(rtwdev, p, end - p);
11852
11853 return p - buf;
11854 }
11855
rtw89_coex_recognize_ver(struct rtw89_dev * rtwdev)11856 void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev)
11857 {
11858 const struct rtw89_chip_info *chip = rtwdev->chip;
11859 struct rtw89_btc *btc = &rtwdev->btc;
11860 const struct rtw89_btc_ver *btc_ver_def;
11861 const struct rtw89_fw_suit *fw_suit;
11862 u32 suit_ver_code;
11863 int i;
11864
11865 fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL);
11866 suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit);
11867
11868 for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) {
11869 btc_ver_def = &rtw89_btc_ver_defs[i];
11870
11871 if (chip->chip_id != btc_ver_def->chip_id)
11872 continue;
11873
11874 if (suit_ver_code >= btc_ver_def->fw_ver_code) {
11875 btc->ver = btc_ver_def;
11876 goto out;
11877 }
11878 }
11879
11880 btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX];
11881
11882 out:
11883 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n",
11884 (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code);
11885 }
11886
rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev * rtwdev,u32 ms)11887 void rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev *rtwdev, u32 ms)
11888 {
11889 struct rtw89_btc_bt_link_info *bt_linfo = &rtwdev->btc.cx.bt.link_info;
11890 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
11891
11892 if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags))
11893 return;
11894
11895 if (!a2dp.exist)
11896 return;
11897
11898 fsleep(ms * 1000);
11899 }
11900 EXPORT_SYMBOL(rtw89_btc_ntfy_preserve_bt_time);
11901
rtw89_btc_ntfy_conn_rfk(struct rtw89_dev * rtwdev,bool state)11902 void rtw89_btc_ntfy_conn_rfk(struct rtw89_dev *rtwdev, bool state)
11903 {
11904 rtwdev->btc.cx.wl.rfk_info.con_rfk = state;
11905 }
11906 EXPORT_SYMBOL(rtw89_btc_ntfy_conn_rfk);
11907