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