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