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