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 FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/
13
14 enum btc_fbtc_tdma_template {
15 CXTD_OFF = 0x0,
16 CXTD_OFF_B2,
17 CXTD_OFF_EXT,
18 CXTD_FIX,
19 CXTD_PFIX,
20 CXTD_AUTO,
21 CXTD_PAUTO,
22 CXTD_AUTO2,
23 CXTD_PAUTO2,
24 CXTD_MAX,
25 };
26
27 enum btc_fbtc_tdma_type {
28 CXTDMA_OFF = 0x0,
29 CXTDMA_FIX = 0x1,
30 CXTDMA_AUTO = 0x2,
31 CXTDMA_AUTO2 = 0x3,
32 CXTDMA_MAX
33 };
34
35 enum btc_fbtc_tdma_rx_flow_ctrl {
36 CXFLC_OFF = 0x0,
37 CXFLC_NULLP = 0x1,
38 CXFLC_QOSNULL = 0x2,
39 CXFLC_CTS = 0x3,
40 CXFLC_MAX
41 };
42
43 enum btc_fbtc_tdma_wlan_tx_pause {
44 CXTPS_OFF = 0x0, /* no wl tx pause*/
45 CXTPS_ON = 0x1,
46 CXTPS_MAX
47 };
48
49 enum btc_mlme_state {
50 MLME_NO_LINK,
51 MLME_LINKING,
52 MLME_LINKED,
53 };
54
55 #define FCXONESLOT_VER 1
56 struct btc_fbtc_1slot {
57 u8 fver;
58 u8 sid; /* slot id */
59 struct rtw89_btc_fbtc_slot slot;
60 } __packed;
61
62 static const struct rtw89_btc_fbtc_tdma t_def[] = {
63 [CXTD_OFF] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
64 [CXTD_OFF_B2] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0},
65 [CXTD_OFF_EXT] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 3, 0, 0},
66 [CXTD_FIX] = { CXTDMA_FIX, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
67 [CXTD_PFIX] = { CXTDMA_FIX, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0},
68 [CXTD_AUTO] = { CXTDMA_AUTO, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
69 [CXTD_PAUTO] = { CXTDMA_AUTO, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0},
70 [CXTD_AUTO2] = {CXTDMA_AUTO2, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
71 [CXTD_PAUTO2] = {CXTDMA_AUTO2, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}
72 };
73
74 #define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \
75 { .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \
76 .cxtype = cpu_to_le16(__cxtype),}
77
78 static const struct rtw89_btc_fbtc_slot s_def[] = {
79 [CXST_OFF] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
80 [CXST_B2W] = __DEF_FBTC_SLOT(5, 0x5a5a5a5a, SLOT_ISO),
81 [CXST_W1] = __DEF_FBTC_SLOT(70, 0x5a5a5a5a, SLOT_ISO),
82 [CXST_W2] = __DEF_FBTC_SLOT(70, 0x5a5a5aaa, SLOT_ISO),
83 [CXST_W2B] = __DEF_FBTC_SLOT(15, 0x5a5a5a5a, SLOT_ISO),
84 [CXST_B1] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
85 [CXST_B2] = __DEF_FBTC_SLOT(7, 0x6a5a5a5a, SLOT_MIX),
86 [CXST_B3] = __DEF_FBTC_SLOT(5, 0x55555555, SLOT_MIX),
87 [CXST_B4] = __DEF_FBTC_SLOT(50, 0x55555555, SLOT_MIX),
88 [CXST_LK] = __DEF_FBTC_SLOT(20, 0x5a5a5a5a, SLOT_ISO),
89 [CXST_BLK] = __DEF_FBTC_SLOT(250, 0x55555555, SLOT_MIX),
90 [CXST_E2G] = __DEF_FBTC_SLOT(20, 0x6a5a5a5a, SLOT_MIX),
91 [CXST_E5G] = __DEF_FBTC_SLOT(20, 0xffffffff, SLOT_MIX),
92 [CXST_EBT] = __DEF_FBTC_SLOT(20, 0x55555555, SLOT_MIX),
93 [CXST_ENULL] = __DEF_FBTC_SLOT(7, 0xaaaaaaaa, SLOT_ISO),
94 [CXST_WLK] = __DEF_FBTC_SLOT(250, 0x6a5a6a5a, SLOT_MIX),
95 [CXST_W1FDD] = __DEF_FBTC_SLOT(35, 0xfafafafa, SLOT_ISO),
96 [CXST_B1FDD] = __DEF_FBTC_SLOT(100, 0xffffffff, SLOT_MIX),
97 };
98
99 static const u32 cxtbl[] = {
100 0xffffffff, /* 0 */
101 0xaaaaaaaa, /* 1 */
102 0x55555555, /* 2 */
103 0x66555555, /* 3 */
104 0x66556655, /* 4 */
105 0x5a5a5a5a, /* 5 */
106 0x5a5a5aaa, /* 6 */
107 0xaa5a5a5a, /* 7 */
108 0x6a5a5a5a, /* 8 */
109 0x6a5a5aaa, /* 9 */
110 0x6a5a6a5a, /* 10 */
111 0x6a5a6aaa, /* 11 */
112 0x6afa5afa, /* 12 */
113 0xaaaa5aaa, /* 13 */
114 0xaaffffaa, /* 14 */
115 0xaa5555aa, /* 15 */
116 0xfafafafa, /* 16 */
117 0xffffddff, /* 17 */
118 0xdaffdaff, /* 18 */
119 0xfafadafa /* 19 */
120 };
121
122 struct rtw89_btc_btf_tlv {
123 u8 type;
124 u8 len;
125 u8 val[1];
126 } __packed;
127
128 enum btc_btf_set_report_en {
129 RPT_EN_TDMA = BIT(0),
130 RPT_EN_CYCLE = BIT(1),
131 RPT_EN_MREG = BIT(2),
132 RPT_EN_BT_VER_INFO = BIT(3),
133 RPT_EN_BT_SCAN_INFO = BIT(4),
134 RPT_EN_BT_AFH_MAP = BIT(5),
135 RPT_EN_BT_DEVICE_INFO = BIT(6),
136 RPT_EN_WL_ALL = GENMASK(2, 0),
137 RPT_EN_BT_ALL = GENMASK(6, 3),
138 RPT_EN_ALL = GENMASK(6, 0),
139 };
140
141 #define BTF_SET_REPORT_VER 1
142 struct rtw89_btc_btf_set_report {
143 u8 fver;
144 __le32 enable;
145 __le32 para;
146 } __packed;
147
148 #define BTF_SET_SLOT_TABLE_VER 1
149 struct rtw89_btc_btf_set_slot_table {
150 u8 fver;
151 u8 tbl_num;
152 u8 buf[];
153 } __packed;
154
155 #define BTF_SET_MON_REG_VER 1
156 struct rtw89_btc_btf_set_mon_reg {
157 u8 fver;
158 u8 reg_num;
159 u8 buf[];
160 } __packed;
161
162 enum btc_btf_set_cx_policy {
163 CXPOLICY_TDMA = 0x0,
164 CXPOLICY_SLOT = 0x1,
165 CXPOLICY_TYPE = 0x2,
166 CXPOLICY_MAX,
167 };
168
169 enum btc_b2w_scoreboard {
170 BTC_BSCB_ACT = BIT(0),
171 BTC_BSCB_ON = BIT(1),
172 BTC_BSCB_WHQL = BIT(2),
173 BTC_BSCB_BT_S1 = BIT(3),
174 BTC_BSCB_A2DP_ACT = BIT(4),
175 BTC_BSCB_RFK_RUN = BIT(5),
176 BTC_BSCB_RFK_REQ = BIT(6),
177 BTC_BSCB_LPS = BIT(7),
178 BTC_BSCB_WLRFK = BIT(11),
179 BTC_BSCB_BT_HILNA = BIT(13),
180 BTC_BSCB_BT_CONNECT = BIT(16),
181 BTC_BSCB_PATCH_CODE = BIT(30),
182 BTC_BSCB_ALL = GENMASK(30, 0),
183 };
184
185 enum btc_phymap {
186 BTC_PHY_0 = BIT(0),
187 BTC_PHY_1 = BIT(1),
188 BTC_PHY_ALL = BIT(0) | BIT(1),
189 };
190
191 enum btc_cx_state_map {
192 BTC_WIDLE = 0,
193 BTC_WBUSY_BNOSCAN,
194 BTC_WBUSY_BSCAN,
195 BTC_WSCAN_BNOSCAN,
196 BTC_WSCAN_BSCAN,
197 BTC_WLINKING
198 };
199
200 enum btc_ant_phase {
201 BTC_ANT_WPOWERON = 0,
202 BTC_ANT_WINIT,
203 BTC_ANT_WONLY,
204 BTC_ANT_WOFF,
205 BTC_ANT_W2G,
206 BTC_ANT_W5G,
207 BTC_ANT_W25G,
208 BTC_ANT_FREERUN,
209 BTC_ANT_WRFK,
210 BTC_ANT_BRFK,
211 BTC_ANT_MAX
212 };
213
214 enum btc_plt {
215 BTC_PLT_NONE = 0,
216 BTC_PLT_LTE_RX = BIT(0),
217 BTC_PLT_GNT_BT_TX = BIT(1),
218 BTC_PLT_GNT_BT_RX = BIT(2),
219 BTC_PLT_GNT_WL = BIT(3),
220 BTC_PLT_BT = BIT(1) | BIT(2),
221 BTC_PLT_ALL = 0xf
222 };
223
224 enum btc_cx_poicy_main_type {
225 BTC_CXP_OFF = 0,
226 BTC_CXP_OFFB,
227 BTC_CXP_OFFE,
228 BTC_CXP_FIX,
229 BTC_CXP_PFIX,
230 BTC_CXP_AUTO,
231 BTC_CXP_PAUTO,
232 BTC_CXP_AUTO2,
233 BTC_CXP_PAUTO2,
234 BTC_CXP_MANUAL,
235 BTC_CXP_USERDEF0,
236 BTC_CXP_MAIN_MAX
237 };
238
239 enum btc_cx_poicy_type {
240 /* TDMA off + pri: BT > WL */
241 BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0,
242
243 /* TDMA off + pri: WL > BT */
244 BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1,
245
246 /* TDMA off + pri: BT = WL */
247 BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2,
248
249 /* TDMA off + pri: BT = WL > BT_Lo */
250 BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3,
251
252 /* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */
253 BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4,
254
255 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
256 BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5,
257
258 /* TDMA off + pri: BT_Hi > WL > BT_Lo */
259 BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 6,
260
261 /* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
262 BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 7,
263
264 /* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
265 BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 8,
266
267 /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/
268 BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
269
270 /* TDMA off + Ext-Ctrl + pri: default */
271 BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0,
272
273 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
274 BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1,
275
276 /* TDMA off + Ext-Ctrl + pri: default */
277 BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2,
278
279 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
280 BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3,
281
282 /* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */
283 BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4,
284
285 /* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */
286 BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5,
287
288 /* TDMA off + Ext-Ctrl + pri: default */
289 BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6,
290
291 /* TDMA Fix slot-0: W1:B1 = 30:30 */
292 BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0,
293
294 /* TDMA Fix slot-1: W1:B1 = 50:50 */
295 BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1,
296
297 /* TDMA Fix slot-2: W1:B1 = 20:30 */
298 BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2,
299
300 /* TDMA Fix slot-3: W1:B1 = 40:10 */
301 BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3,
302
303 /* TDMA Fix slot-4: W1:B1 = 70:10 */
304 BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4,
305
306 /* TDMA Fix slot-5: W1:B1 = 20:60 */
307 BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5,
308
309 /* TDMA Fix slot-6: W1:B1 = 30:60 */
310 BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6,
311
312 /* TDMA Fix slot-7: W1:B1 = 20:80 */
313 BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7,
314
315 /* TDMA Fix slot-8: W1:B1 = user-define */
316 BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8,
317
318 /* TDMA Fix slot-9: W1:B1 = 40:20 */
319 BTC_CXP_FIX_TD4020 = (BTC_CXP_FIX << 8) | 9,
320
321 /* TDMA Fix slot-9: W1:B1 = 40:10 */
322 BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 10,
323
324 /* PS-TDMA Fix slot-0: W1:B1 = 30:30 */
325 BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0,
326
327 /* PS-TDMA Fix slot-1: W1:B1 = 50:50 */
328 BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1,
329
330 /* PS-TDMA Fix slot-2: W1:B1 = 20:30 */
331 BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2,
332
333 /* PS-TDMA Fix slot-3: W1:B1 = 20:60 */
334 BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3,
335
336 /* PS-TDMA Fix slot-4: W1:B1 = 30:70 */
337 BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4,
338
339 /* PS-TDMA Fix slot-5: W1:B1 = 20:80 */
340 BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5,
341
342 /* PS-TDMA Fix slot-6: W1:B1 = user-define */
343 BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6,
344
345 /* TDMA Auto slot-0: W1:B1 = 50:200 */
346 BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0,
347
348 /* TDMA Auto slot-1: W1:B1 = 60:200 */
349 BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1,
350
351 /* TDMA Auto slot-2: W1:B1 = 20:200 */
352 BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2,
353
354 /* TDMA Auto slot-3: W1:B1 = user-define */
355 BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3,
356
357 /* PS-TDMA Auto slot-0: W1:B1 = 50:200 */
358 BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0,
359
360 /* PS-TDMA Auto slot-1: W1:B1 = 60:200 */
361 BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1,
362
363 /* PS-TDMA Auto slot-2: W1:B1 = 20:200 */
364 BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2,
365
366 /* PS-TDMA Auto slot-3: W1:B1 = user-define */
367 BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3,
368
369 /* TDMA Auto slot2-0: W1:B4 = 30:50 */
370 BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0,
371
372 /* TDMA Auto slot2-1: W1:B4 = 30:70 */
373 BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1,
374
375 /* TDMA Auto slot2-2: W1:B4 = 50:50 */
376 BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2,
377
378 /* TDMA Auto slot2-3: W1:B4 = 60:60 */
379 BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3,
380
381 /* TDMA Auto slot2-4: W1:B4 = 20:80 */
382 BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4,
383
384 /* TDMA Auto slot2-5: W1:B4 = user-define */
385 BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5,
386
387 /* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */
388 BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0,
389
390 /* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */
391 BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1,
392
393 /* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */
394 BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2,
395
396 /* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */
397 BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3,
398
399 /* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */
400 BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4,
401
402 /* PS-TDMA Auto slot2-5: W1:B4 = user-define */
403 BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5,
404
405 BTC_CXP_MAX = 0xffff
406 };
407
408 enum btc_wl_rfk_result {
409 BTC_WRFK_REJECT = 0,
410 BTC_WRFK_ALLOW = 1,
411 };
412
413 enum btc_coex_info_map_en {
414 BTC_COEX_INFO_CX = BIT(0),
415 BTC_COEX_INFO_WL = BIT(1),
416 BTC_COEX_INFO_BT = BIT(2),
417 BTC_COEX_INFO_DM = BIT(3),
418 BTC_COEX_INFO_MREG = BIT(4),
419 BTC_COEX_INFO_SUMMARY = BIT(5),
420 BTC_COEX_INFO_ALL = GENMASK(7, 0),
421 };
422
423 #define BTC_CXP_MASK GENMASK(15, 8)
424
425 enum btc_w2b_scoreboard {
426 BTC_WSCB_ACTIVE = BIT(0),
427 BTC_WSCB_ON = BIT(1),
428 BTC_WSCB_SCAN = BIT(2),
429 BTC_WSCB_UNDERTEST = BIT(3),
430 BTC_WSCB_RXGAIN = BIT(4),
431 BTC_WSCB_WLBUSY = BIT(7),
432 BTC_WSCB_EXTFEM = BIT(8),
433 BTC_WSCB_TDMA = BIT(9),
434 BTC_WSCB_FIX2M = BIT(10),
435 BTC_WSCB_WLRFK = BIT(11),
436 BTC_WSCB_BTRFK_GNT = BIT(12), /* not used, use mailbox to inform BT */
437 BTC_WSCB_BT_HILNA = BIT(13),
438 BTC_WSCB_BTLOG = BIT(14),
439 BTC_WSCB_ALL = GENMASK(23, 0),
440 };
441
442 enum btc_wl_link_mode {
443 BTC_WLINK_NOLINK = 0x0,
444 BTC_WLINK_2G_STA,
445 BTC_WLINK_2G_AP,
446 BTC_WLINK_2G_GO,
447 BTC_WLINK_2G_GC,
448 BTC_WLINK_2G_SCC,
449 BTC_WLINK_2G_MCC,
450 BTC_WLINK_25G_MCC,
451 BTC_WLINK_25G_DBCC,
452 BTC_WLINK_5G,
453 BTC_WLINK_2G_NAN,
454 BTC_WLINK_OTHER,
455 BTC_WLINK_MAX
456 };
457
458 enum btc_wl_mrole_type {
459 BTC_WLMROLE_NONE = 0x0,
460 BTC_WLMROLE_STA_GC,
461 BTC_WLMROLE_STA_GC_NOA,
462 BTC_WLMROLE_STA_GO,
463 BTC_WLMROLE_STA_GO_NOA,
464 BTC_WLMROLE_STA_STA,
465 BTC_WLMROLE_MAX
466 };
467
468 enum btc_bt_hid_type {
469 BTC_HID_218 = BIT(0),
470 BTC_HID_418 = BIT(1),
471 BTC_HID_BLE = BIT(2),
472 BTC_HID_RCU = BIT(3),
473 BTC_HID_RCU_VOICE = BIT(4),
474 BTC_HID_OTHER_LEGACY = BIT(5)
475 };
476
477 enum btc_reset_module {
478 BTC_RESET_CX = BIT(0),
479 BTC_RESET_DM = BIT(1),
480 BTC_RESET_CTRL = BIT(2),
481 BTC_RESET_CXDM = BIT(0) | BIT(1),
482 BTC_RESET_BTINFO = BIT(3),
483 BTC_RESET_MDINFO = BIT(4),
484 BTC_RESET_ALL = GENMASK(7, 0),
485 };
486
487 enum btc_gnt_state {
488 BTC_GNT_HW = 0,
489 BTC_GNT_SW_LO,
490 BTC_GNT_SW_HI,
491 BTC_GNT_MAX
492 };
493
494 enum btc_wl_max_tx_time {
495 BTC_MAX_TX_TIME_L1 = 500,
496 BTC_MAX_TX_TIME_L2 = 1000,
497 BTC_MAX_TX_TIME_L3 = 2000,
498 BTC_MAX_TX_TIME_DEF = 5280
499 };
500
501 enum btc_wl_max_tx_retry {
502 BTC_MAX_TX_RETRY_L1 = 7,
503 BTC_MAX_TX_RETRY_L2 = 15,
504 BTC_MAX_TX_RETRY_DEF = 31,
505 };
506
507 enum btc_reason_and_action {
508 BTC_RSN_NONE,
509 BTC_RSN_NTFY_INIT,
510 BTC_RSN_NTFY_SWBAND,
511 BTC_RSN_NTFY_WL_STA,
512 BTC_RSN_NTFY_RADIO_STATE,
513 BTC_RSN_UPDATE_BT_SCBD,
514 BTC_RSN_NTFY_WL_RFK,
515 BTC_RSN_UPDATE_BT_INFO,
516 BTC_RSN_NTFY_SCAN_START,
517 BTC_RSN_NTFY_SCAN_FINISH,
518 BTC_RSN_NTFY_SPECIFIC_PACKET,
519 BTC_RSN_NTFY_POWEROFF,
520 BTC_RSN_NTFY_ROLE_INFO,
521 BTC_RSN_CMD_SET_COEX,
522 BTC_RSN_ACT1_WORK,
523 BTC_RSN_BT_DEVINFO_WORK,
524 BTC_RSN_RFK_CHK_WORK,
525 BTC_RSN_NUM,
526 BTC_ACT_NONE = 100,
527 BTC_ACT_WL_ONLY,
528 BTC_ACT_WL_5G,
529 BTC_ACT_WL_OTHER,
530 BTC_ACT_WL_IDLE,
531 BTC_ACT_WL_NC,
532 BTC_ACT_WL_RFK,
533 BTC_ACT_WL_INIT,
534 BTC_ACT_WL_OFF,
535 BTC_ACT_FREERUN,
536 BTC_ACT_BT_WHQL,
537 BTC_ACT_BT_RFK,
538 BTC_ACT_BT_OFF,
539 BTC_ACT_BT_IDLE,
540 BTC_ACT_BT_HFP,
541 BTC_ACT_BT_HID,
542 BTC_ACT_BT_A2DP,
543 BTC_ACT_BT_A2DPSINK,
544 BTC_ACT_BT_PAN,
545 BTC_ACT_BT_A2DP_HID,
546 BTC_ACT_BT_A2DP_PAN,
547 BTC_ACT_BT_PAN_HID,
548 BTC_ACT_BT_A2DP_PAN_HID,
549 BTC_ACT_WL_25G_MCC,
550 BTC_ACT_WL_2G_MCC,
551 BTC_ACT_WL_2G_SCC,
552 BTC_ACT_WL_2G_AP,
553 BTC_ACT_WL_2G_GO,
554 BTC_ACT_WL_2G_GC,
555 BTC_ACT_WL_2G_NAN,
556 BTC_ACT_LAST,
557 BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE,
558 BTC_ACT_EXT_BIT = BIT(14),
559 BTC_POLICY_EXT_BIT = BIT(15),
560 };
561
562 #define BTC_FREERUN_ANTISO_MIN 30
563 #define BTC_TDMA_BTHID_MAX 2
564 #define BTC_BLINK_NOCONNECT 0
565 #define BTC_B1_MAX 250 /* unit ms */
566
567 static void _run_coex(struct rtw89_dev *rtwdev,
568 enum btc_reason_and_action reason);
569 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state);
570 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update);
571
572 static void _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func,
573 void *param, u16 len)
574 {
575 struct rtw89_btc *btc = &rtwdev->btc;
576 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
577 struct rtw89_btc_cx *cx = &btc->cx;
578 struct rtw89_btc_wl_info *wl = &cx->wl;
579 int ret;
580
581 if (!wl->status.map.init_ok) {
582 rtw89_debug(rtwdev, RTW89_DBG_BTC,
583 "[BTC], %s(): return by btc not init!!\n", __func__);
584 pfwinfo->cnt_h2c_fail++;
585 return;
586 } else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF &&
587 wl->status.map.rf_off == BTC_LPS_RF_OFF) ||
588 (wl->status.map.lps_pre == BTC_LPS_RF_OFF &&
589 wl->status.map.lps == BTC_LPS_RF_OFF)) {
590 rtw89_debug(rtwdev, RTW89_DBG_BTC,
591 "[BTC], %s(): return by wl off!!\n", __func__);
592 pfwinfo->cnt_h2c_fail++;
593 return;
594 }
595
596 pfwinfo->cnt_h2c++;
597
598 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, param, len,
599 false, true);
600 if (ret != 0)
601 pfwinfo->cnt_h2c_fail++;
602 }
603
604 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
605 {
606 struct rtw89_btc *btc = &rtwdev->btc;
607 struct rtw89_btc_cx *cx = &btc->cx;
608 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
609 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
610 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
611 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
612 u8 i;
613
614 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
615
616 if (type & BTC_RESET_CX)
617 memset(cx, 0, sizeof(*cx));
618 else if (type & BTC_RESET_BTINFO) /* only for BT enable */
619 memset(bt, 0, sizeof(*bt));
620
621 if (type & BTC_RESET_CTRL) {
622 memset(&btc->ctrl, 0, sizeof(btc->ctrl));
623 btc->ctrl.trace_step = FCXDEF_STEP;
624 }
625
626 /* Init Coex variables that are not zero */
627 if (type & BTC_RESET_DM) {
628 memset(&btc->dm, 0, sizeof(btc->dm));
629 memset(bt_linfo->rssi_state, 0, sizeof(bt_linfo->rssi_state));
630
631 for (i = 0; i < RTW89_PORT_NUM; i++)
632 memset(wl_linfo[i].rssi_state, 0,
633 sizeof(wl_linfo[i].rssi_state));
634
635 /* set the slot_now table to original */
636 btc->dm.tdma_now = t_def[CXTD_OFF];
637 btc->dm.tdma = t_def[CXTD_OFF];
638 memcpy(&btc->dm.slot_now, s_def, sizeof(btc->dm.slot_now));
639 memcpy(&btc->dm.slot, s_def, sizeof(btc->dm.slot));
640
641 btc->policy_len = 0;
642 btc->bt_req_len = 0;
643
644 btc->dm.coex_info_map = BTC_COEX_INFO_ALL;
645 btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF;
646 btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF;
647 }
648
649 if (type & BTC_RESET_MDINFO)
650 memset(&btc->mdinfo, 0, sizeof(btc->mdinfo));
651 }
652
653 #define BTC_FWINFO_BUF 1024
654
655 #define BTC_RPT_HDR_SIZE 3
656 #define BTC_CHK_WLSLOT_DRIFT_MAX 15
657 #define BTC_CHK_HANG_MAX 3
658
659 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt)
660 {
661 struct rtw89_btc *btc = &rtwdev->btc;
662 struct rtw89_btc_cx *cx = &btc->cx;
663 struct rtw89_btc_dm *dm = &btc->dm;
664 struct rtw89_btc_bt_info *bt = &cx->bt;
665
666 rtw89_debug(rtwdev, RTW89_DBG_BTC,
667 "[BTC], %s(): type:%d cnt:%d\n",
668 __func__, type, cnt);
669
670 switch (type) {
671 case BTC_DCNT_RPT_FREEZE:
672 if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map)
673 dm->cnt_dm[BTC_DCNT_RPT_FREEZE]++;
674 else
675 dm->cnt_dm[BTC_DCNT_RPT_FREEZE] = 0;
676
677 if (dm->cnt_dm[BTC_DCNT_RPT_FREEZE] >= BTC_CHK_HANG_MAX)
678 dm->error.map.wl_fw_hang = true;
679 else
680 dm->error.map.wl_fw_hang = false;
681
682 dm->cnt_dm[BTC_DCNT_RPT] = cnt;
683 break;
684 case BTC_DCNT_CYCLE_FREEZE:
685 if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt &&
686 (dm->tdma_now.type != CXTDMA_OFF ||
687 dm->tdma_now.ext_ctrl == CXECTL_EXT))
688 dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE]++;
689 else
690 dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE] = 0;
691
692 if (dm->cnt_dm[BTC_DCNT_CYCLE_FREEZE] >= BTC_CHK_HANG_MAX)
693 dm->error.map.cycle_hang = true;
694 else
695 dm->error.map.cycle_hang = false;
696
697 dm->cnt_dm[BTC_DCNT_CYCLE] = cnt;
698 break;
699 case BTC_DCNT_W1_FREEZE:
700 if (dm->cnt_dm[BTC_DCNT_W1] == cnt &&
701 dm->tdma_now.type != CXTDMA_OFF)
702 dm->cnt_dm[BTC_DCNT_W1_FREEZE]++;
703 else
704 dm->cnt_dm[BTC_DCNT_W1_FREEZE] = 0;
705
706 if (dm->cnt_dm[BTC_DCNT_W1_FREEZE] >= BTC_CHK_HANG_MAX)
707 dm->error.map.w1_hang = true;
708 else
709 dm->error.map.w1_hang = false;
710
711 dm->cnt_dm[BTC_DCNT_W1] = cnt;
712 break;
713 case BTC_DCNT_B1_FREEZE:
714 if (dm->cnt_dm[BTC_DCNT_B1] == cnt &&
715 dm->tdma_now.type != CXTDMA_OFF)
716 dm->cnt_dm[BTC_DCNT_B1_FREEZE]++;
717 else
718 dm->cnt_dm[BTC_DCNT_B1_FREEZE] = 0;
719
720 if (dm->cnt_dm[BTC_DCNT_B1_FREEZE] >= BTC_CHK_HANG_MAX)
721 dm->error.map.b1_hang = true;
722 else
723 dm->error.map.b1_hang = false;
724
725 dm->cnt_dm[BTC_DCNT_B1] = cnt;
726 break;
727 case BTC_DCNT_TDMA_NONSYNC:
728 if (cnt != 0) /* if tdma not sync between drv/fw */
729 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++;
730 else
731 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0;
732
733 if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX)
734 dm->error.map.tdma_no_sync = true;
735 else
736 dm->error.map.tdma_no_sync = false;
737 break;
738 case BTC_DCNT_SLOT_NONSYNC:
739 if (cnt != 0) /* if slot not sync between drv/fw */
740 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++;
741 else
742 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0;
743
744 if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX)
745 dm->error.map.tdma_no_sync = true;
746 else
747 dm->error.map.tdma_no_sync = false;
748 break;
749 case BTC_DCNT_BTCNT_FREEZE:
750 cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] +
751 cx->cnt_bt[BTC_BCNT_HIPRI_TX] +
752 cx->cnt_bt[BTC_BCNT_LOPRI_RX] +
753 cx->cnt_bt[BTC_BCNT_LOPRI_TX];
754
755 if (cnt == 0)
756 dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE]++;
757 else
758 dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] = 0;
759
760 if ((dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] >= BTC_CHK_HANG_MAX &&
761 bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_FREEZE] &&
762 !bt->enable.now))
763 _update_bt_scbd(rtwdev, false);
764 break;
765 case BTC_DCNT_WL_SLOT_DRIFT:
766 if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX)
767 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++;
768 else
769 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0;
770
771 if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
772 dm->error.map.wl_slot_drift = true;
773 else
774 dm->error.map.wl_slot_drift = false;
775 break;
776 }
777 }
778
779 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo)
780 {
781 struct rtw89_btc *btc = &rtwdev->btc;
782 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
783 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
784 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc;
785 struct rtw89_btc_fbtc_btver *pver = NULL;
786 struct rtw89_btc_fbtc_btscan *pscan = NULL;
787 struct rtw89_btc_fbtc_btafh *pafh = NULL;
788 struct rtw89_btc_fbtc_btdevinfo *pdev = NULL;
789
790 pver = (struct rtw89_btc_fbtc_btver *)pfinfo;
791 pscan = (struct rtw89_btc_fbtc_btscan *)pfinfo;
792 pafh = (struct rtw89_btc_fbtc_btafh *)pfinfo;
793 pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo;
794
795 rtw89_debug(rtwdev, RTW89_DBG_BTC,
796 "[BTC], %s(): rpt_type:%d\n",
797 __func__, rpt_type);
798
799 switch (rpt_type) {
800 case BTC_RPT_TYPE_BT_VER:
801 bt->ver_info.fw = le32_to_cpu(pver->fw_ver);
802 bt->ver_info.fw_coex = le32_get_bits(pver->coex_ver, GENMASK(7, 0));
803 bt->feature = le32_to_cpu(pver->feature);
804 break;
805 case BTC_RPT_TYPE_BT_SCAN:
806 memcpy(bt->scan_info, pscan->scan, BTC_SCAN_MAX1);
807 break;
808 case BTC_RPT_TYPE_BT_AFH:
809 memcpy(&bt_linfo->afh_map[0], pafh->afh_l, 4);
810 memcpy(&bt_linfo->afh_map[4], pafh->afh_m, 4);
811 memcpy(&bt_linfo->afh_map[8], pafh->afh_h, 2);
812 break;
813 case BTC_RPT_TYPE_BT_DEVICE:
814 a2dp->device_name = le32_to_cpu(pdev->dev_name);
815 a2dp->vendor_id = le16_to_cpu(pdev->vendor_id);
816 a2dp->flush_time = le32_to_cpu(pdev->flush_time);
817 break;
818 default:
819 break;
820 }
821 }
822
823 struct rtw89_btc_fbtc_cysta_cpu {
824 u8 fver;
825 u8 rsvd;
826 u16 cycles;
827 u16 cycles_a2dp[CXT_FLCTRL_MAX];
828 u16 a2dpept;
829 u16 a2dpeptto;
830 u16 tavg_cycle[CXT_MAX];
831 u16 tmax_cycle[CXT_MAX];
832 u16 tmaxdiff_cycle[CXT_MAX];
833 u16 tavg_a2dp[CXT_FLCTRL_MAX];
834 u16 tmax_a2dp[CXT_FLCTRL_MAX];
835 u16 tavg_a2dpept;
836 u16 tmax_a2dpept;
837 u16 tavg_lk;
838 u16 tmax_lk;
839 u32 slot_cnt[CXST_MAX];
840 u32 bcn_cnt[CXBCN_MAX];
841 u32 leakrx_cnt;
842 u32 collision_cnt;
843 u32 skip_cnt;
844 u32 exception;
845 u32 except_cnt;
846 u16 tslot_cycle[BTC_CYCLE_SLOT_MAX];
847 };
848
849 static void rtw89_btc_fbtc_cysta_to_cpu(const struct rtw89_btc_fbtc_cysta *src,
850 struct rtw89_btc_fbtc_cysta_cpu *dst)
851 {
852 #if defined(__linux__)
853 static_assert(sizeof(*src) == sizeof(*dst));
854 #elif defined(__FreeBSD__)
855 rtw89_static_assert(sizeof(*src) == sizeof(*dst));
856 #endif
857
858 #define __CPY_U8(_x) ({dst->_x = src->_x; })
859 #define __CPY_LE16(_x) ({dst->_x = le16_to_cpu(src->_x); })
860 #define __CPY_LE16S(_x) ({int _i; for (_i = 0; _i < ARRAY_SIZE(dst->_x); _i++) \
861 dst->_x[_i] = le16_to_cpu(src->_x[_i]); })
862 #define __CPY_LE32(_x) ({dst->_x = le32_to_cpu(src->_x); })
863 #define __CPY_LE32S(_x) ({int _i; for (_i = 0; _i < ARRAY_SIZE(dst->_x); _i++) \
864 dst->_x[_i] = le32_to_cpu(src->_x[_i]); })
865
866 __CPY_U8(fver);
867 __CPY_U8(rsvd);
868 __CPY_LE16(cycles);
869 __CPY_LE16S(cycles_a2dp);
870 __CPY_LE16(a2dpept);
871 __CPY_LE16(a2dpeptto);
872 __CPY_LE16S(tavg_cycle);
873 __CPY_LE16S(tmax_cycle);
874 __CPY_LE16S(tmaxdiff_cycle);
875 __CPY_LE16S(tavg_a2dp);
876 __CPY_LE16S(tmax_a2dp);
877 __CPY_LE16(tavg_a2dpept);
878 __CPY_LE16(tmax_a2dpept);
879 __CPY_LE16(tavg_lk);
880 __CPY_LE16(tmax_lk);
881 __CPY_LE32S(slot_cnt);
882 __CPY_LE32S(bcn_cnt);
883 __CPY_LE32(leakrx_cnt);
884 __CPY_LE32(collision_cnt);
885 __CPY_LE32(skip_cnt);
886 __CPY_LE32(exception);
887 __CPY_LE32(except_cnt);
888 __CPY_LE16S(tslot_cycle);
889
890 #undef __CPY_U8
891 #undef __CPY_LE16
892 #undef __CPY_LE16S
893 #undef __CPY_LE32
894 #undef __CPY_LE32S
895 }
896
897 #define BTC_LEAK_AP_TH 10
898 #define BTC_CYSTA_CHK_PERIOD 100
899
900 struct rtw89_btc_prpt {
901 u8 type;
902 __le16 len;
903 u8 content[];
904 } __packed;
905
906 static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
907 struct rtw89_btc_btf_fwinfo *pfwinfo,
908 u8 *prptbuf, u32 index)
909 {
910 const struct rtw89_chip_info *chip = rtwdev->chip;
911 struct rtw89_btc *btc = &rtwdev->btc;
912 struct rtw89_btc_dm *dm = &btc->dm;
913 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
914 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
915 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
916 struct rtw89_btc_fbtc_rpt_ctrl *prpt;
917 struct rtw89_btc_fbtc_rpt_ctrl_v1 *prpt_v1;
918 struct rtw89_btc_fbtc_cysta *pcysta_le32 = NULL;
919 struct rtw89_btc_fbtc_cysta_v1 *pcysta_v1 = NULL;
920 struct rtw89_btc_fbtc_cysta_cpu pcysta[1];
921 struct rtw89_btc_prpt *btc_prpt = NULL;
922 struct rtw89_btc_fbtc_slot *rtp_slot = NULL;
923 u8 rpt_type = 0, *rpt_content = NULL, *pfinfo = NULL;
924 u16 wl_slot_set = 0, wl_slot_real = 0;
925 u32 trace_step = btc->ctrl.trace_step, rpt_len = 0, diff_t;
926 u32 cnt_leak_slot = 0, bt_slot_real = 0, cnt_rx_imr = 0;
927 u8 i;
928
929 rtw89_debug(rtwdev, RTW89_DBG_BTC,
930 "[BTC], %s(): index:%d\n",
931 __func__, index);
932
933 if (!prptbuf) {
934 pfwinfo->err[BTFRE_INVALID_INPUT]++;
935 return 0;
936 }
937
938 btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index];
939 rpt_type = btc_prpt->type;
940 rpt_len = le16_to_cpu(btc_prpt->len);
941 rpt_content = btc_prpt->content;
942
943 rtw89_debug(rtwdev, RTW89_DBG_BTC,
944 "[BTC], %s(): rpt_type:%d\n",
945 __func__, rpt_type);
946
947 switch (rpt_type) {
948 case BTC_RPT_TYPE_CTRL:
949 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
950 if (chip->chip_id == RTL8852A) {
951 pfinfo = (u8 *)(&pfwinfo->rpt_ctrl.finfo);
952 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo);
953 } else {
954 pfinfo = (u8 *)(&pfwinfo->rpt_ctrl.finfo_v1);
955 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo_v1);
956 }
957 pcinfo->req_fver = chip->fcxbtcrpt_ver;
958 pcinfo->rx_len = rpt_len;
959 pcinfo->rx_cnt++;
960 break;
961 case BTC_RPT_TYPE_TDMA:
962 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
963 if (chip->chip_id == RTL8852A) {
964 pfinfo = (u8 *)&pfwinfo->rpt_fbtc_tdma.finfo;
965 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo);
966 } else {
967 pfinfo = (u8 *)&pfwinfo->rpt_fbtc_tdma.finfo_v1;
968 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo_v1);
969 }
970 pcinfo->req_fver = chip->fcxtdma_ver;
971 pcinfo->rx_len = rpt_len;
972 pcinfo->rx_cnt++;
973 break;
974 case BTC_RPT_TYPE_SLOT:
975 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
976 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_slots.finfo);
977 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo);
978 pcinfo->req_fver = chip->fcxslots_ver;
979 pcinfo->rx_len = rpt_len;
980 pcinfo->rx_cnt++;
981 break;
982 case BTC_RPT_TYPE_CYSTA:
983 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
984 if (chip->chip_id == RTL8852A) {
985 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_cysta.finfo);
986 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo;
987 rtw89_btc_fbtc_cysta_to_cpu(pcysta_le32, pcysta);
988 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo);
989 } else {
990 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_cysta.finfo_v1);
991 pcysta_v1 = &pfwinfo->rpt_fbtc_cysta.finfo_v1;
992 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo_v1);
993 }
994 pcinfo->req_fver = chip->fcxcysta_ver;
995 pcinfo->rx_len = rpt_len;
996 pcinfo->rx_cnt++;
997 break;
998 case BTC_RPT_TYPE_STEP:
999 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
1000 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_step.finfo);
1001 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.step[0]) *
1002 trace_step + 8;
1003 pcinfo->req_fver = chip->fcxstep_ver;
1004 pcinfo->rx_len = rpt_len;
1005 pcinfo->rx_cnt++;
1006 break;
1007 case BTC_RPT_TYPE_NULLSTA:
1008 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
1009 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_nullsta.finfo);
1010 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo);
1011 pcinfo->req_fver = chip->fcxnullsta_ver;
1012 pcinfo->rx_len = rpt_len;
1013 pcinfo->rx_cnt++;
1014 break;
1015 case BTC_RPT_TYPE_MREG:
1016 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
1017 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_mregval.finfo);
1018 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo);
1019 pcinfo->req_fver = chip->fcxmreg_ver;
1020 pcinfo->rx_len = rpt_len;
1021 pcinfo->rx_cnt++;
1022 break;
1023 case BTC_RPT_TYPE_GPIO_DBG:
1024 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
1025 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_gpio_dbg.finfo);
1026 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo);
1027 pcinfo->req_fver = chip->fcxgpiodbg_ver;
1028 pcinfo->rx_len = rpt_len;
1029 pcinfo->rx_cnt++;
1030 break;
1031 case BTC_RPT_TYPE_BT_VER:
1032 pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
1033 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btver.finfo);
1034 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo);
1035 pcinfo->req_fver = chip->fcxbtver_ver;
1036 pcinfo->rx_len = rpt_len;
1037 pcinfo->rx_cnt++;
1038 break;
1039 case BTC_RPT_TYPE_BT_SCAN:
1040 pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
1041 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btscan.finfo);
1042 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo);
1043 pcinfo->req_fver = chip->fcxbtscan_ver;
1044 pcinfo->rx_len = rpt_len;
1045 pcinfo->rx_cnt++;
1046 break;
1047 case BTC_RPT_TYPE_BT_AFH:
1048 pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
1049 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btafh.finfo);
1050 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo);
1051 pcinfo->req_fver = chip->fcxbtafh_ver;
1052 pcinfo->rx_len = rpt_len;
1053 pcinfo->rx_cnt++;
1054 break;
1055 case BTC_RPT_TYPE_BT_DEVICE:
1056 pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
1057 pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btdev.finfo);
1058 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo);
1059 pcinfo->req_fver = chip->fcxbtdevinfo_ver;
1060 pcinfo->rx_len = rpt_len;
1061 pcinfo->rx_cnt++;
1062 break;
1063 default:
1064 pfwinfo->err[BTFRE_UNDEF_TYPE]++;
1065 return 0;
1066 }
1067
1068 if (rpt_len != pcinfo->req_len) {
1069 if (rpt_type < BTC_RPT_TYPE_MAX)
1070 pfwinfo->len_mismch |= (0x1 << rpt_type);
1071 else
1072 pfwinfo->len_mismch |= BIT(31);
1073 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1074 "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n",
1075 __func__, rpt_type, rpt_len, pcinfo->req_len);
1076
1077 pcinfo->valid = 0;
1078 return 0;
1079 } else if (!pfinfo || !rpt_content || !pcinfo->req_len) {
1080 pfwinfo->err[BTFRE_EXCEPTION]++;
1081 pcinfo->valid = 0;
1082 return 0;
1083 }
1084
1085 memcpy(pfinfo, rpt_content, pcinfo->req_len);
1086 pcinfo->valid = 1;
1087
1088 if (rpt_type == BTC_RPT_TYPE_TDMA && chip->chip_id == RTL8852A) {
1089 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1090 "[BTC], %s(): check %d %zu\n", __func__,
1091 BTC_DCNT_TDMA_NONSYNC, sizeof(dm->tdma_now));
1092
1093 if (memcmp(&dm->tdma_now, &pfwinfo->rpt_fbtc_tdma.finfo,
1094 sizeof(dm->tdma_now)) != 0) {
1095 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1096 "[BTC], %s(): %d tdma_now %x %x %x %x %x %x %x %x\n",
1097 __func__, BTC_DCNT_TDMA_NONSYNC,
1098 dm->tdma_now.type, dm->tdma_now.rxflctrl,
1099 dm->tdma_now.txpause, dm->tdma_now.wtgle_n,
1100 dm->tdma_now.leak_n, dm->tdma_now.ext_ctrl,
1101 dm->tdma_now.rxflctrl_role,
1102 dm->tdma_now.option_ctrl);
1103
1104 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1105 "[BTC], %s(): %d rpt_fbtc_tdma %x %x %x %x %x %x %x %x\n",
1106 __func__, BTC_DCNT_TDMA_NONSYNC,
1107 pfwinfo->rpt_fbtc_tdma.finfo.type,
1108 pfwinfo->rpt_fbtc_tdma.finfo.rxflctrl,
1109 pfwinfo->rpt_fbtc_tdma.finfo.txpause,
1110 pfwinfo->rpt_fbtc_tdma.finfo.wtgle_n,
1111 pfwinfo->rpt_fbtc_tdma.finfo.leak_n,
1112 pfwinfo->rpt_fbtc_tdma.finfo.ext_ctrl,
1113 pfwinfo->rpt_fbtc_tdma.finfo.rxflctrl_role,
1114 pfwinfo->rpt_fbtc_tdma.finfo.option_ctrl);
1115 }
1116
1117 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
1118 memcmp(&dm->tdma_now,
1119 &pfwinfo->rpt_fbtc_tdma.finfo,
1120 sizeof(dm->tdma_now)));
1121 } else if (rpt_type == BTC_RPT_TYPE_TDMA) {
1122 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1123 "[BTC], %s(): check %d %zu\n", __func__,
1124 BTC_DCNT_TDMA_NONSYNC, sizeof(dm->tdma_now));
1125
1126 if (memcmp(&dm->tdma_now, &pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma,
1127 sizeof(dm->tdma_now)) != 0) {
1128 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1129 "[BTC], %s(): %d tdma_now %x %x %x %x %x %x %x %x\n",
1130 __func__, BTC_DCNT_TDMA_NONSYNC,
1131 dm->tdma_now.type, dm->tdma_now.rxflctrl,
1132 dm->tdma_now.txpause, dm->tdma_now.wtgle_n,
1133 dm->tdma_now.leak_n, dm->tdma_now.ext_ctrl,
1134 dm->tdma_now.rxflctrl_role,
1135 dm->tdma_now.option_ctrl);
1136 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1137 "[BTC], %s(): %d rpt_fbtc_tdma %x %x %x %x %x %x %x %x\n",
1138 __func__, BTC_DCNT_TDMA_NONSYNC,
1139 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.type,
1140 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.rxflctrl,
1141 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.txpause,
1142 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.wtgle_n,
1143 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.leak_n,
1144 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.ext_ctrl,
1145 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.rxflctrl_role,
1146 pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.option_ctrl);
1147 }
1148
1149 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
1150 memcmp(&dm->tdma_now,
1151 &pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma,
1152 sizeof(dm->tdma_now)));
1153 }
1154
1155 if (rpt_type == BTC_RPT_TYPE_SLOT) {
1156 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1157 "[BTC], %s(): check %d %zu\n",
1158 __func__, BTC_DCNT_SLOT_NONSYNC,
1159 sizeof(dm->slot_now));
1160
1161 if (memcmp(dm->slot_now, pfwinfo->rpt_fbtc_slots.finfo.slot,
1162 sizeof(dm->slot_now)) != 0) {
1163 for (i = 0; i < CXST_MAX; i++) {
1164 rtp_slot =
1165 &pfwinfo->rpt_fbtc_slots.finfo.slot[i];
1166 if (memcmp(&dm->slot_now[i], rtp_slot,
1167 sizeof(dm->slot_now[i])) != 0) {
1168 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1169 "[BTC], %s(): %d slot_now[%d] dur=0x%04x tbl=%08x type=0x%04x\n",
1170 __func__,
1171 BTC_DCNT_SLOT_NONSYNC, i,
1172 dm->slot_now[i].dur,
1173 dm->slot_now[i].cxtbl,
1174 dm->slot_now[i].cxtype);
1175
1176 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1177 "[BTC], %s(): %d rpt_fbtc_slots[%d] dur=0x%04x tbl=%08x type=0x%04x\n",
1178 __func__,
1179 BTC_DCNT_SLOT_NONSYNC, i,
1180 rtp_slot->dur,
1181 rtp_slot->cxtbl,
1182 rtp_slot->cxtype);
1183 }
1184 }
1185 }
1186 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
1187 memcmp(dm->slot_now,
1188 pfwinfo->rpt_fbtc_slots.finfo.slot,
1189 sizeof(dm->slot_now)));
1190 }
1191
1192 if (rpt_type == BTC_RPT_TYPE_CYSTA && chip->chip_id == RTL8852A &&
1193 pcysta->cycles >= BTC_CYSTA_CHK_PERIOD) {
1194 /* Check Leak-AP */
1195 if (pcysta->slot_cnt[CXST_LK] != 0 &&
1196 pcysta->leakrx_cnt != 0 && dm->tdma_now.rxflctrl) {
1197 if (pcysta->slot_cnt[CXST_LK] <
1198 BTC_LEAK_AP_TH * pcysta->leakrx_cnt)
1199 dm->leak_ap = 1;
1200 }
1201
1202 /* Check diff time between WL slot and W1/E2G slot */
1203 if (dm->tdma_now.type == CXTDMA_OFF &&
1204 dm->tdma_now.ext_ctrl == CXECTL_EXT)
1205 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_E2G].dur);
1206 else
1207 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
1208
1209 if (pcysta->tavg_cycle[CXT_WL] > wl_slot_set) {
1210 diff_t = pcysta->tavg_cycle[CXT_WL] - wl_slot_set;
1211 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1212 }
1213
1214 _chk_btc_err(rtwdev, BTC_DCNT_W1_FREEZE, pcysta->slot_cnt[CXST_W1]);
1215 _chk_btc_err(rtwdev, BTC_DCNT_W1_FREEZE, pcysta->slot_cnt[CXST_B1]);
1216 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_FREEZE, (u32)pcysta->cycles);
1217 } else if (rpt_type == BTC_RPT_TYPE_CYSTA && pcysta_v1 &&
1218 le16_to_cpu(pcysta_v1->cycles) >= BTC_CYSTA_CHK_PERIOD) {
1219 cnt_leak_slot = le32_to_cpu(pcysta_v1->slot_cnt[CXST_LK]);
1220 cnt_rx_imr = le32_to_cpu(pcysta_v1->leak_slot.cnt_rximr);
1221 /* Check Leak-AP */
1222 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
1223 dm->tdma_now.rxflctrl) {
1224 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
1225 dm->leak_ap = 1;
1226 }
1227
1228 /* Check diff time between real WL slot and W1 slot */
1229 if (dm->tdma_now.type == CXTDMA_OFF) {
1230 wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
1231 wl_slot_real = le16_to_cpu(pcysta_v1->cycle_time.tavg[CXT_WL]);
1232 if (wl_slot_real > wl_slot_set) {
1233 diff_t = wl_slot_real - wl_slot_set;
1234 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1235 }
1236 }
1237
1238 /* Check diff time between real BT slot and EBT/E5G slot */
1239 if (dm->tdma_now.type == CXTDMA_OFF &&
1240 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
1241 btc->bt_req_len != 0) {
1242 bt_slot_real = le16_to_cpu(pcysta_v1->cycle_time.tavg[CXT_BT]);
1243
1244 if (btc->bt_req_len > bt_slot_real) {
1245 diff_t = btc->bt_req_len - bt_slot_real;
1246 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
1247 }
1248 }
1249
1250 _chk_btc_err(rtwdev, BTC_DCNT_W1_FREEZE,
1251 le32_to_cpu(pcysta_v1->slot_cnt[CXST_W1]));
1252 _chk_btc_err(rtwdev, BTC_DCNT_B1_FREEZE,
1253 le32_to_cpu(pcysta_v1->slot_cnt[CXST_B1]));
1254 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_FREEZE,
1255 (u32)le16_to_cpu(pcysta_v1->cycles));
1256 }
1257
1258 if (rpt_type == BTC_RPT_TYPE_CTRL && chip->chip_id == RTL8852A) {
1259 prpt = &pfwinfo->rpt_ctrl.finfo;
1260 btc->fwinfo.rpt_en_map = prpt->rpt_enable;
1261 wl->ver_info.fw_coex = prpt->wl_fw_coex_ver;
1262 wl->ver_info.fw = prpt->wl_fw_ver;
1263 dm->wl_fw_cx_offload = !!prpt->wl_fw_cx_offload;
1264
1265 _chk_btc_err(rtwdev, BTC_DCNT_RPT_FREEZE,
1266 pfwinfo->event[BTF_EVNT_RPT]);
1267
1268 /* To avoid I/O if WL LPS or power-off */
1269 if (wl->status.map.lps != BTC_LPS_RF_OFF && !wl->status.map.rf_off) {
1270 rtwdev->chip->ops->btc_update_bt_cnt(rtwdev);
1271 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_FREEZE, 0);
1272
1273 btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1274 rtw89_mac_get_plt_cnt(rtwdev, RTW89_MAC_0);
1275 }
1276 } else if (rpt_type == BTC_RPT_TYPE_CTRL) {
1277 prpt_v1 = &pfwinfo->rpt_ctrl.finfo_v1;
1278 btc->fwinfo.rpt_en_map = le32_to_cpu(prpt_v1->rpt_info.en);
1279 wl->ver_info.fw_coex = le32_to_cpu(prpt_v1->wl_fw_info.cx_ver);
1280 wl->ver_info.fw = le32_to_cpu(prpt_v1->wl_fw_info.fw_ver);
1281 dm->wl_fw_cx_offload = !!le32_to_cpu(prpt_v1->wl_fw_info.cx_offload);
1282
1283 for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
1284 memcpy(&dm->gnt.band[i], &prpt_v1->gnt_val[i],
1285 sizeof(dm->gnt.band[i]));
1286
1287 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_HI_TX]);
1288 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_HI_RX]);
1289 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_LO_TX]);
1290 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_LO_RX]);
1291 btc->cx.cnt_bt[BTC_BCNT_POLUT] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_POLLUTED]);
1292
1293 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_FREEZE, 0);
1294 _chk_btc_err(rtwdev, BTC_DCNT_RPT_FREEZE,
1295 pfwinfo->event[BTF_EVNT_RPT]);
1296
1297 if (le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
1298 bt->rfk_info.map.timeout = 1;
1299 else
1300 bt->rfk_info.map.timeout = 0;
1301
1302 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1303 }
1304
1305 if (rpt_type >= BTC_RPT_TYPE_BT_VER &&
1306 rpt_type <= BTC_RPT_TYPE_BT_DEVICE)
1307 _update_bt_report(rtwdev, rpt_type, pfinfo);
1308
1309 return (rpt_len + BTC_RPT_HDR_SIZE);
1310 }
1311
1312 static void _parse_btc_report(struct rtw89_dev *rtwdev,
1313 struct rtw89_btc_btf_fwinfo *pfwinfo,
1314 u8 *pbuf, u32 buf_len)
1315 {
1316 struct rtw89_btc_prpt *btc_prpt = NULL;
1317 u32 index = 0, rpt_len = 0;
1318
1319 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1320 "[BTC], %s(): buf_len:%d\n",
1321 __func__, buf_len);
1322
1323 while (pbuf) {
1324 btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index];
1325 if (index + 2 >= BTC_FWINFO_BUF)
1326 break;
1327 /* At least 3 bytes: type(1) & len(2) */
1328 rpt_len = le16_to_cpu(btc_prpt->len);
1329 if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len)
1330 break;
1331
1332 rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index);
1333 if (!rpt_len)
1334 break;
1335 index += rpt_len;
1336 }
1337 }
1338
1339 #define BTC_TLV_HDR_LEN 2
1340
1341 static void _append_tdma(struct rtw89_dev *rtwdev)
1342 {
1343 const struct rtw89_chip_info *chip = rtwdev->chip;
1344 struct rtw89_btc *btc = &rtwdev->btc;
1345 struct rtw89_btc_dm *dm = &btc->dm;
1346 struct rtw89_btc_btf_tlv *tlv;
1347 struct rtw89_btc_fbtc_tdma *v;
1348 struct rtw89_btc_fbtc_tdma_v1 *v1;
1349 u16 len = btc->policy_len;
1350
1351 if (!btc->update_policy_force &&
1352 !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) {
1353 rtw89_debug(rtwdev,
1354 RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n",
1355 __func__);
1356 return;
1357 }
1358
1359 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
1360 tlv->type = CXPOLICY_TDMA;
1361 if (chip->chip_id == RTL8852A) {
1362 v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0];
1363 tlv->len = sizeof(*v);
1364 memcpy(v, &dm->tdma, sizeof(*v));
1365 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
1366 } else {
1367 tlv->len = sizeof(*v1);
1368 v1 = (struct rtw89_btc_fbtc_tdma_v1 *)&tlv->val[0];
1369 v1->fver = chip->fcxtdma_ver;
1370 v1->tdma = dm->tdma;
1371 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v1);
1372 }
1373
1374 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1375 "[BTC], %s(): type:%d, rxflctrl=%d, txpause=%d, wtgle_n=%d, leak_n=%d, ext_ctrl=%d\n",
1376 __func__, dm->tdma.type, dm->tdma.rxflctrl,
1377 dm->tdma.txpause, dm->tdma.wtgle_n, dm->tdma.leak_n,
1378 dm->tdma.ext_ctrl);
1379 }
1380
1381 static void _append_slot(struct rtw89_dev *rtwdev)
1382 {
1383 struct rtw89_btc *btc = &rtwdev->btc;
1384 struct rtw89_btc_dm *dm = &btc->dm;
1385 struct rtw89_btc_btf_tlv *tlv = NULL;
1386 struct btc_fbtc_1slot *v = NULL;
1387 u16 len = 0;
1388 u8 i, cnt = 0;
1389
1390 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1391 "[BTC], %s(): A:btc->policy_len = %d\n",
1392 __func__, btc->policy_len);
1393
1394 for (i = 0; i < CXST_MAX; i++) {
1395 if (!btc->update_policy_force &&
1396 !memcmp(&dm->slot[i], &dm->slot_now[i],
1397 sizeof(dm->slot[i])))
1398 continue;
1399
1400 len = btc->policy_len;
1401
1402 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
1403 v = (struct btc_fbtc_1slot *)&tlv->val[0];
1404 tlv->type = CXPOLICY_SLOT;
1405 tlv->len = sizeof(*v);
1406
1407 v->fver = FCXONESLOT_VER;
1408 v->sid = i;
1409 v->slot = dm->slot[i];
1410
1411 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1412 "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n",
1413 __func__, i, dm->slot[i].dur, dm->slot[i].cxtbl,
1414 dm->slot[i].cxtype);
1415 cnt++;
1416
1417 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
1418 }
1419
1420 if (cnt > 0)
1421 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1422 "[BTC], %s(): slot update (cnt=%d)!!\n",
1423 __func__, cnt);
1424 }
1425
1426 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
1427 u32 rpt_map, bool rpt_state)
1428 {
1429 struct rtw89_btc *btc = &rtwdev->btc;
1430 struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo;
1431 struct rtw89_btc_btf_set_report r = {0};
1432 u32 val = 0;
1433
1434 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1435 "[BTC], %s(): rpt_map=%x, rpt_state=%x\n",
1436 __func__, rpt_map, rpt_state);
1437
1438 if (rpt_state)
1439 val = fwinfo->rpt_en_map | rpt_map;
1440 else
1441 val = fwinfo->rpt_en_map & ~rpt_map;
1442
1443 if (val == fwinfo->rpt_en_map)
1444 return;
1445
1446 fwinfo->rpt_en_map = val;
1447
1448 r.fver = BTF_SET_REPORT_VER;
1449 r.enable = cpu_to_le32(val);
1450 r.para = cpu_to_le32(rpt_state);
1451
1452 _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r, sizeof(r));
1453 }
1454
1455 static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev, u8 num,
1456 struct rtw89_btc_fbtc_slot *s)
1457 {
1458 struct rtw89_btc_btf_set_slot_table *tbl = NULL;
1459 u8 *ptr = NULL;
1460 u16 n = 0;
1461
1462 n = sizeof(*s) * num + sizeof(*tbl);
1463 tbl = kmalloc(n, GFP_KERNEL);
1464 if (!tbl)
1465 return;
1466
1467 tbl->fver = BTF_SET_SLOT_TABLE_VER;
1468 tbl->tbl_num = num;
1469 ptr = &tbl->buf[0];
1470 memcpy(ptr, s, num * sizeof(*s));
1471
1472 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
1473
1474 kfree(tbl);
1475 }
1476
1477 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
1478 {
1479 const struct rtw89_chip_info *chip = rtwdev->chip;
1480 struct rtw89_btc_btf_set_mon_reg *monreg = NULL;
1481 u8 n, *ptr = NULL, ulen;
1482 u16 sz = 0;
1483
1484 n = chip->mon_reg_num;
1485
1486 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1487 "[BTC], %s(): mon_reg_num=%d\n", __func__, n);
1488 if (n > CXMREG_MAX) {
1489 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1490 "[BTC], %s(): mon reg count %d > %d\n",
1491 __func__, n, CXMREG_MAX);
1492 return;
1493 }
1494
1495 ulen = sizeof(struct rtw89_btc_fbtc_mreg);
1496 sz = (ulen * n) + sizeof(*monreg);
1497 monreg = kmalloc(sz, GFP_KERNEL);
1498 if (!monreg)
1499 return;
1500
1501 monreg->fver = BTF_SET_MON_REG_VER;
1502 monreg->reg_num = n;
1503 ptr = &monreg->buf[0];
1504 memcpy(ptr, chip->mon_reg, n * ulen);
1505 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1506 "[BTC], %s(): sz=%d ulen=%d n=%d\n",
1507 __func__, sz, ulen, n);
1508
1509 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, (u8 *)monreg, sz);
1510 kfree(monreg);
1511 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
1512 }
1513
1514 static void _update_dm_step(struct rtw89_dev *rtwdev,
1515 enum btc_reason_and_action reason_or_action)
1516 {
1517 struct rtw89_btc *btc = &rtwdev->btc;
1518 struct rtw89_btc_dm *dm = &btc->dm;
1519
1520 /* use ring-structure to store dm step */
1521 dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action;
1522 dm->dm_step.step_pos++;
1523
1524 if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) {
1525 dm->dm_step.step_pos = 0;
1526 dm->dm_step.step_ov = true;
1527 }
1528 }
1529
1530 static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
1531 enum btc_reason_and_action action)
1532 {
1533 struct rtw89_btc *btc = &rtwdev->btc;
1534 struct rtw89_btc_dm *dm = &btc->dm;
1535
1536 dm->run_action = action;
1537
1538 _update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT);
1539 _update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT);
1540
1541 btc->policy_len = 0;
1542 btc->policy_type = policy_type;
1543
1544 _append_tdma(rtwdev);
1545 _append_slot(rtwdev);
1546
1547 if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN)
1548 return;
1549
1550 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1551 "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n",
1552 __func__, action, policy_type, btc->policy_len);
1553
1554 if (dm->tdma.rxflctrl == CXFLC_NULLP ||
1555 dm->tdma.rxflctrl == CXFLC_QOSNULL)
1556 btc->lps = 1;
1557 else
1558 btc->lps = 0;
1559
1560 if (btc->lps == 1)
1561 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
1562
1563 _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY,
1564 btc->policy, btc->policy_len);
1565
1566 memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now));
1567 memcpy(&dm->slot_now, &dm->slot, sizeof(dm->slot_now));
1568
1569 if (btc->update_policy_force)
1570 btc->update_policy_force = false;
1571
1572 if (btc->lps == 0)
1573 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
1574 }
1575
1576 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 type)
1577 {
1578 const struct rtw89_chip_info *chip = rtwdev->chip;
1579
1580 switch (type) {
1581 case CXDRVINFO_INIT:
1582 rtw89_fw_h2c_cxdrv_init(rtwdev);
1583 break;
1584 case CXDRVINFO_ROLE:
1585 if (chip->chip_id == RTL8852A)
1586 rtw89_fw_h2c_cxdrv_role(rtwdev);
1587 else
1588 rtw89_fw_h2c_cxdrv_role_v1(rtwdev);
1589 break;
1590 case CXDRVINFO_CTRL:
1591 rtw89_fw_h2c_cxdrv_ctrl(rtwdev);
1592 break;
1593 case CXDRVINFO_RFK:
1594 rtw89_fw_h2c_cxdrv_rfk(rtwdev);
1595 break;
1596 default:
1597 break;
1598 }
1599 }
1600
1601 static
1602 void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len)
1603 {
1604 struct rtw89_btc *btc = &rtwdev->btc;
1605 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
1606
1607 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1608 "[BTC], %s(): evt_id:%d len:%d\n",
1609 __func__, evt_id, len);
1610
1611 if (!len || !data)
1612 return;
1613
1614 switch (evt_id) {
1615 case BTF_EVNT_RPT:
1616 _parse_btc_report(rtwdev, pfwinfo, data, len);
1617 break;
1618 default:
1619 break;
1620 }
1621 }
1622
1623 static void _set_gnt_wl(struct rtw89_dev *rtwdev, u8 phy_map, u8 state)
1624 {
1625 struct rtw89_btc *btc = &rtwdev->btc;
1626 struct rtw89_btc_dm *dm = &btc->dm;
1627 struct rtw89_mac_ax_gnt *g = dm->gnt.band;
1628 u8 i;
1629
1630 if (phy_map > BTC_PHY_ALL)
1631 return;
1632
1633 for (i = 0; i < RTW89_PHY_MAX; i++) {
1634 if (!(phy_map & BIT(i)))
1635 continue;
1636
1637 switch (state) {
1638 case BTC_GNT_HW:
1639 g[i].gnt_wl_sw_en = 0;
1640 g[i].gnt_wl = 0;
1641 break;
1642 case BTC_GNT_SW_LO:
1643 g[i].gnt_wl_sw_en = 1;
1644 g[i].gnt_wl = 0;
1645 break;
1646 case BTC_GNT_SW_HI:
1647 g[i].gnt_wl_sw_en = 1;
1648 g[i].gnt_wl = 1;
1649 break;
1650 }
1651 }
1652
1653 rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
1654 }
1655
1656 #define BTC_TDMA_WLROLE_MAX 2
1657
1658 static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable)
1659 {
1660 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1661 "[BTC], %s(): set bt %s wlan_act\n", __func__,
1662 enable ? "ignore" : "do not ignore");
1663
1664 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1);
1665 }
1666
1667 #define WL_TX_POWER_NO_BTC_CTRL GENMASK(31, 0)
1668 #define WL_TX_POWER_ALL_TIME GENMASK(15, 0)
1669 #define WL_TX_POWER_WITH_BT GENMASK(31, 16)
1670 #define WL_TX_POWER_INT_PART GENMASK(8, 2)
1671 #define WL_TX_POWER_FRA_PART GENMASK(1, 0)
1672 #define B_BTC_WL_TX_POWER_SIGN BIT(7)
1673 #define B_TSSI_WL_TX_POWER_SIGN BIT(8)
1674
1675 static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level)
1676 {
1677 const struct rtw89_chip_info *chip = rtwdev->chip;
1678 struct rtw89_btc *btc = &rtwdev->btc;
1679 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1680 u32 pwr_val;
1681
1682 if (wl->rf_para.tx_pwr_freerun == level)
1683 return;
1684
1685 wl->rf_para.tx_pwr_freerun = level;
1686 btc->dm.rf_trx_para.wl_tx_power = level;
1687
1688 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1689 "[BTC], %s(): level = %d\n",
1690 __func__, level);
1691
1692 if (level == RTW89_BTC_WL_DEF_TX_PWR) {
1693 pwr_val = WL_TX_POWER_NO_BTC_CTRL;
1694 } else { /* only apply "force tx power" */
1695 pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level);
1696 if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR)
1697 pwr_val = RTW89_BTC_WL_DEF_TX_PWR;
1698
1699 if (level & B_BTC_WL_TX_POWER_SIGN)
1700 pwr_val |= B_TSSI_WL_TX_POWER_SIGN;
1701 pwr_val |= WL_TX_POWER_WITH_BT;
1702 }
1703
1704 chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val);
1705 }
1706
1707 static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
1708 {
1709 struct rtw89_btc *btc = &rtwdev->btc;
1710 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1711
1712 if (wl->rf_para.rx_gain_freerun == level)
1713 return;
1714
1715 wl->rf_para.rx_gain_freerun = level;
1716 btc->dm.rf_trx_para.wl_rx_gain = level;
1717
1718 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1719 "[BTC], %s(): level = %d\n",
1720 __func__, level);
1721 }
1722
1723 static void _set_bt_tx_power(struct rtw89_dev *rtwdev, u8 level)
1724 {
1725 struct rtw89_btc *btc = &rtwdev->btc;
1726 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1727 u8 buf;
1728
1729 if (bt->rf_para.tx_pwr_freerun == level)
1730 return;
1731
1732 bt->rf_para.tx_pwr_freerun = level;
1733 btc->dm.rf_trx_para.bt_tx_power = level;
1734
1735 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1736 "[BTC], %s(): level = %d\n",
1737 __func__, level);
1738
1739 buf = (s8)(-level);
1740 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_TX_PWR, &buf, 1);
1741 }
1742
1743 #define BTC_BT_RX_NORMAL_LVL 7
1744
1745 static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, u8 level)
1746 {
1747 struct rtw89_btc *btc = &rtwdev->btc;
1748 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1749
1750 if (bt->rf_para.rx_gain_freerun == level ||
1751 level > BTC_BT_RX_NORMAL_LVL)
1752 return;
1753
1754 bt->rf_para.rx_gain_freerun = level;
1755 btc->dm.rf_trx_para.bt_rx_gain = level;
1756
1757 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1758 "[BTC], %s(): level = %d\n",
1759 __func__, level);
1760
1761 if (level == BTC_BT_RX_NORMAL_LVL)
1762 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, false);
1763 else
1764 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
1765
1766 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_LNA_CONSTRAIN, &level, 1);
1767 }
1768
1769 static void _set_rf_trx_para(struct rtw89_dev *rtwdev)
1770 {
1771 const struct rtw89_chip_info *chip = rtwdev->chip;
1772 struct rtw89_btc *btc = &rtwdev->btc;
1773 struct rtw89_btc_dm *dm = &btc->dm;
1774 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1775 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1776 struct rtw89_btc_rf_trx_para para;
1777 u32 wl_stb_chg = 0;
1778 u8 level_id = 0;
1779
1780 if (!dm->freerun) {
1781 dm->trx_para_level = 0;
1782 chip->ops->btc_bt_aci_imp(rtwdev);
1783 }
1784
1785 level_id = (u8)dm->trx_para_level;
1786
1787 if (level_id >= chip->rf_para_dlink_num ||
1788 level_id >= chip->rf_para_ulink_num) {
1789 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1790 "[BTC], %s(): invalid level_id: %d\n",
1791 __func__, level_id);
1792 return;
1793 }
1794
1795 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
1796 para = chip->rf_para_ulink[level_id];
1797 else
1798 para = chip->rf_para_dlink[level_id];
1799
1800 if (para.wl_tx_power != RTW89_BTC_WL_DEF_TX_PWR)
1801 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1802 "[BTC], %s(): wl_tx_power=%d\n",
1803 __func__, para.wl_tx_power);
1804 _set_wl_tx_power(rtwdev, para.wl_tx_power);
1805 _set_wl_rx_gain(rtwdev, para.wl_rx_gain);
1806 _set_bt_tx_power(rtwdev, para.bt_tx_power);
1807 _set_bt_rx_gain(rtwdev, para.bt_rx_gain);
1808
1809 if (bt->enable.now == 0 || wl->status.map.rf_off == 1 ||
1810 wl->status.map.lps == BTC_LPS_RF_OFF)
1811 wl_stb_chg = 0;
1812 else
1813 wl_stb_chg = 1;
1814
1815 if (wl_stb_chg != dm->wl_stb_chg) {
1816 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1817 "[BTC], %s(): wl_stb_chg=%d\n",
1818 __func__, wl_stb_chg);
1819 dm->wl_stb_chg = wl_stb_chg;
1820 chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg);
1821 }
1822 }
1823
1824 static void _update_btc_state_map(struct rtw89_dev *rtwdev)
1825 {
1826 struct rtw89_btc *btc = &rtwdev->btc;
1827 struct rtw89_btc_cx *cx = &btc->cx;
1828 struct rtw89_btc_wl_info *wl = &cx->wl;
1829 struct rtw89_btc_bt_info *bt = &cx->bt;
1830 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
1831
1832 if (wl->status.map.connecting || wl->status.map._4way ||
1833 wl->status.map.roaming) {
1834 cx->state_map = BTC_WLINKING;
1835 } else if (wl->status.map.scan) { /* wl scan */
1836 if (bt_linfo->status.map.inq_pag)
1837 cx->state_map = BTC_WSCAN_BSCAN;
1838 else
1839 cx->state_map = BTC_WSCAN_BNOSCAN;
1840 } else if (wl->status.map.busy) { /* only busy */
1841 if (bt_linfo->status.map.inq_pag)
1842 cx->state_map = BTC_WBUSY_BSCAN;
1843 else
1844 cx->state_map = BTC_WBUSY_BNOSCAN;
1845 } else { /* wl idle */
1846 cx->state_map = BTC_WIDLE;
1847 }
1848 }
1849
1850 static void _set_bt_afh_info(struct rtw89_dev *rtwdev)
1851 {
1852 const struct rtw89_chip_info *chip = rtwdev->chip;
1853 struct rtw89_btc *btc = &rtwdev->btc;
1854 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1855 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1856 struct rtw89_btc_bt_link_info *b = &bt->link_info;
1857 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
1858 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
1859 struct rtw89_btc_wl_active_role *r;
1860 struct rtw89_btc_wl_active_role_v1 *r1;
1861 u8 en = 0, i, ch = 0, bw = 0;
1862 u8 mode, connect_cnt;
1863
1864 if (btc->ctrl.manual || wl->status.map.scan)
1865 return;
1866
1867 if (chip->chip_id == RTL8852A) {
1868 mode = wl_rinfo->link_mode;
1869 connect_cnt = wl_rinfo->connect_cnt;
1870 } else {
1871 mode = wl_rinfo_v1->link_mode;
1872 connect_cnt = wl_rinfo_v1->connect_cnt;
1873 }
1874
1875 if (wl->status.map.rf_off || bt->whql_test ||
1876 mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_5G ||
1877 connect_cnt > BTC_TDMA_WLROLE_MAX) {
1878 en = false;
1879 } else if (mode == BTC_WLINK_2G_MCC || mode == BTC_WLINK_2G_SCC) {
1880 en = true;
1881 /* get p2p channel */
1882 for (i = 0; i < RTW89_PORT_NUM; i++) {
1883 r = &wl_rinfo->active_role[i];
1884 r1 = &wl_rinfo_v1->active_role_v1[i];
1885
1886 if (chip->chip_id == RTL8852A &&
1887 (r->role == RTW89_WIFI_ROLE_P2P_GO ||
1888 r->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
1889 ch = r->ch;
1890 bw = r->bw;
1891 break;
1892 } else if (chip->chip_id != RTL8852A &&
1893 (r1->role == RTW89_WIFI_ROLE_P2P_GO ||
1894 r1->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
1895 ch = r1->ch;
1896 bw = r1->bw;
1897 break;
1898 }
1899 }
1900 } else {
1901 en = true;
1902 /* get 2g channel */
1903 for (i = 0; i < RTW89_PORT_NUM; i++) {
1904 r = &wl_rinfo->active_role[i];
1905 r1 = &wl_rinfo_v1->active_role_v1[i];
1906
1907 if (chip->chip_id == RTL8852A &&
1908 r->connected && r->band == RTW89_BAND_2G) {
1909 ch = r->ch;
1910 bw = r->bw;
1911 break;
1912 } else if (chip->chip_id != RTL8852A &&
1913 r1->connected && r1->band == RTW89_BAND_2G) {
1914 ch = r1->ch;
1915 bw = r1->bw;
1916 break;
1917 }
1918 }
1919 }
1920
1921 switch (bw) {
1922 case RTW89_CHANNEL_WIDTH_20:
1923 bw = 20 + chip->afh_guard_ch * 2;
1924 break;
1925 case RTW89_CHANNEL_WIDTH_40:
1926 bw = 40 + chip->afh_guard_ch * 2;
1927 break;
1928 case RTW89_CHANNEL_WIDTH_5:
1929 bw = 5 + chip->afh_guard_ch * 2;
1930 break;
1931 case RTW89_CHANNEL_WIDTH_10:
1932 bw = 10 + chip->afh_guard_ch * 2;
1933 break;
1934 default:
1935 bw = 0;
1936 en = false; /* turn off AFH info if BW > 40 */
1937 break;
1938 }
1939
1940 if (wl->afh_info.en == en &&
1941 wl->afh_info.ch == ch &&
1942 wl->afh_info.bw == bw &&
1943 b->profile_cnt.last == b->profile_cnt.now) {
1944 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1945 "[BTC], %s(): return because no change!\n",
1946 __func__);
1947 return;
1948 }
1949
1950 wl->afh_info.en = en;
1951 wl->afh_info.ch = ch;
1952 wl->afh_info.bw = bw;
1953
1954 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3);
1955
1956 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1957 "[BTC], %s(): en=%d, ch=%d, bw=%d\n",
1958 __func__, en, ch, bw);
1959 btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++;
1960 }
1961
1962 static bool _check_freerun(struct rtw89_dev *rtwdev)
1963 {
1964 struct rtw89_btc *btc = &rtwdev->btc;
1965 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1966 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1967 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
1968 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
1969 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
1970 struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc;
1971
1972 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
1973 btc->dm.trx_para_level = 0;
1974 return false;
1975 }
1976
1977 /* The below is dedicated antenna case */
1978 if (wl_rinfo->connect_cnt > BTC_TDMA_WLROLE_MAX ||
1979 wl_rinfo_v1->connect_cnt > BTC_TDMA_WLROLE_MAX) {
1980 btc->dm.trx_para_level = 5;
1981 return true;
1982 }
1983
1984 if (bt_linfo->profile_cnt.now == 0) {
1985 btc->dm.trx_para_level = 5;
1986 return true;
1987 }
1988
1989 if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) {
1990 btc->dm.trx_para_level = 5;
1991 return true;
1992 }
1993
1994 /* TODO get isolation by BT psd */
1995 if (btc->mdinfo.ant.isolation >= BTC_FREERUN_ANTISO_MIN) {
1996 btc->dm.trx_para_level = 5;
1997 return true;
1998 }
1999
2000 if (!wl->status.map.busy) {/* wl idle -> freerun */
2001 btc->dm.trx_para_level = 5;
2002 return true;
2003 } else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */
2004 btc->dm.trx_para_level = 0;
2005 return false;
2006 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
2007 if (wl->rssi_level == 0 && bt_linfo->rssi > 31) {
2008 btc->dm.trx_para_level = 6;
2009 return true;
2010 } else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) {
2011 btc->dm.trx_para_level = 7;
2012 return true;
2013 }
2014 btc->dm.trx_para_level = 0;
2015 return false;
2016 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) {
2017 if (bt_linfo->rssi > 28) {
2018 btc->dm.trx_para_level = 6;
2019 return true;
2020 }
2021 }
2022
2023 btc->dm.trx_para_level = 0;
2024 return false;
2025 }
2026
2027 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; })
2028 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; })
2029 #define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; })
2030 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; })
2031
2032 #define _slot_set(btc, sid, dura, tbl, type) \
2033 do { \
2034 typeof(sid) _sid = (sid); \
2035 typeof(btc) _btc = (btc); \
2036 _btc->dm.slot[_sid].dur = cpu_to_le16(dura);\
2037 _btc->dm.slot[_sid].cxtbl = cpu_to_le32(tbl); \
2038 _btc->dm.slot[_sid].cxtype = cpu_to_le16(type); \
2039 } while (0)
2040
2041 #define _slot_set_dur(btc, sid, dura) (btc)->dm.slot[sid].dur = cpu_to_le16(dura)
2042 #define _slot_set_tbl(btc, sid, tbl) (btc)->dm.slot[sid].cxtbl = cpu_to_le32(tbl)
2043 #define _slot_set_type(btc, sid, type) (btc)->dm.slot[sid].cxtype = cpu_to_le16(type)
2044
2045 struct btc_btinfo_lb2 {
2046 u8 connect: 1;
2047 u8 sco_busy: 1;
2048 u8 inq_pag: 1;
2049 u8 acl_busy: 1;
2050 u8 hfp: 1;
2051 u8 hid: 1;
2052 u8 a2dp: 1;
2053 u8 pan: 1;
2054 };
2055
2056 struct btc_btinfo_lb3 {
2057 u8 retry: 4;
2058 u8 cqddr: 1;
2059 u8 inq: 1;
2060 u8 mesh_busy: 1;
2061 u8 pag: 1;
2062 };
2063
2064 struct btc_btinfo_hb0 {
2065 s8 rssi;
2066 };
2067
2068 struct btc_btinfo_hb1 {
2069 u8 ble_connect: 1;
2070 u8 reinit: 1;
2071 u8 relink: 1;
2072 u8 igno_wl: 1;
2073 u8 voice: 1;
2074 u8 ble_scan: 1;
2075 u8 role_sw: 1;
2076 u8 multi_link: 1;
2077 };
2078
2079 struct btc_btinfo_hb2 {
2080 u8 pan_active: 1;
2081 u8 afh_update: 1;
2082 u8 a2dp_active: 1;
2083 u8 slave: 1;
2084 u8 hid_slot: 2;
2085 u8 hid_cnt: 2;
2086 };
2087
2088 struct btc_btinfo_hb3 {
2089 u8 a2dp_bitpool: 6;
2090 u8 tx_3m: 1;
2091 u8 a2dp_sink: 1;
2092 };
2093
2094 union btc_btinfo {
2095 u8 val;
2096 struct btc_btinfo_lb2 lb2;
2097 struct btc_btinfo_lb3 lb3;
2098 struct btc_btinfo_hb0 hb0;
2099 struct btc_btinfo_hb1 hb1;
2100 struct btc_btinfo_hb2 hb2;
2101 struct btc_btinfo_hb3 hb3;
2102 };
2103
2104 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
2105 enum btc_reason_and_action action)
2106 {
2107 const struct rtw89_chip_info *chip = rtwdev->chip;
2108
2109 chip->ops->btc_set_policy(rtwdev, policy_type);
2110 _fw_set_policy(rtwdev, policy_type, action);
2111 }
2112
2113 #define BTC_B1_MAX 250 /* unit ms */
2114 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type)
2115 {
2116 struct rtw89_btc *btc = &rtwdev->btc;
2117 struct rtw89_btc_dm *dm = &btc->dm;
2118 struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
2119 struct rtw89_btc_fbtc_slot *s = dm->slot;
2120 u8 type;
2121 u32 tbl_w1, tbl_b1, tbl_b4;
2122
2123 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
2124 if (btc->cx.wl.status.map._4way)
2125 tbl_w1 = cxtbl[1];
2126 else
2127 tbl_w1 = cxtbl[8];
2128 tbl_b1 = cxtbl[3];
2129 tbl_b4 = cxtbl[3];
2130 } else {
2131 tbl_w1 = cxtbl[16];
2132 tbl_b1 = cxtbl[17];
2133 tbl_b4 = cxtbl[17];
2134 }
2135
2136 type = (u8)((policy_type & BTC_CXP_MASK) >> 8);
2137 btc->bt_req_en = false;
2138
2139 switch (type) {
2140 case BTC_CXP_USERDEF0:
2141 *t = t_def[CXTD_OFF];
2142 s[CXST_OFF] = s_def[CXST_OFF];
2143 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
2144 btc->update_policy_force = true;
2145 break;
2146 case BTC_CXP_OFF: /* TDMA off */
2147 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
2148 *t = t_def[CXTD_OFF];
2149 s[CXST_OFF] = s_def[CXST_OFF];
2150
2151 switch (policy_type) {
2152 case BTC_CXP_OFF_BT:
2153 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
2154 break;
2155 case BTC_CXP_OFF_WL:
2156 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
2157 break;
2158 case BTC_CXP_OFF_EQ0:
2159 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
2160 break;
2161 case BTC_CXP_OFF_EQ1:
2162 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
2163 break;
2164 case BTC_CXP_OFF_EQ2:
2165 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
2166 break;
2167 case BTC_CXP_OFF_EQ3:
2168 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
2169 break;
2170 case BTC_CXP_OFF_BWB0:
2171 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
2172 break;
2173 case BTC_CXP_OFF_BWB1:
2174 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
2175 break;
2176 }
2177 break;
2178 case BTC_CXP_OFFB: /* TDMA off + beacon protect */
2179 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
2180 *t = t_def[CXTD_OFF_B2];
2181 s[CXST_OFF] = s_def[CXST_OFF];
2182 switch (policy_type) {
2183 case BTC_CXP_OFFB_BWB0:
2184 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
2185 break;
2186 }
2187 break;
2188 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
2189 btc->bt_req_en = true;
2190 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2191 *t = t_def[CXTD_OFF_EXT];
2192 switch (policy_type) {
2193 case BTC_CXP_OFFE_DEF:
2194 s[CXST_E2G] = s_def[CXST_E2G];
2195 s[CXST_E5G] = s_def[CXST_E5G];
2196 s[CXST_EBT] = s_def[CXST_EBT];
2197 s[CXST_ENULL] = s_def[CXST_ENULL];
2198 break;
2199 case BTC_CXP_OFFE_DEF2:
2200 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
2201 s[CXST_E5G] = s_def[CXST_E5G];
2202 s[CXST_EBT] = s_def[CXST_EBT];
2203 s[CXST_ENULL] = s_def[CXST_ENULL];
2204 break;
2205 }
2206 break;
2207 case BTC_CXP_FIX: /* TDMA Fix-Slot */
2208 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2209 *t = t_def[CXTD_FIX];
2210 switch (policy_type) {
2211 case BTC_CXP_FIX_TD3030:
2212 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2213 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2214 break;
2215 case BTC_CXP_FIX_TD5050:
2216 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2217 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
2218 break;
2219 case BTC_CXP_FIX_TD2030:
2220 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2221 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2222 break;
2223 case BTC_CXP_FIX_TD4010:
2224 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
2225 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
2226 break;
2227 case BTC_CXP_FIX_TD4020:
2228 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_MIX);
2229 _slot_set(btc, CXST_B1, 20, tbl_b1, SLOT_MIX);
2230 break;
2231 case BTC_CXP_FIX_TD7010:
2232 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
2233 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
2234 break;
2235 case BTC_CXP_FIX_TD2060:
2236 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2237 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2238 break;
2239 case BTC_CXP_FIX_TD3060:
2240 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2241 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2242 break;
2243 case BTC_CXP_FIX_TD2080:
2244 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2245 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
2246 break;
2247 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
2248 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2249 tbl_w1, SLOT_ISO);
2250 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2251 tbl_b1, SLOT_MIX);
2252 break;
2253 }
2254 break;
2255 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
2256 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2257 *t = t_def[CXTD_PFIX];
2258 if (btc->cx.wl.role_info.role_map.role.ap)
2259 _tdma_set_flctrl(btc, CXFLC_QOSNULL);
2260
2261 switch (policy_type) {
2262 case BTC_CXP_PFIX_TD3030:
2263 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2264 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2265 break;
2266 case BTC_CXP_PFIX_TD5050:
2267 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2268 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
2269 break;
2270 case BTC_CXP_PFIX_TD2030:
2271 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2272 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2273 break;
2274 case BTC_CXP_PFIX_TD2060:
2275 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2276 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2277 break;
2278 case BTC_CXP_PFIX_TD3070:
2279 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2280 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2281 break;
2282 case BTC_CXP_PFIX_TD2080:
2283 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2284 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
2285 break;
2286 }
2287 break;
2288 case BTC_CXP_AUTO: /* TDMA Auto-Slot */
2289 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2290 *t = t_def[CXTD_AUTO];
2291 switch (policy_type) {
2292 case BTC_CXP_AUTO_TD50B1:
2293 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2294 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2295 break;
2296 case BTC_CXP_AUTO_TD60B1:
2297 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2298 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2299 break;
2300 case BTC_CXP_AUTO_TD20B1:
2301 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2302 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2303 break;
2304 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
2305 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2306 tbl_w1, SLOT_ISO);
2307 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2308 tbl_b1, SLOT_MIX);
2309 break;
2310 }
2311 break;
2312 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
2313 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2314 *t = t_def[CXTD_PAUTO];
2315 switch (policy_type) {
2316 case BTC_CXP_PAUTO_TD50B1:
2317 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2318 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2319 break;
2320 case BTC_CXP_PAUTO_TD60B1:
2321 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2322 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2323 break;
2324 case BTC_CXP_PAUTO_TD20B1:
2325 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2326 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2327 break;
2328 case BTC_CXP_PAUTO_TDW1B1:
2329 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2330 tbl_w1, SLOT_ISO);
2331 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2332 tbl_b1, SLOT_MIX);
2333 break;
2334 }
2335 break;
2336 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
2337 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2338 *t = t_def[CXTD_AUTO2];
2339 switch (policy_type) {
2340 case BTC_CXP_AUTO2_TD3050:
2341 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2342 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2343 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2344 break;
2345 case BTC_CXP_AUTO2_TD3070:
2346 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2347 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
2348 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2349 break;
2350 case BTC_CXP_AUTO2_TD5050:
2351 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2352 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2353 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2354 break;
2355 case BTC_CXP_AUTO2_TD6060:
2356 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2357 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
2358 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2359 break;
2360 case BTC_CXP_AUTO2_TD2080:
2361 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2362 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
2363 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2364 break;
2365 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
2366 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2367 tbl_w1, SLOT_ISO);
2368 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
2369 tbl_b4, SLOT_MIX);
2370 break;
2371 }
2372 break;
2373 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
2374 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2375 *t = t_def[CXTD_PAUTO2];
2376 switch (policy_type) {
2377 case BTC_CXP_PAUTO2_TD3050:
2378 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2379 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2380 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2381 break;
2382 case BTC_CXP_PAUTO2_TD3070:
2383 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2384 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
2385 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2386 break;
2387 case BTC_CXP_PAUTO2_TD5050:
2388 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2389 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2390 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2391 break;
2392 case BTC_CXP_PAUTO2_TD6060:
2393 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2394 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
2395 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2396 break;
2397 case BTC_CXP_PAUTO2_TD2080:
2398 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2399 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
2400 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2401 break;
2402 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
2403 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2404 tbl_w1, SLOT_ISO);
2405 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
2406 tbl_b4, SLOT_MIX);
2407 break;
2408 }
2409 break;
2410 }
2411 }
2412 EXPORT_SYMBOL(rtw89_btc_set_policy);
2413
2414 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
2415 {
2416 struct rtw89_btc *btc = &rtwdev->btc;
2417 struct rtw89_btc_dm *dm = &btc->dm;
2418 struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
2419 struct rtw89_btc_fbtc_slot *s = dm->slot;
2420 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1;
2421 struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
2422 struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc;
2423 u8 type, null_role;
2424 u32 tbl_w1, tbl_b1, tbl_b4;
2425
2426 type = FIELD_GET(BTC_CXP_MASK, policy_type);
2427
2428 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
2429 if (btc->cx.wl.status.map._4way)
2430 tbl_w1 = cxtbl[1];
2431 else if (hid->exist && hid->type == BTC_HID_218)
2432 tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */
2433 else
2434 tbl_w1 = cxtbl[8];
2435
2436 if (dm->leak_ap &&
2437 (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) {
2438 tbl_b1 = cxtbl[3];
2439 tbl_b4 = cxtbl[3];
2440 } else if (hid->exist && hid->type == BTC_HID_218) {
2441 tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */
2442 tbl_b4 = cxtbl[4];
2443 } else {
2444 tbl_b1 = cxtbl[2];
2445 tbl_b4 = cxtbl[2];
2446 }
2447 } else {
2448 tbl_w1 = cxtbl[16];
2449 tbl_b1 = cxtbl[17];
2450 tbl_b4 = cxtbl[17];
2451 }
2452
2453 btc->bt_req_en = false;
2454
2455 switch (type) {
2456 case BTC_CXP_USERDEF0:
2457 btc->update_policy_force = true;
2458 *t = t_def[CXTD_OFF];
2459 s[CXST_OFF] = s_def[CXST_OFF];
2460 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
2461 break;
2462 case BTC_CXP_OFF: /* TDMA off */
2463 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
2464 *t = t_def[CXTD_OFF];
2465 s[CXST_OFF] = s_def[CXST_OFF];
2466
2467 switch (policy_type) {
2468 case BTC_CXP_OFF_BT:
2469 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
2470 break;
2471 case BTC_CXP_OFF_WL:
2472 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
2473 break;
2474 case BTC_CXP_OFF_EQ0:
2475 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
2476 break;
2477 case BTC_CXP_OFF_EQ1:
2478 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
2479 break;
2480 case BTC_CXP_OFF_EQ2:
2481 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
2482 break;
2483 case BTC_CXP_OFF_EQ3:
2484 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
2485 break;
2486 case BTC_CXP_OFF_BWB0:
2487 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
2488 break;
2489 case BTC_CXP_OFF_BWB1:
2490 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
2491 break;
2492 case BTC_CXP_OFF_BWB2:
2493 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
2494 break;
2495 default:
2496 break;
2497 }
2498 break;
2499 case BTC_CXP_OFFB: /* TDMA off + beacon protect */
2500 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
2501 *t = t_def[CXTD_OFF_B2];
2502 s[CXST_OFF] = s_def[CXST_OFF];
2503
2504 switch (policy_type) {
2505 case BTC_CXP_OFFB_BWB0:
2506 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
2507 break;
2508 default:
2509 break;
2510 }
2511 break;
2512 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
2513 btc->bt_req_en = true;
2514 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2515 *t = t_def[CXTD_OFF_EXT];
2516
2517 /* To avoid wl-s0 tx break by hid/hfp tx */
2518 if (hid->exist || hfp->exist)
2519 tbl_w1 = cxtbl[16];
2520
2521 switch (policy_type) {
2522 case BTC_CXP_OFFE_DEF:
2523 s[CXST_E2G] = s_def[CXST_E2G];
2524 s[CXST_E5G] = s_def[CXST_E5G];
2525 s[CXST_EBT] = s_def[CXST_EBT];
2526 s[CXST_ENULL] = s_def[CXST_ENULL];
2527 break;
2528 case BTC_CXP_OFFE_DEF2:
2529 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
2530 s[CXST_E5G] = s_def[CXST_E5G];
2531 s[CXST_EBT] = s_def[CXST_EBT];
2532 s[CXST_ENULL] = s_def[CXST_ENULL];
2533 break;
2534 default:
2535 break;
2536 }
2537 break;
2538 case BTC_CXP_FIX: /* TDMA Fix-Slot */
2539 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2540 *t = t_def[CXTD_FIX];
2541
2542 switch (policy_type) {
2543 case BTC_CXP_FIX_TD3030:
2544 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2545 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2546 break;
2547 case BTC_CXP_FIX_TD5050:
2548 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2549 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
2550 break;
2551 case BTC_CXP_FIX_TD2030:
2552 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2553 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2554 break;
2555 case BTC_CXP_FIX_TD4010:
2556 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
2557 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
2558 break;
2559 case BTC_CXP_FIX_TD4010ISO:
2560 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
2561 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
2562 break;
2563 case BTC_CXP_FIX_TD7010:
2564 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
2565 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
2566 break;
2567 case BTC_CXP_FIX_TD2060:
2568 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2569 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2570 break;
2571 case BTC_CXP_FIX_TD3060:
2572 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2573 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2574 break;
2575 case BTC_CXP_FIX_TD2080:
2576 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2577 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
2578 break;
2579 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
2580 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2581 tbl_w1, SLOT_ISO);
2582 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2583 tbl_b1, SLOT_MIX);
2584 break;
2585 default:
2586 break;
2587 }
2588 break;
2589 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
2590 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2591 *t = t_def[CXTD_PFIX];
2592
2593 switch (policy_type) {
2594 case BTC_CXP_PFIX_TD3030:
2595 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2596 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2597 break;
2598 case BTC_CXP_PFIX_TD5050:
2599 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2600 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
2601 break;
2602 case BTC_CXP_PFIX_TD2030:
2603 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2604 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
2605 break;
2606 case BTC_CXP_PFIX_TD2060:
2607 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2608 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2609 break;
2610 case BTC_CXP_PFIX_TD3070:
2611 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2612 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
2613 break;
2614 case BTC_CXP_PFIX_TD2080:
2615 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2616 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
2617 break;
2618 case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */
2619 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2620 tbl_w1, SLOT_ISO);
2621 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2622 tbl_b1, SLOT_MIX);
2623 break;
2624 default:
2625 break;
2626 }
2627 break;
2628 case BTC_CXP_AUTO: /* TDMA Auto-Slot */
2629 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2630 *t = t_def[CXTD_AUTO];
2631
2632 switch (policy_type) {
2633 case BTC_CXP_AUTO_TD50B1:
2634 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2635 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2636 break;
2637 case BTC_CXP_AUTO_TD60B1:
2638 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2639 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2640 break;
2641 case BTC_CXP_AUTO_TD20B1:
2642 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2643 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2644 break;
2645 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
2646 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2647 tbl_w1, SLOT_ISO);
2648 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2649 tbl_b1, SLOT_MIX);
2650 break;
2651 default:
2652 break;
2653 }
2654 break;
2655 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
2656 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2657 *t = t_def[CXTD_PAUTO];
2658
2659 switch (policy_type) {
2660 case BTC_CXP_PAUTO_TD50B1:
2661 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2662 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2663 break;
2664 case BTC_CXP_PAUTO_TD60B1:
2665 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2666 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2667 break;
2668 case BTC_CXP_PAUTO_TD20B1:
2669 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2670 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2671 break;
2672 case BTC_CXP_PAUTO_TDW1B1:
2673 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2674 tbl_w1, SLOT_ISO);
2675 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2676 tbl_b1, SLOT_MIX);
2677 break;
2678 default:
2679 break;
2680 }
2681 break;
2682 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
2683 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2684 *t = t_def[CXTD_AUTO2];
2685
2686 switch (policy_type) {
2687 case BTC_CXP_AUTO2_TD3050:
2688 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2689 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2690 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2691 break;
2692 case BTC_CXP_AUTO2_TD3070:
2693 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2694 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2695 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
2696 break;
2697 case BTC_CXP_AUTO2_TD5050:
2698 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2699 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2700 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2701 break;
2702 case BTC_CXP_AUTO2_TD6060:
2703 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2704 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2705 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
2706 break;
2707 case BTC_CXP_AUTO2_TD2080:
2708 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2709 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2710 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
2711 break;
2712 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
2713 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2714 tbl_w1, SLOT_ISO);
2715 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2716 tbl_b1, SLOT_MIX);
2717 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
2718 tbl_b4, SLOT_MIX);
2719 break;
2720 default:
2721 break;
2722 }
2723 break;
2724 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
2725 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
2726 *t = t_def[CXTD_PAUTO2];
2727
2728 switch (policy_type) {
2729 case BTC_CXP_PAUTO2_TD3050:
2730 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2731 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2732 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2733 break;
2734 case BTC_CXP_PAUTO2_TD3070:
2735 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
2736 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2737 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
2738 break;
2739 case BTC_CXP_PAUTO2_TD5050:
2740 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
2741 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2742 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
2743 break;
2744 case BTC_CXP_PAUTO2_TD6060:
2745 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
2746 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2747 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
2748 break;
2749 case BTC_CXP_PAUTO2_TD2080:
2750 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
2751 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
2752 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
2753 break;
2754 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
2755 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
2756 tbl_w1, SLOT_ISO);
2757 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
2758 tbl_b1, SLOT_MIX);
2759 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
2760 tbl_b4, SLOT_MIX);
2761 break;
2762 default:
2763 break;
2764 }
2765 break;
2766 }
2767
2768 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) {
2769 null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) |
2770 FIELD_PREP(0xf0, dm->wl_scc.null_role2);
2771 _tdma_set_flctrl_role(btc, null_role);
2772 }
2773
2774 /* enter leak_slot after each null-1 */
2775 if (dm->leak_ap && dm->tdma.leak_n > 1)
2776 _tdma_set_lek(btc, 1);
2777
2778 if (dm->tdma_instant_excute) {
2779 btc->dm.tdma.option_ctrl |= BIT(0);
2780 btc->update_policy_force = true;
2781 }
2782 }
2783 EXPORT_SYMBOL(rtw89_btc_set_policy_v1);
2784
2785 static void _set_gnt_bt(struct rtw89_dev *rtwdev, u8 phy_map, u8 state)
2786 {
2787 struct rtw89_btc *btc = &rtwdev->btc;
2788 struct rtw89_btc_dm *dm = &btc->dm;
2789 struct rtw89_mac_ax_gnt *g = dm->gnt.band;
2790 u8 i;
2791
2792 if (phy_map > BTC_PHY_ALL)
2793 return;
2794
2795 for (i = 0; i < RTW89_PHY_MAX; i++) {
2796 if (!(phy_map & BIT(i)))
2797 continue;
2798
2799 switch (state) {
2800 case BTC_GNT_HW:
2801 g[i].gnt_bt_sw_en = 0;
2802 g[i].gnt_bt = 0;
2803 break;
2804 case BTC_GNT_SW_LO:
2805 g[i].gnt_bt_sw_en = 1;
2806 g[i].gnt_bt = 0;
2807 break;
2808 case BTC_GNT_SW_HI:
2809 g[i].gnt_bt_sw_en = 1;
2810 g[i].gnt_bt = 1;
2811 break;
2812 }
2813 }
2814
2815 rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
2816 }
2817
2818 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
2819 u8 tx_val, u8 rx_val)
2820 {
2821 struct rtw89_mac_ax_plt plt;
2822
2823 plt.band = RTW89_MAC_0;
2824 plt.tx = tx_val;
2825 plt.rx = rx_val;
2826
2827 if (phy_map & BTC_PHY_0)
2828 rtw89_mac_cfg_plt(rtwdev, &plt);
2829
2830 if (!rtwdev->dbcc_en)
2831 return;
2832
2833 plt.band = RTW89_MAC_1;
2834 if (phy_map & BTC_PHY_1)
2835 rtw89_mac_cfg_plt(rtwdev, &plt);
2836 }
2837
2838 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
2839 u8 phy_map, u8 type)
2840 {
2841 struct rtw89_btc *btc = &rtwdev->btc;
2842 struct rtw89_btc_dm *dm = &btc->dm;
2843 struct rtw89_btc_cx *cx = &btc->cx;
2844 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2845 struct rtw89_btc_bt_info *bt = &cx->bt;
2846 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
2847 u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0;
2848 u32 ant_path_type;
2849
2850 ant_path_type = ((phy_map << 8) + type);
2851
2852 if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
2853 btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
2854 btc->dm.run_reason == BTC_RSN_CMD_SET_COEX)
2855 force_exec = FC_EXEC;
2856
2857 if (!force_exec && ant_path_type == dm->set_ant_path) {
2858 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2859 "[BTC], %s(): return by no change!!\n",
2860 __func__);
2861 return;
2862 } else if (bt->rfk_info.map.run) {
2863 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2864 "[BTC], %s(): return by bt rfk!!\n", __func__);
2865 return;
2866 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
2867 wl->rfk_info.state != BTC_WRFK_STOP) {
2868 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2869 "[BTC], %s(): return by wl rfk!!\n", __func__);
2870 return;
2871 }
2872
2873 dm->set_ant_path = ant_path_type;
2874
2875 rtw89_debug(rtwdev,
2876 RTW89_DBG_BTC,
2877 "[BTC], %s(): path=0x%x, set_type=0x%x\n",
2878 __func__, phy_map, dm->set_ant_path & 0xff);
2879
2880 switch (type) {
2881 case BTC_ANT_WPOWERON:
2882 rtw89_chip_cfg_ctrl_path(rtwdev, false);
2883 break;
2884 case BTC_ANT_WINIT:
2885 if (bt->enable.now) {
2886 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_LO);
2887 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_HI);
2888 } else {
2889 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
2890 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_LO);
2891 }
2892 rtw89_chip_cfg_ctrl_path(rtwdev, true);
2893 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT);
2894 break;
2895 case BTC_ANT_WONLY:
2896 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
2897 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_LO);
2898 rtw89_chip_cfg_ctrl_path(rtwdev, true);
2899 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
2900 break;
2901 case BTC_ANT_WOFF:
2902 rtw89_chip_cfg_ctrl_path(rtwdev, false);
2903 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
2904 break;
2905 case BTC_ANT_W2G:
2906 rtw89_chip_cfg_ctrl_path(rtwdev, true);
2907 if (rtwdev->dbcc_en) {
2908 for (i = 0; i < RTW89_PHY_MAX; i++) {
2909 b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G);
2910
2911 gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
2912 _set_gnt_wl(rtwdev, BIT(i), gnt_wl_ctrl);
2913
2914 gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
2915 /* BT should control by GNT_BT if WL_2G at S0 */
2916 if (i == 1 &&
2917 wl_dinfo->real_band[0] == RTW89_BAND_2G &&
2918 wl_dinfo->real_band[1] == RTW89_BAND_5G)
2919 gnt_bt_ctrl = BTC_GNT_HW;
2920 _set_gnt_bt(rtwdev, BIT(i), gnt_bt_ctrl);
2921
2922 plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE;
2923 _set_bt_plut(rtwdev, BIT(i),
2924 plt_ctrl, plt_ctrl);
2925 }
2926 } else {
2927 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_HW);
2928 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_HW);
2929 _set_bt_plut(rtwdev, BTC_PHY_ALL,
2930 BTC_PLT_BT, BTC_PLT_BT);
2931 }
2932 break;
2933 case BTC_ANT_W5G:
2934 rtw89_chip_cfg_ctrl_path(rtwdev, true);
2935 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
2936 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_HW);
2937 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
2938 break;
2939 case BTC_ANT_W25G:
2940 rtw89_chip_cfg_ctrl_path(rtwdev, true);
2941 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_HW);
2942 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_HW);
2943 _set_bt_plut(rtwdev, BTC_PHY_ALL,
2944 BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
2945 break;
2946 case BTC_ANT_FREERUN:
2947 rtw89_chip_cfg_ctrl_path(rtwdev, true);
2948 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
2949 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_HI);
2950 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
2951 break;
2952 case BTC_ANT_WRFK:
2953 rtw89_chip_cfg_ctrl_path(rtwdev, true);
2954 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_HI);
2955 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_LO);
2956 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
2957 break;
2958 case BTC_ANT_BRFK:
2959 rtw89_chip_cfg_ctrl_path(rtwdev, false);
2960 _set_gnt_wl(rtwdev, phy_map, BTC_GNT_SW_LO);
2961 _set_gnt_bt(rtwdev, phy_map, BTC_GNT_SW_HI);
2962 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
2963 break;
2964 default:
2965 break;
2966 }
2967 }
2968
2969 static void _action_wl_only(struct rtw89_dev *rtwdev)
2970 {
2971 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
2972 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY);
2973 }
2974
2975 static void _action_wl_init(struct rtw89_dev *rtwdev)
2976 {
2977 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
2978
2979 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT);
2980 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT);
2981 }
2982
2983 static void _action_wl_off(struct rtw89_dev *rtwdev)
2984 {
2985 struct rtw89_btc *btc = &rtwdev->btc;
2986 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2987
2988 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
2989
2990 if (wl->status.map.rf_off || btc->dm.bt_only)
2991 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF);
2992
2993 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
2994 }
2995
2996 static void _action_freerun(struct rtw89_dev *rtwdev)
2997 {
2998 struct rtw89_btc *btc = &rtwdev->btc;
2999
3000 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
3001
3002 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN);
3003 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN);
3004
3005 btc->dm.freerun = true;
3006 }
3007
3008 static void _action_bt_whql(struct rtw89_dev *rtwdev)
3009 {
3010 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
3011
3012 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3013 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL);
3014 }
3015
3016 static void _action_bt_off(struct rtw89_dev *rtwdev)
3017 {
3018 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
3019
3020 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
3021 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF);
3022 }
3023
3024 static void _action_bt_idle(struct rtw89_dev *rtwdev)
3025 {
3026 struct rtw89_btc *btc = &rtwdev->btc;
3027 struct rtw89_btc_bt_link_info *b = &btc->cx.bt.link_info;
3028
3029 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3030
3031 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
3032 switch (btc->cx.state_map) {
3033 case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/
3034 if (b->profile_cnt.now > 0)
3035 _set_policy(rtwdev, BTC_CXP_FIX_TD4010,
3036 BTC_ACT_BT_IDLE);
3037 else
3038 _set_policy(rtwdev, BTC_CXP_FIX_TD4020,
3039 BTC_ACT_BT_IDLE);
3040 break;
3041 case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */
3042 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050,
3043 BTC_ACT_BT_IDLE);
3044 break;
3045 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */
3046 if (b->profile_cnt.now > 0)
3047 _set_policy(rtwdev, BTC_CXP_FIX_TD4010,
3048 BTC_ACT_BT_IDLE);
3049 else
3050 _set_policy(rtwdev, BTC_CXP_FIX_TD4020,
3051 BTC_ACT_BT_IDLE);
3052 break;
3053 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */
3054 _set_policy(rtwdev, BTC_CXP_FIX_TD5050,
3055 BTC_ACT_BT_IDLE);
3056 break;
3057 case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */
3058 _set_policy(rtwdev, BTC_CXP_FIX_TD7010,
3059 BTC_ACT_BT_IDLE);
3060 break;
3061 case BTC_WIDLE: /* wl-idle + bt-idle */
3062 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE);
3063 break;
3064 }
3065 } else { /* dedicated-antenna */
3066 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE);
3067 }
3068 }
3069
3070 static void _action_bt_hfp(struct rtw89_dev *rtwdev)
3071 {
3072 struct rtw89_btc *btc = &rtwdev->btc;
3073
3074 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3075
3076 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
3077 if (btc->cx.wl.status.map._4way)
3078 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP);
3079 else
3080 _set_policy(rtwdev, BTC_CXP_OFF_BWB0, BTC_ACT_BT_HFP);
3081 } else {
3082 _set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP);
3083 }
3084 }
3085
3086 static void _action_bt_hid(struct rtw89_dev *rtwdev)
3087 {
3088 struct rtw89_btc *btc = &rtwdev->btc;
3089
3090 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3091
3092 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) /* shared-antenna */
3093 if (btc->cx.wl.status.map._4way)
3094 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HID);
3095 else
3096 _set_policy(rtwdev, BTC_CXP_OFF_BWB0, BTC_ACT_BT_HID);
3097 else /* dedicated-antenna */
3098 _set_policy(rtwdev, BTC_CXP_OFF_EQ3, BTC_ACT_BT_HID);
3099 }
3100
3101 static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
3102 {
3103 struct rtw89_btc *btc = &rtwdev->btc;
3104 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
3105 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
3106 struct rtw89_btc_dm *dm = &btc->dm;
3107
3108 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3109
3110 switch (btc->cx.state_map) {
3111 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
3112 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
3113 dm->slot_dur[CXST_W1] = 40;
3114 dm->slot_dur[CXST_B1] = 200;
3115 _set_policy(rtwdev,
3116 BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
3117 } else {
3118 _set_policy(rtwdev,
3119 BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP);
3120 }
3121 break;
3122 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
3123 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP);
3124 break;
3125 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */
3126 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP);
3127 break;
3128 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
3129 case BTC_WLINKING: /* wl-connecting + bt-A2DP */
3130 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
3131 dm->slot_dur[CXST_W1] = 40;
3132 dm->slot_dur[CXST_B1] = 200;
3133 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
3134 BTC_ACT_BT_A2DP);
3135 } else {
3136 _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
3137 BTC_ACT_BT_A2DP);
3138 }
3139 break;
3140 case BTC_WIDLE: /* wl-idle + bt-A2DP */
3141 _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP);
3142 break;
3143 }
3144 }
3145
3146 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev)
3147 {
3148 struct rtw89_btc *btc = &rtwdev->btc;
3149
3150 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3151
3152 switch (btc->cx.state_map) {
3153 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */
3154 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK);
3155 break;
3156 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */
3157 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK);
3158 break;
3159 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */
3160 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK);
3161 break;
3162 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */
3163 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK);
3164 break;
3165 case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */
3166 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
3167 break;
3168 case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */
3169 _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK);
3170 break;
3171 }
3172 }
3173
3174 static void _action_bt_pan(struct rtw89_dev *rtwdev)
3175 {
3176 struct rtw89_btc *btc = &rtwdev->btc;
3177
3178 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3179
3180 switch (btc->cx.state_map) {
3181 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */
3182 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
3183 break;
3184 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */
3185 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN);
3186 break;
3187 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */
3188 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN);
3189 break;
3190 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */
3191 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN);
3192 break;
3193 case BTC_WLINKING: /* wl-connecting + bt-PAN */
3194 _set_policy(rtwdev, BTC_CXP_FIX_TD4020, BTC_ACT_BT_PAN);
3195 break;
3196 case BTC_WIDLE: /* wl-idle + bt-pan */
3197 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN);
3198 break;
3199 }
3200 }
3201
3202 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
3203 {
3204 struct rtw89_btc *btc = &rtwdev->btc;
3205 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
3206 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
3207 struct rtw89_btc_dm *dm = &btc->dm;
3208
3209 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3210
3211 switch (btc->cx.state_map) {
3212 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */
3213 case BTC_WIDLE: /* wl-idle + bt-A2DP */
3214 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
3215 dm->slot_dur[CXST_W1] = 40;
3216 dm->slot_dur[CXST_B1] = 200;
3217 _set_policy(rtwdev,
3218 BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
3219 } else {
3220 _set_policy(rtwdev,
3221 BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP_HID);
3222 }
3223 break;
3224 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */
3225 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
3226 break;
3227
3228 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */
3229 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
3230 break;
3231 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */
3232 case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */
3233 if (a2dp.vendor_id == 0x4c || dm->leak_ap) {
3234 dm->slot_dur[CXST_W1] = 40;
3235 dm->slot_dur[CXST_B1] = 200;
3236 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
3237 BTC_ACT_BT_A2DP_HID);
3238 } else {
3239 _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
3240 BTC_ACT_BT_A2DP_HID);
3241 }
3242 break;
3243 }
3244 }
3245
3246 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev)
3247 {
3248 struct rtw89_btc *btc = &rtwdev->btc;
3249
3250 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3251
3252 switch (btc->cx.state_map) {
3253 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */
3254 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
3255 break;
3256 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */
3257 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
3258 break;
3259 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */
3260 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN);
3261 break;
3262 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */
3263 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
3264 break;
3265 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */
3266 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN);
3267 break;
3268 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */
3269 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN);
3270 break;
3271 }
3272 }
3273
3274 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev)
3275 {
3276 struct rtw89_btc *btc = &rtwdev->btc;
3277
3278 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3279
3280 switch (btc->cx.state_map) {
3281 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */
3282 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID);
3283 break;
3284 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */
3285 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID);
3286 break;
3287 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */
3288 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID);
3289 break;
3290 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */
3291 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID);
3292 break;
3293 case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */
3294 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID);
3295 break;
3296 case BTC_WIDLE: /* wl-idle + bt-PAN+HID */
3297 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID);
3298 break;
3299 }
3300 }
3301
3302 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev)
3303 {
3304 struct rtw89_btc *btc = &rtwdev->btc;
3305
3306 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3307
3308 switch (btc->cx.state_map) {
3309 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */
3310 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
3311 BTC_ACT_BT_A2DP_PAN_HID);
3312 break;
3313 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */
3314 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
3315 BTC_ACT_BT_A2DP_PAN_HID);
3316 break;
3317 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */
3318 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070,
3319 BTC_ACT_BT_A2DP_PAN_HID);
3320 break;
3321 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */
3322 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */
3323 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050,
3324 BTC_ACT_BT_A2DP_PAN_HID);
3325 break;
3326 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */
3327 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080,
3328 BTC_ACT_BT_A2DP_PAN_HID);
3329 break;
3330 }
3331 }
3332
3333 static void _action_wl_5g(struct rtw89_dev *rtwdev)
3334 {
3335 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
3336 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G);
3337 }
3338
3339 static void _action_wl_other(struct rtw89_dev *rtwdev)
3340 {
3341 struct rtw89_btc *btc = &rtwdev->btc;
3342
3343 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3344
3345 if (btc->mdinfo.ant.type == BTC_ANT_SHARED)
3346 _set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER);
3347 else
3348 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER);
3349 }
3350
3351 static void _action_wl_nc(struct rtw89_dev *rtwdev)
3352 {
3353 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3354 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC);
3355 }
3356
3357 static void _action_wl_rfk(struct rtw89_dev *rtwdev)
3358 {
3359 struct rtw89_btc *btc = &rtwdev->btc;
3360 struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info;
3361
3362 if (rfk.state != BTC_WRFK_START)
3363 return;
3364
3365 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n",
3366 __func__, rfk.band);
3367
3368 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
3369 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK);
3370 }
3371
3372 static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
3373 {
3374 const struct rtw89_chip_info *chip = rtwdev->chip;
3375 struct rtw89_btc *btc = &rtwdev->btc;
3376 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3377 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3378 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3379 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
3380 bool is_btg;
3381 u8 mode;
3382
3383 if (btc->ctrl.manual)
3384 return;
3385
3386 if (chip->chip_id == RTL8852A)
3387 mode = wl_rinfo->link_mode;
3388 else
3389 mode = wl_rinfo_v1->link_mode;
3390
3391 /* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */
3392 if (mode == BTC_WLINK_5G) /* always 0 if 5G */
3393 is_btg = false;
3394 else if (mode == BTC_WLINK_25G_DBCC &&
3395 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
3396 is_btg = false;
3397 else
3398 is_btg = true;
3399
3400 if (btc->dm.run_reason != BTC_RSN_NTFY_INIT &&
3401 is_btg == btc->dm.wl_btg_rx)
3402 return;
3403
3404 btc->dm.wl_btg_rx = is_btg;
3405
3406 if (mode == BTC_WLINK_25G_MCC)
3407 return;
3408
3409 rtw89_ctrl_btg(rtwdev, is_btg);
3410 }
3411
3412 struct rtw89_txtime_data {
3413 struct rtw89_dev *rtwdev;
3414 int type;
3415 u32 tx_time;
3416 u8 tx_retry;
3417 u16 enable;
3418 bool reenable;
3419 };
3420
3421 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
3422 {
3423 struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
3424 struct rtw89_txtime_data *iter_data =
3425 (struct rtw89_txtime_data *)data;
3426 struct rtw89_dev *rtwdev = iter_data->rtwdev;
3427 struct rtw89_vif *rtwvif = rtwsta->rtwvif;
3428 struct rtw89_btc *btc = &rtwdev->btc;
3429 struct rtw89_btc_cx *cx = &btc->cx;
3430 struct rtw89_btc_wl_info *wl = &cx->wl;
3431 struct rtw89_btc_wl_link_info *plink = NULL;
3432 u8 port = rtwvif->port;
3433 u32 tx_time = iter_data->tx_time;
3434 u8 tx_retry = iter_data->tx_retry;
3435 u16 enable = iter_data->enable;
3436 bool reenable = iter_data->reenable;
3437
3438 plink = &wl->link_info[port];
3439
3440 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3441 "[BTC], %s(): port = %d\n", __func__, port);
3442
3443 if (!plink->connected) {
3444 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3445 "[BTC], %s(): connected = %d\n",
3446 __func__, plink->connected);
3447 return;
3448 }
3449
3450 /* backup the original tx time before tx-limit on */
3451 if (reenable) {
3452 rtw89_mac_get_tx_time(rtwdev, rtwsta, &plink->tx_time);
3453 rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta, &plink->tx_retry);
3454 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3455 "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n",
3456 __func__, plink->tx_time, plink->tx_retry);
3457 }
3458
3459 /* restore the original tx time if no tx-limit */
3460 if (!enable) {
3461 rtw89_mac_set_tx_time(rtwdev, rtwsta, true, plink->tx_time);
3462 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, true,
3463 plink->tx_retry);
3464 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3465 "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n",
3466 __func__, plink->tx_time, plink->tx_retry);
3467
3468 } else {
3469 rtw89_mac_set_tx_time(rtwdev, rtwsta, false, tx_time);
3470 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta, false, tx_retry);
3471 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3472 "[BTC], %s(): set, tx_time=%d tx_retry= %d\n",
3473 __func__, tx_time, tx_retry);
3474 }
3475 }
3476
3477 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
3478 {
3479 const struct rtw89_chip_info *chip = rtwdev->chip;
3480 struct rtw89_btc *btc = &rtwdev->btc;
3481 struct rtw89_btc_cx *cx = &btc->cx;
3482 struct rtw89_btc_dm *dm = &btc->dm;
3483 struct rtw89_btc_wl_info *wl = &cx->wl;
3484 struct rtw89_btc_bt_info *bt = &cx->bt;
3485 struct rtw89_btc_bt_link_info *b = &bt->link_info;
3486 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
3487 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
3488 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3489 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3490 struct rtw89_txtime_data data = {.rtwdev = rtwdev};
3491 u8 mode;
3492 u8 tx_retry;
3493 u32 tx_time;
3494 u16 enable;
3495 bool reenable = false;
3496
3497 if (btc->ctrl.manual)
3498 return;
3499
3500 if (chip->chip_id == RTL8852A)
3501 mode = wl_rinfo->link_mode;
3502 else
3503 mode = wl_rinfo_v1->link_mode;
3504
3505 if (btc->dm.freerun || btc->ctrl.igno_bt || b->profile_cnt.now == 0 ||
3506 mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) {
3507 enable = 0;
3508 tx_time = BTC_MAX_TX_TIME_DEF;
3509 tx_retry = BTC_MAX_TX_RETRY_DEF;
3510 } else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) {
3511 enable = 1;
3512 tx_time = BTC_MAX_TX_TIME_L2;
3513 tx_retry = BTC_MAX_TX_RETRY_L1;
3514 } else if (hfp->exist || hid->exist) {
3515 enable = 1;
3516 tx_time = BTC_MAX_TX_TIME_L3;
3517 tx_retry = BTC_MAX_TX_RETRY_L1;
3518 } else {
3519 enable = 0;
3520 tx_time = BTC_MAX_TX_TIME_DEF;
3521 tx_retry = BTC_MAX_TX_RETRY_DEF;
3522 }
3523
3524 if (dm->wl_tx_limit.enable == enable &&
3525 dm->wl_tx_limit.tx_time == tx_time &&
3526 dm->wl_tx_limit.tx_retry == tx_retry)
3527 return;
3528
3529 if (!dm->wl_tx_limit.enable && enable)
3530 reenable = true;
3531
3532 dm->wl_tx_limit.enable = enable;
3533 dm->wl_tx_limit.tx_time = tx_time;
3534 dm->wl_tx_limit.tx_retry = tx_retry;
3535
3536 data.enable = enable;
3537 data.tx_time = tx_time;
3538 data.tx_retry = tx_retry;
3539 data.reenable = reenable;
3540
3541 ieee80211_iterate_stations_atomic(rtwdev->hw,
3542 rtw89_tx_time_iter,
3543 &data);
3544 }
3545
3546 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
3547 {
3548 const struct rtw89_chip_info *chip = rtwdev->chip;
3549 struct rtw89_btc *btc = &rtwdev->btc;
3550 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3551 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3552 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3553 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3554 bool bt_hi_lna_rx = false;
3555 u8 mode;
3556
3557 if (chip->chip_id == RTL8852A)
3558 mode = wl_rinfo->link_mode;
3559 else
3560 mode = wl_rinfo_v1->link_mode;
3561
3562 if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
3563 bt_hi_lna_rx = true;
3564
3565 if (bt_hi_lna_rx == bt->hi_lna_rx)
3566 return;
3567
3568 _write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx);
3569 }
3570
3571 /* TODO add these functions */
3572 static void _action_common(struct rtw89_dev *rtwdev)
3573 {
3574 _set_btg_ctrl(rtwdev);
3575 _set_wl_tx_limit(rtwdev);
3576 _set_bt_afh_info(rtwdev);
3577 _set_bt_rx_agc(rtwdev);
3578 _set_rf_trx_para(rtwdev);
3579 }
3580
3581 static void _action_by_bt(struct rtw89_dev *rtwdev)
3582 {
3583 struct rtw89_btc *btc = &rtwdev->btc;
3584 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3585 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
3586 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
3587 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
3588 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
3589 u8 profile_map = 0;
3590
3591 if (bt_linfo->hfp_desc.exist)
3592 profile_map |= BTC_BT_HFP;
3593
3594 if (bt_linfo->hid_desc.exist)
3595 profile_map |= BTC_BT_HID;
3596
3597 if (bt_linfo->a2dp_desc.exist)
3598 profile_map |= BTC_BT_A2DP;
3599
3600 if (bt_linfo->pan_desc.exist)
3601 profile_map |= BTC_BT_PAN;
3602
3603 switch (profile_map) {
3604 case BTC_BT_NOPROFILE:
3605 if (_check_freerun(rtwdev))
3606 _action_freerun(rtwdev);
3607 else if (a2dp.active || pan.active)
3608 _action_bt_pan(rtwdev);
3609 else
3610 _action_bt_idle(rtwdev);
3611 break;
3612 case BTC_BT_HFP:
3613 if (_check_freerun(rtwdev))
3614 _action_freerun(rtwdev);
3615 else
3616 _action_bt_hfp(rtwdev);
3617 break;
3618 case BTC_BT_HFP | BTC_BT_HID:
3619 case BTC_BT_HID:
3620 if (_check_freerun(rtwdev))
3621 _action_freerun(rtwdev);
3622 else
3623 _action_bt_hid(rtwdev);
3624 break;
3625 case BTC_BT_A2DP:
3626 if (_check_freerun(rtwdev))
3627 _action_freerun(rtwdev);
3628 else if (a2dp.sink)
3629 _action_bt_a2dpsink(rtwdev);
3630 else if (bt_linfo->multi_link.now && !hid.pair_cnt)
3631 _action_bt_a2dp_pan(rtwdev);
3632 else
3633 _action_bt_a2dp(rtwdev);
3634 break;
3635 case BTC_BT_PAN:
3636 _action_bt_pan(rtwdev);
3637 break;
3638 case BTC_BT_A2DP | BTC_BT_HFP:
3639 case BTC_BT_A2DP | BTC_BT_HID:
3640 case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID:
3641 if (_check_freerun(rtwdev))
3642 _action_freerun(rtwdev);
3643 else
3644 _action_bt_a2dp_hid(rtwdev);
3645 break;
3646 case BTC_BT_A2DP | BTC_BT_PAN:
3647 _action_bt_a2dp_pan(rtwdev);
3648 break;
3649 case BTC_BT_PAN | BTC_BT_HFP:
3650 case BTC_BT_PAN | BTC_BT_HID:
3651 case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID:
3652 _action_bt_pan_hid(rtwdev);
3653 break;
3654 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID:
3655 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP:
3656 default:
3657 _action_bt_a2dp_pan_hid(rtwdev);
3658 break;
3659 }
3660 }
3661
3662 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev)
3663 {
3664 _action_by_bt(rtwdev);
3665 }
3666
3667 static void _action_wl_scan(struct rtw89_dev *rtwdev)
3668 {
3669 struct rtw89_btc *btc = &rtwdev->btc;
3670 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3671 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
3672
3673 if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
3674 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
3675 if (btc->mdinfo.ant.type == BTC_ANT_SHARED)
3676 _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
3677 BTC_RSN_NTFY_SCAN_START);
3678 else
3679 _set_policy(rtwdev, BTC_CXP_OFF_EQ0,
3680 BTC_RSN_NTFY_SCAN_START);
3681
3682 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n");
3683 } else if (rtwdev->dbcc_en) {
3684 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G &&
3685 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
3686 _action_wl_5g(rtwdev);
3687 else
3688 _action_by_bt(rtwdev);
3689 } else {
3690 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G)
3691 _action_wl_5g(rtwdev);
3692 else
3693 _action_by_bt(rtwdev);
3694 }
3695 }
3696
3697 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev)
3698 {
3699 struct rtw89_btc *btc = &rtwdev->btc;
3700
3701 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
3702
3703 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
3704 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3705 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
3706 BTC_ACT_WL_25G_MCC);
3707 else
3708 _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
3709 BTC_ACT_WL_25G_MCC);
3710 } else { /* dedicated-antenna */
3711 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_25G_MCC);
3712 }
3713 }
3714
3715 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev)
3716 { struct rtw89_btc *btc = &rtwdev->btc;
3717
3718 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3719
3720 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
3721 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3722 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
3723 BTC_ACT_WL_2G_MCC);
3724 else
3725 _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
3726 BTC_ACT_WL_2G_MCC);
3727 } else { /* dedicated-antenna */
3728 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC);
3729 }
3730 }
3731
3732 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev)
3733 {
3734 struct rtw89_btc *btc = &rtwdev->btc;
3735
3736 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3737
3738 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
3739 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3740 _set_policy(rtwdev,
3741 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC);
3742 else
3743 _set_policy(rtwdev,
3744 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC);
3745 } else { /* dedicated-antenna */
3746 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC);
3747 }
3748 }
3749
3750 static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev)
3751 {
3752 struct rtw89_btc *btc = &rtwdev->btc;
3753 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3754 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3755 struct rtw89_btc_dm *dm = &btc->dm;
3756 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
3757 u16 policy_type = BTC_CXP_OFF_BT;
3758 u32 dur;
3759
3760 if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED) {
3761 policy_type = BTC_CXP_OFF_EQ0;
3762 } else {
3763 /* shared-antenna */
3764 switch (wl_rinfo->mrole_type) {
3765 case BTC_WLMROLE_STA_GC:
3766 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
3767 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
3768 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
3769 _action_by_bt(rtwdev);
3770 return;
3771 case BTC_WLMROLE_STA_STA:
3772 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
3773 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
3774 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
3775 _action_by_bt(rtwdev);
3776 return;
3777 case BTC_WLMROLE_STA_GC_NOA:
3778 case BTC_WLMROLE_STA_GO:
3779 case BTC_WLMROLE_STA_GO_NOA:
3780 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
3781 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
3782 dur = wl_rinfo->mrole_noa_duration;
3783
3784 if (wl->status.map._4way) {
3785 dm->wl_scc.ebt_null = 0;
3786 policy_type = BTC_CXP_OFFE_WL;
3787 } else if (bt->link_info.status.map.connect == 0) {
3788 dm->wl_scc.ebt_null = 0;
3789 policy_type = BTC_CXP_OFFE_2GISOB;
3790 } else if (bt->link_info.a2dp_desc.exist &&
3791 dur < btc->bt_req_len) {
3792 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
3793 policy_type = BTC_CXP_OFFE_2GBWMIXB2;
3794 } else if (bt->link_info.a2dp_desc.exist ||
3795 bt->link_info.pan_desc.exist) {
3796 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
3797 policy_type = BTC_CXP_OFFE_2GBWISOB;
3798 } else {
3799 dm->wl_scc.ebt_null = 0;
3800 policy_type = BTC_CXP_OFFE_2GBWISOB;
3801 }
3802 break;
3803 default:
3804 break;
3805 }
3806 }
3807
3808 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3809 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
3810 }
3811
3812 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
3813 {
3814 struct rtw89_btc *btc = &rtwdev->btc;
3815
3816 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3817
3818 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
3819 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3820 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
3821 BTC_ACT_WL_2G_AP);
3822 else
3823 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP);
3824 } else {/* dedicated-antenna */
3825 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP);
3826 }
3827 }
3828
3829 static void _action_wl_2g_go(struct rtw89_dev *rtwdev)
3830 {
3831 struct rtw89_btc *btc = &rtwdev->btc;
3832
3833 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3834
3835 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
3836 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3837 _set_policy(rtwdev,
3838 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO);
3839 else
3840 _set_policy(rtwdev,
3841 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO);
3842 } else { /* dedicated-antenna */
3843 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO);
3844 }
3845 }
3846
3847 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev)
3848 {
3849 struct rtw89_btc *btc = &rtwdev->btc;
3850
3851 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3852
3853 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
3854 _action_by_bt(rtwdev);
3855 } else {/* dedicated-antenna */
3856 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC);
3857 }
3858 }
3859
3860 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev)
3861 {
3862 struct rtw89_btc *btc = &rtwdev->btc;
3863
3864 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
3865
3866 if (btc->mdinfo.ant.type == BTC_ANT_SHARED) { /* shared-antenna */
3867 if (btc->cx.bt.link_info.profile_cnt.now == 0)
3868 _set_policy(rtwdev,
3869 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN);
3870 else
3871 _set_policy(rtwdev,
3872 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN);
3873 } else { /* dedicated-antenna */
3874 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN);
3875 }
3876 }
3877
3878 static u32 _read_scbd(struct rtw89_dev *rtwdev)
3879 {
3880 const struct rtw89_chip_info *chip = rtwdev->chip;
3881 struct rtw89_btc *btc = &rtwdev->btc;
3882 u32 scbd_val = 0;
3883
3884 if (!chip->scbd)
3885 return 0;
3886
3887 scbd_val = rtw89_mac_get_sb(rtwdev);
3888 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n",
3889 scbd_val);
3890
3891 btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++;
3892 return scbd_val;
3893 }
3894
3895 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state)
3896 {
3897 const struct rtw89_chip_info *chip = rtwdev->chip;
3898 struct rtw89_btc *btc = &rtwdev->btc;
3899 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3900 u32 scbd_val = 0;
3901
3902 if (!chip->scbd)
3903 return;
3904
3905 scbd_val = state ? wl->scbd | val : wl->scbd & ~val;
3906
3907 if (scbd_val == wl->scbd)
3908 return;
3909 rtw89_mac_cfg_sb(rtwdev, scbd_val);
3910 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n",
3911 scbd_val);
3912 wl->scbd = scbd_val;
3913
3914 btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++;
3915 }
3916
3917 static u8
3918 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh)
3919 {
3920 const struct rtw89_chip_info *chip = rtwdev->chip;
3921 u8 next_state, tol = chip->rssi_tol;
3922
3923 if (pre_state == BTC_RSSI_ST_LOW ||
3924 pre_state == BTC_RSSI_ST_STAY_LOW) {
3925 if (rssi >= (thresh + tol))
3926 next_state = BTC_RSSI_ST_HIGH;
3927 else
3928 next_state = BTC_RSSI_ST_STAY_LOW;
3929 } else {
3930 if (rssi < thresh)
3931 next_state = BTC_RSSI_ST_LOW;
3932 else
3933 next_state = BTC_RSSI_ST_STAY_HIGH;
3934 }
3935
3936 return next_state;
3937 }
3938
3939 static
3940 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
3941 {
3942 struct rtw89_btc *btc = &rtwdev->btc;
3943
3944 btc->cx.wl.dbcc_info.real_band[phy_idx] =
3945 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ?
3946 btc->cx.wl.dbcc_info.scan_band[phy_idx] :
3947 btc->cx.wl.dbcc_info.op_band[phy_idx];
3948 }
3949
3950 static void _update_wl_info(struct rtw89_dev *rtwdev)
3951 {
3952 struct rtw89_btc *btc = &rtwdev->btc;
3953 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3954 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
3955 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3956 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
3957 u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
3958 u8 cnt_2g = 0, cnt_5g = 0, phy;
3959 u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0};
3960 bool b2g = false, b5g = false, client_joined = false;
3961
3962 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
3963
3964 for (i = 0; i < RTW89_PORT_NUM; i++) {
3965 /* check if role active? */
3966 if (!wl_linfo[i].active)
3967 continue;
3968
3969 cnt_active++;
3970 wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role;
3971 wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid;
3972 wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy;
3973 wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band;
3974 wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
3975 wl_rinfo->active_role[cnt_active - 1].connected = 0;
3976
3977 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
3978
3979 phy = wl_linfo[i].phy;
3980
3981 /* check dbcc role */
3982 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
3983 wl_dinfo->role[phy] = wl_linfo[i].role;
3984 wl_dinfo->op_band[phy] = wl_linfo[i].band;
3985 _update_dbcc_band(rtwdev, phy);
3986 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
3987 }
3988
3989 if (wl_linfo[i].connected == MLME_NO_LINK) {
3990 continue;
3991 } else if (wl_linfo[i].connected == MLME_LINKING) {
3992 cnt_connecting++;
3993 } else {
3994 cnt_connect++;
3995 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
3996 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
3997 wl_linfo[i].client_cnt > 1)
3998 client_joined = true;
3999 }
4000
4001 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
4002 wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch;
4003 wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw;
4004 wl_rinfo->active_role[cnt_active - 1].connected = 1;
4005
4006 /* only care 2 roles + BT coex */
4007 if (wl_linfo[i].band != RTW89_BAND_2G) {
4008 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
4009 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
4010 cnt_5g++;
4011 b5g = true;
4012 } else {
4013 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
4014 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
4015 cnt_2g++;
4016 b2g = true;
4017 }
4018 }
4019
4020 wl_rinfo->connect_cnt = cnt_connect;
4021
4022 /* Be careful to change the following sequence!! */
4023 if (cnt_connect == 0) {
4024 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
4025 wl_rinfo->role_map.role.none = 1;
4026 } else if (!b2g && b5g) {
4027 wl_rinfo->link_mode = BTC_WLINK_5G;
4028 } else if (wl_rinfo->role_map.role.nan) {
4029 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
4030 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
4031 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4032 } else if (b2g && b5g && cnt_connect == 2) {
4033 if (rtwdev->dbcc_en) {
4034 switch (wl_dinfo->role[RTW89_PHY_0]) {
4035 case RTW89_WIFI_ROLE_STATION:
4036 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4037 break;
4038 case RTW89_WIFI_ROLE_P2P_GO:
4039 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
4040 break;
4041 case RTW89_WIFI_ROLE_P2P_CLIENT:
4042 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
4043 break;
4044 case RTW89_WIFI_ROLE_AP:
4045 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
4046 break;
4047 default:
4048 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4049 break;
4050 }
4051 } else {
4052 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
4053 }
4054 } else if (!b5g && cnt_connect == 2) {
4055 if (wl_rinfo->role_map.role.station &&
4056 (wl_rinfo->role_map.role.p2p_go ||
4057 wl_rinfo->role_map.role.p2p_gc ||
4058 wl_rinfo->role_map.role.ap)) {
4059 if (wl_2g_ch[0] == wl_2g_ch[1])
4060 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
4061 else
4062 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
4063 } else {
4064 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
4065 }
4066 } else if (!b5g && cnt_connect == 1) {
4067 if (wl_rinfo->role_map.role.station)
4068 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4069 else if (wl_rinfo->role_map.role.ap)
4070 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
4071 else if (wl_rinfo->role_map.role.p2p_go)
4072 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
4073 else if (wl_rinfo->role_map.role.p2p_gc)
4074 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
4075 else
4076 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4077 }
4078
4079 /* if no client_joined, don't care P2P-GO/AP role */
4080 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
4081 if (!client_joined) {
4082 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
4083 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
4084 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4085 wl_rinfo->connect_cnt = 1;
4086 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
4087 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
4088 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
4089 wl_rinfo->connect_cnt = 0;
4090 }
4091 }
4092 }
4093
4094 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4095 "[BTC], cnt_connect = %d, link_mode = %d\n",
4096 cnt_connect, wl_rinfo->link_mode);
4097
4098 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
4099 }
4100
4101 static void _update_wl_info_v1(struct rtw89_dev *rtwdev)
4102 {
4103 struct rtw89_btc *btc = &rtwdev->btc;
4104 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4105 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
4106 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
4107 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4108 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
4109 u8 cnt_2g = 0, cnt_5g = 0, phy;
4110 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
4111 bool b2g = false, b5g = false, client_joined = false;
4112 u8 i;
4113
4114 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
4115
4116 for (i = 0; i < RTW89_PORT_NUM; i++) {
4117 if (!wl_linfo[i].active)
4118 continue;
4119
4120 cnt_active++;
4121 wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role;
4122 wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid;
4123 wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy;
4124 wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band;
4125 wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
4126 wl_rinfo->active_role_v1[cnt_active - 1].connected = 0;
4127
4128 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
4129
4130 phy = wl_linfo[i].phy;
4131
4132 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
4133 wl_dinfo->role[phy] = wl_linfo[i].role;
4134 wl_dinfo->op_band[phy] = wl_linfo[i].band;
4135 _update_dbcc_band(rtwdev, phy);
4136 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
4137 }
4138
4139 if (wl_linfo[i].connected == MLME_NO_LINK) {
4140 continue;
4141 } else if (wl_linfo[i].connected == MLME_LINKING) {
4142 cnt_connecting++;
4143 } else {
4144 cnt_connect++;
4145 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
4146 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
4147 wl_linfo[i].client_cnt > 1)
4148 client_joined = true;
4149 }
4150
4151 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
4152 wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch;
4153 wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw;
4154 wl_rinfo->active_role_v1[cnt_active - 1].connected = 1;
4155
4156 /* only care 2 roles + BT coex */
4157 if (wl_linfo[i].band != RTW89_BAND_2G) {
4158 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
4159 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
4160 cnt_5g++;
4161 b5g = true;
4162 } else {
4163 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
4164 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
4165 cnt_2g++;
4166 b2g = true;
4167 }
4168 }
4169
4170 wl_rinfo->connect_cnt = cnt_connect;
4171
4172 /* Be careful to change the following sequence!! */
4173 if (cnt_connect == 0) {
4174 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
4175 wl_rinfo->role_map.role.none = 1;
4176 } else if (!b2g && b5g) {
4177 wl_rinfo->link_mode = BTC_WLINK_5G;
4178 } else if (wl_rinfo->role_map.role.nan) {
4179 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
4180 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
4181 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4182 } else if (b2g && b5g && cnt_connect == 2) {
4183 if (rtwdev->dbcc_en) {
4184 switch (wl_dinfo->role[RTW89_PHY_0]) {
4185 case RTW89_WIFI_ROLE_STATION:
4186 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4187 break;
4188 case RTW89_WIFI_ROLE_P2P_GO:
4189 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
4190 break;
4191 case RTW89_WIFI_ROLE_P2P_CLIENT:
4192 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
4193 break;
4194 case RTW89_WIFI_ROLE_AP:
4195 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
4196 break;
4197 default:
4198 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4199 break;
4200 }
4201 } else {
4202 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
4203 }
4204 } else if (!b5g && cnt_connect == 2) {
4205 if (wl_rinfo->role_map.role.station &&
4206 (wl_rinfo->role_map.role.p2p_go ||
4207 wl_rinfo->role_map.role.p2p_gc ||
4208 wl_rinfo->role_map.role.ap)) {
4209 if (wl_2g_ch[0] == wl_2g_ch[1])
4210 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
4211 else
4212 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
4213 } else {
4214 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
4215 }
4216 } else if (!b5g && cnt_connect == 1) {
4217 if (wl_rinfo->role_map.role.station)
4218 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4219 else if (wl_rinfo->role_map.role.ap)
4220 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
4221 else if (wl_rinfo->role_map.role.p2p_go)
4222 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
4223 else if (wl_rinfo->role_map.role.p2p_gc)
4224 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
4225 else
4226 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4227 }
4228
4229 /* if no client_joined, don't care P2P-GO/AP role */
4230 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
4231 if (!client_joined) {
4232 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
4233 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
4234 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4235 wl_rinfo->connect_cnt = 1;
4236 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
4237 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
4238 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
4239 wl_rinfo->connect_cnt = 0;
4240 }
4241 }
4242 }
4243
4244 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4245 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
4246 cnt_connect, cnt_connecting, wl_rinfo->link_mode);
4247
4248 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
4249 }
4250
4251 #define BTC_CHK_HANG_MAX 3
4252 #define BTC_SCB_INV_VALUE GENMASK(31, 0)
4253
4254 void rtw89_coex_act1_work(struct work_struct *work)
4255 {
4256 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4257 coex_act1_work.work);
4258 struct rtw89_btc *btc = &rtwdev->btc;
4259 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4260 struct rtw89_btc_cx *cx = &btc->cx;
4261 struct rtw89_btc_wl_info *wl = &cx->wl;
4262
4263 mutex_lock(&rtwdev->mutex);
4264 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
4265 dm->cnt_notify[BTC_NCNT_TIMER]++;
4266 if (wl->status.map._4way)
4267 wl->status.map._4way = false;
4268 if (wl->status.map.connecting)
4269 wl->status.map.connecting = false;
4270
4271 _run_coex(rtwdev, BTC_RSN_ACT1_WORK);
4272 mutex_unlock(&rtwdev->mutex);
4273 }
4274
4275 void rtw89_coex_bt_devinfo_work(struct work_struct *work)
4276 {
4277 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4278 coex_bt_devinfo_work.work);
4279 struct rtw89_btc *btc = &rtwdev->btc;
4280 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4281 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
4282
4283 mutex_lock(&rtwdev->mutex);
4284 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
4285 dm->cnt_notify[BTC_NCNT_TIMER]++;
4286 a2dp->play_latency = 0;
4287 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK);
4288 mutex_unlock(&rtwdev->mutex);
4289 }
4290
4291 void rtw89_coex_rfk_chk_work(struct work_struct *work)
4292 {
4293 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4294 coex_rfk_chk_work.work);
4295 struct rtw89_btc *btc = &rtwdev->btc;
4296 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4297 struct rtw89_btc_cx *cx = &btc->cx;
4298 struct rtw89_btc_wl_info *wl = &cx->wl;
4299
4300 mutex_lock(&rtwdev->mutex);
4301 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
4302 dm->cnt_notify[BTC_NCNT_TIMER]++;
4303 if (wl->rfk_info.state != BTC_WRFK_STOP) {
4304 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4305 "[BTC], %s(): RFK timeout\n", __func__);
4306 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++;
4307 dm->error.map.wl_rfk_timeout = true;
4308 wl->rfk_info.state = BTC_WRFK_STOP;
4309 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
4310 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK);
4311 }
4312 mutex_unlock(&rtwdev->mutex);
4313 }
4314
4315 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update)
4316 {
4317 const struct rtw89_chip_info *chip = rtwdev->chip;
4318 struct rtw89_btc *btc = &rtwdev->btc;
4319 struct rtw89_btc_cx *cx = &btc->cx;
4320 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4321 u32 val;
4322 bool status_change = false;
4323
4324 if (!chip->scbd)
4325 return;
4326
4327 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
4328
4329 val = _read_scbd(rtwdev);
4330 if (val == BTC_SCB_INV_VALUE) {
4331 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4332 "[BTC], %s(): return by invalid scbd value\n",
4333 __func__);
4334 return;
4335 }
4336
4337 if (!(val & BTC_BSCB_ON) ||
4338 btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] >= BTC_CHK_HANG_MAX)
4339 bt->enable.now = 0;
4340 else
4341 bt->enable.now = 1;
4342
4343 if (bt->enable.now != bt->enable.last)
4344 status_change = true;
4345
4346 /* reset bt info if bt re-enable */
4347 if (bt->enable.now && !bt->enable.last) {
4348 _reset_btc_var(rtwdev, BTC_RESET_BTINFO);
4349 cx->cnt_bt[BTC_BCNT_REENABLE]++;
4350 bt->enable.now = 1;
4351 }
4352
4353 bt->enable.last = bt->enable.now;
4354 bt->scbd = val;
4355 bt->mbx_avl = !!(val & BTC_BSCB_ACT);
4356
4357 if (bt->whql_test != !!(val & BTC_BSCB_WHQL))
4358 status_change = true;
4359
4360 bt->whql_test = !!(val & BTC_BSCB_WHQL);
4361 bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE;
4362 bt->link_info.a2dp_desc.active = !!(val & BTC_BSCB_A2DP_ACT);
4363
4364 /* if rfk run 1->0 */
4365 if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN))
4366 status_change = true;
4367
4368 bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN);
4369 bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ);
4370 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
4371 bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT);
4372 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
4373
4374 if (!only_update && status_change)
4375 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
4376 }
4377
4378 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev)
4379 {
4380 struct rtw89_btc *btc = &rtwdev->btc;
4381 struct rtw89_btc_cx *cx = &btc->cx;
4382 struct rtw89_btc_bt_info *bt = &cx->bt;
4383
4384 _update_bt_scbd(rtwdev, true);
4385
4386 cx->cnt_wl[BTC_WCNT_RFK_REQ]++;
4387
4388 if ((bt->rfk_info.map.run || bt->rfk_info.map.req) &&
4389 !bt->rfk_info.map.timeout) {
4390 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++;
4391 } else {
4392 cx->cnt_wl[BTC_WCNT_RFK_GO]++;
4393 return true;
4394 }
4395 return false;
4396 }
4397
4398 static
4399 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
4400 {
4401 const struct rtw89_chip_info *chip = rtwdev->chip;
4402 struct rtw89_btc *btc = &rtwdev->btc;
4403 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4404 struct rtw89_btc_cx *cx = &btc->cx;
4405 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4406 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
4407 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
4408 u8 mode;
4409
4410 lockdep_assert_held(&rtwdev->mutex);
4411
4412 dm->run_reason = reason;
4413 _update_dm_step(rtwdev, reason);
4414 _update_btc_state_map(rtwdev);
4415
4416 if (chip->chip_id == RTL8852A)
4417 mode = wl_rinfo->link_mode;
4418 else
4419 mode = wl_rinfo_v1->link_mode;
4420
4421 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
4422 __func__, reason, mode);
4423 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
4424 __func__, dm->wl_only, dm->bt_only);
4425
4426 /* Be careful to change the following function sequence!! */
4427 if (btc->ctrl.manual) {
4428 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4429 "[BTC], %s(): return for Manual CTRL!!\n",
4430 __func__);
4431 return;
4432 }
4433
4434 if (btc->ctrl.igno_bt &&
4435 (reason == BTC_RSN_UPDATE_BT_INFO ||
4436 reason == BTC_RSN_UPDATE_BT_SCBD)) {
4437 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4438 "[BTC], %s(): return for Stop Coex DM!!\n",
4439 __func__);
4440 return;
4441 }
4442
4443 if (!wl->status.map.init_ok) {
4444 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4445 "[BTC], %s(): return for WL init fail!!\n",
4446 __func__);
4447 return;
4448 }
4449
4450 if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
4451 wl->status.map.lps_pre == wl->status.map.lps &&
4452 (reason == BTC_RSN_NTFY_POWEROFF ||
4453 reason == BTC_RSN_NTFY_RADIO_STATE)) {
4454 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4455 "[BTC], %s(): return for WL rf off state no change!!\n",
4456 __func__);
4457 return;
4458 }
4459
4460 dm->cnt_dm[BTC_DCNT_RUN]++;
4461
4462 if (btc->ctrl.always_freerun) {
4463 _action_freerun(rtwdev);
4464 btc->ctrl.igno_bt = true;
4465 goto exit;
4466 }
4467
4468 if (dm->wl_only) {
4469 _action_wl_only(rtwdev);
4470 btc->ctrl.igno_bt = true;
4471 goto exit;
4472 }
4473
4474 if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) {
4475 _action_wl_off(rtwdev);
4476 btc->ctrl.igno_bt = true;
4477 goto exit;
4478 }
4479
4480 btc->ctrl.igno_bt = false;
4481 dm->freerun = false;
4482
4483 if (reason == BTC_RSN_NTFY_INIT) {
4484 _action_wl_init(rtwdev);
4485 goto exit;
4486 }
4487
4488 if (!cx->bt.enable.now && !cx->other.type) {
4489 _action_bt_off(rtwdev);
4490 goto exit;
4491 }
4492
4493 if (cx->bt.whql_test) {
4494 _action_bt_whql(rtwdev);
4495 goto exit;
4496 }
4497
4498 if (wl->rfk_info.state != BTC_WRFK_STOP) {
4499 _action_wl_rfk(rtwdev);
4500 goto exit;
4501 }
4502
4503 if (cx->state_map == BTC_WLINKING) {
4504 if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA ||
4505 mode == BTC_WLINK_5G) {
4506 _action_wl_scan(rtwdev);
4507 goto exit;
4508 }
4509 }
4510
4511 if (wl->status.map.scan) {
4512 _action_wl_scan(rtwdev);
4513 goto exit;
4514 }
4515
4516 switch (mode) {
4517 case BTC_WLINK_NOLINK:
4518 _action_wl_nc(rtwdev);
4519 break;
4520 case BTC_WLINK_2G_STA:
4521 _action_wl_2g_sta(rtwdev);
4522 break;
4523 case BTC_WLINK_2G_AP:
4524 _action_wl_2g_ap(rtwdev);
4525 break;
4526 case BTC_WLINK_2G_GO:
4527 _action_wl_2g_go(rtwdev);
4528 break;
4529 case BTC_WLINK_2G_GC:
4530 _action_wl_2g_gc(rtwdev);
4531 break;
4532 case BTC_WLINK_2G_SCC:
4533 if (chip->chip_id == RTL8852A)
4534 _action_wl_2g_scc(rtwdev);
4535 else if (chip->chip_id == RTL8852C)
4536 _action_wl_2g_scc_v1(rtwdev);
4537 break;
4538 case BTC_WLINK_2G_MCC:
4539 _action_wl_2g_mcc(rtwdev);
4540 break;
4541 case BTC_WLINK_25G_MCC:
4542 _action_wl_25g_mcc(rtwdev);
4543 break;
4544 case BTC_WLINK_5G:
4545 _action_wl_5g(rtwdev);
4546 break;
4547 case BTC_WLINK_2G_NAN:
4548 _action_wl_2g_nan(rtwdev);
4549 break;
4550 default:
4551 _action_wl_other(rtwdev);
4552 break;
4553 }
4554
4555 exit:
4556 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__);
4557 _action_common(rtwdev);
4558 }
4559
4560 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
4561 {
4562 struct rtw89_btc *btc = &rtwdev->btc;
4563
4564 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4565 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++;
4566 }
4567
4568 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
4569 {
4570 struct rtw89_btc *btc = &rtwdev->btc;
4571 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4572
4573 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4574 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
4575
4576 btc->cx.wl.status.map.rf_off = 1;
4577 btc->cx.wl.status.map.busy = 0;
4578 wl->status.map.lps = BTC_LPS_OFF;
4579
4580 _write_scbd(rtwdev, BTC_WSCB_ALL, false);
4581 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
4582
4583 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
4584
4585 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
4586 }
4587
4588 static void _set_init_info(struct rtw89_dev *rtwdev)
4589 {
4590 const struct rtw89_chip_info *chip = rtwdev->chip;
4591 struct rtw89_btc *btc = &rtwdev->btc;
4592 struct rtw89_btc_dm *dm = &btc->dm;
4593 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4594
4595 dm->init_info.wl_only = (u8)dm->wl_only;
4596 dm->init_info.bt_only = (u8)dm->bt_only;
4597 dm->init_info.wl_init_ok = (u8)wl->status.map.init_ok;
4598 dm->init_info.dbcc_en = rtwdev->dbcc_en;
4599 dm->init_info.cx_other = btc->cx.other.type;
4600 dm->init_info.wl_guard_ch = chip->afh_guard_ch;
4601 dm->init_info.module = btc->mdinfo;
4602 }
4603
4604 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
4605 {
4606 struct rtw89_btc *btc = &rtwdev->btc;
4607 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4608 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4609 const struct rtw89_chip_info *chip = rtwdev->chip;
4610
4611 _reset_btc_var(rtwdev, BTC_RESET_ALL);
4612 btc->dm.run_reason = BTC_RSN_NONE;
4613 btc->dm.run_action = BTC_ACT_NONE;
4614 btc->ctrl.igno_bt = true;
4615
4616 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4617 "[BTC], %s(): mode=%d\n", __func__, mode);
4618
4619 dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
4620 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0;
4621 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0;
4622 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0;
4623
4624 chip->ops->btc_set_rfe(rtwdev);
4625 chip->ops->btc_init_cfg(rtwdev);
4626
4627 if (!wl->status.map.init_ok) {
4628 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4629 "[BTC], %s(): return for WL init fail!!\n",
4630 __func__);
4631 dm->error.map.init = true;
4632 return;
4633 }
4634
4635 _write_scbd(rtwdev,
4636 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
4637 _update_bt_scbd(rtwdev, true);
4638 if (rtw89_mac_get_ctrl_path(rtwdev)) {
4639 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4640 "[BTC], %s(): PTA owner warning!!\n",
4641 __func__);
4642 dm->error.map.pta_owner = true;
4643 }
4644
4645 _set_init_info(rtwdev);
4646 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR);
4647 rtw89_btc_fw_set_slots(rtwdev, CXST_MAX, dm->slot);
4648 btc_fw_set_monreg(rtwdev);
4649 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
4650 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
4651
4652 _run_coex(rtwdev, BTC_RSN_NTFY_INIT);
4653 }
4654
4655 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
4656 {
4657 struct rtw89_btc *btc = &rtwdev->btc;
4658 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4659
4660 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4661 "[BTC], %s(): phy_idx=%d, band=%d\n",
4662 __func__, phy_idx, band);
4663 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
4664 wl->status.map.scan = true;
4665 wl->scan_info.band[phy_idx] = band;
4666 wl->scan_info.phy_map |= BIT(phy_idx);
4667 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
4668
4669 if (rtwdev->dbcc_en) {
4670 wl->dbcc_info.scan_band[phy_idx] = band;
4671 _update_dbcc_band(rtwdev, phy_idx);
4672 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
4673 }
4674
4675 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START);
4676 }
4677
4678 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
4679 {
4680 struct rtw89_btc *btc = &rtwdev->btc;
4681 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4682
4683 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4684 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
4685 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
4686
4687 wl->status.map.scan = false;
4688 wl->scan_info.phy_map &= ~BIT(phy_idx);
4689 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
4690
4691 if (rtwdev->dbcc_en) {
4692 _update_dbcc_band(rtwdev, phy_idx);
4693 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
4694 }
4695
4696 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
4697 }
4698
4699 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
4700 {
4701 struct rtw89_btc *btc = &rtwdev->btc;
4702 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4703
4704 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4705 "[BTC], %s(): phy_idx=%d, band=%d\n",
4706 __func__, phy_idx, band);
4707 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
4708
4709 wl->scan_info.band[phy_idx] = band;
4710 wl->scan_info.phy_map |= BIT(phy_idx);
4711 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
4712
4713 if (rtwdev->dbcc_en) {
4714 wl->dbcc_info.scan_band[phy_idx] = band;
4715 _update_dbcc_band(rtwdev, phy_idx);
4716 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
4717 }
4718 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND);
4719 }
4720
4721 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev,
4722 enum btc_pkt_type pkt_type)
4723 {
4724 struct rtw89_btc *btc = &rtwdev->btc;
4725 struct rtw89_btc_cx *cx = &btc->cx;
4726 struct rtw89_btc_wl_info *wl = &cx->wl;
4727 struct rtw89_btc_bt_link_info *b = &cx->bt.link_info;
4728 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
4729 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
4730 u32 cnt;
4731 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD;
4732 bool delay_work = false;
4733
4734 switch (pkt_type) {
4735 case PACKET_DHCP:
4736 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP];
4737 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4738 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt);
4739 wl->status.map.connecting = true;
4740 delay_work = true;
4741 break;
4742 case PACKET_EAPOL:
4743 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
4744 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4745 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt);
4746 wl->status.map._4way = true;
4747 delay_work = true;
4748 if (hfp->exist || hid->exist)
4749 delay /= 2;
4750 break;
4751 case PACKET_EAPOL_END:
4752 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
4753 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4754 "[BTC], %s(): EAPOL_End cnt=%d\n",
4755 __func__, cnt);
4756 wl->status.map._4way = false;
4757 cancel_delayed_work(&rtwdev->coex_act1_work);
4758 break;
4759 case PACKET_ARP:
4760 cnt = ++cx->cnt_wl[BTC_WCNT_ARP];
4761 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4762 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt);
4763 return;
4764 case PACKET_ICMP:
4765 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4766 "[BTC], %s(): ICMP pkt\n", __func__);
4767 return;
4768 default:
4769 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4770 "[BTC], %s(): unknown packet type %d\n",
4771 __func__, pkt_type);
4772 return;
4773 }
4774
4775 if (delay_work) {
4776 cancel_delayed_work(&rtwdev->coex_act1_work);
4777 ieee80211_queue_delayed_work(rtwdev->hw,
4778 &rtwdev->coex_act1_work, delay);
4779 }
4780
4781 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
4782 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET);
4783 }
4784
4785 void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work)
4786 {
4787 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4788 btc.eapol_notify_work);
4789
4790 mutex_lock(&rtwdev->mutex);
4791 rtw89_leave_ps_mode(rtwdev);
4792 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL);
4793 mutex_unlock(&rtwdev->mutex);
4794 }
4795
4796 void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work)
4797 {
4798 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4799 btc.arp_notify_work);
4800
4801 mutex_lock(&rtwdev->mutex);
4802 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP);
4803 mutex_unlock(&rtwdev->mutex);
4804 }
4805
4806 void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work)
4807 {
4808 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4809 btc.dhcp_notify_work);
4810
4811 mutex_lock(&rtwdev->mutex);
4812 rtw89_leave_ps_mode(rtwdev);
4813 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP);
4814 mutex_unlock(&rtwdev->mutex);
4815 }
4816
4817 void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work)
4818 {
4819 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4820 btc.icmp_notify_work);
4821
4822 mutex_lock(&rtwdev->mutex);
4823 rtw89_leave_ps_mode(rtwdev);
4824 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP);
4825 mutex_unlock(&rtwdev->mutex);
4826 }
4827
4828 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
4829 {
4830 const struct rtw89_chip_info *chip = rtwdev->chip;
4831 struct rtw89_btc *btc = &rtwdev->btc;
4832 struct rtw89_btc_cx *cx = &btc->cx;
4833 struct rtw89_btc_bt_info *bt = &cx->bt;
4834 struct rtw89_btc_bt_link_info *b = &bt->link_info;
4835 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
4836 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
4837 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
4838 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc;
4839 union btc_btinfo btinfo;
4840
4841 if (buf[BTC_BTINFO_L1] != 6)
4842 return;
4843
4844 if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) {
4845 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4846 "[BTC], %s(): return by bt-info duplicate!!\n",
4847 __func__);
4848 cx->cnt_bt[BTC_BCNT_INFOSAME]++;
4849 return;
4850 }
4851
4852 memcpy(bt->raw_info, buf, BTC_BTINFO_MAX);
4853
4854 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4855 "[BTC], %s(): bt_info[2]=0x%02x\n",
4856 __func__, bt->raw_info[2]);
4857
4858 /* reset to mo-connect before update */
4859 b->status.val = BTC_BLINK_NOCONNECT;
4860 b->profile_cnt.last = b->profile_cnt.now;
4861 b->relink.last = b->relink.now;
4862 a2dp->exist_last = a2dp->exist;
4863 b->multi_link.last = b->multi_link.now;
4864 bt->inq_pag.last = bt->inq_pag.now;
4865 b->profile_cnt.now = 0;
4866 hid->type = 0;
4867
4868 /* parse raw info low-Byte2 */
4869 btinfo.val = bt->raw_info[BTC_BTINFO_L2];
4870 b->status.map.connect = btinfo.lb2.connect;
4871 b->status.map.sco_busy = btinfo.lb2.sco_busy;
4872 b->status.map.acl_busy = btinfo.lb2.acl_busy;
4873 b->status.map.inq_pag = btinfo.lb2.inq_pag;
4874 bt->inq_pag.now = btinfo.lb2.inq_pag;
4875 cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
4876
4877 hfp->exist = btinfo.lb2.hfp;
4878 b->profile_cnt.now += (u8)hfp->exist;
4879 hid->exist = btinfo.lb2.hid;
4880 b->profile_cnt.now += (u8)hid->exist;
4881 a2dp->exist = btinfo.lb2.a2dp;
4882 b->profile_cnt.now += (u8)a2dp->exist;
4883 pan->active = btinfo.lb2.pan;
4884
4885 /* parse raw info low-Byte3 */
4886 btinfo.val = bt->raw_info[BTC_BTINFO_L3];
4887 if (btinfo.lb3.retry != 0)
4888 cx->cnt_bt[BTC_BCNT_RETRY]++;
4889 b->cqddr = btinfo.lb3.cqddr;
4890 cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
4891 bt->inq = btinfo.lb3.inq;
4892 cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
4893 bt->pag = btinfo.lb3.pag;
4894
4895 b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
4896 /* parse raw info high-Byte0 */
4897 btinfo.val = bt->raw_info[BTC_BTINFO_H0];
4898 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/
4899 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi);
4900
4901 /* parse raw info high-Byte1 */
4902 btinfo.val = bt->raw_info[BTC_BTINFO_H1];
4903 b->status.map.ble_connect = btinfo.hb1.ble_connect;
4904 if (btinfo.hb1.ble_connect)
4905 hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU);
4906
4907 cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
4908 bt->reinit = btinfo.hb1.reinit;
4909 cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
4910 b->relink.now = btinfo.hb1.relink;
4911 cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
4912 bt->igno_wl = btinfo.hb1.igno_wl;
4913
4914 if (bt->igno_wl && !cx->wl.status.map.rf_off)
4915 _set_bt_ignore_wlan_act(rtwdev, false);
4916
4917 hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0);
4918 bt->ble_scan_en = btinfo.hb1.ble_scan;
4919
4920 cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
4921 b->role_sw = btinfo.hb1.role_sw;
4922
4923 b->multi_link.now = btinfo.hb1.multi_link;
4924
4925 /* parse raw info high-Byte2 */
4926 btinfo.val = bt->raw_info[BTC_BTINFO_H2];
4927 pan->exist = btinfo.hb2.pan_active;
4928 b->profile_cnt.now += (u8)pan->exist;
4929
4930 cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
4931 b->afh_update = btinfo.hb2.afh_update;
4932 a2dp->active = btinfo.hb2.a2dp_active;
4933 b->slave_role = btinfo.hb2.slave;
4934 hid->slot_info = btinfo.hb2.hid_slot;
4935 hid->pair_cnt = btinfo.hb2.hid_cnt;
4936 hid->type |= (hid->slot_info == BTC_HID_218 ?
4937 BTC_HID_218 : BTC_HID_418);
4938 /* parse raw info high-Byte3 */
4939 btinfo.val = bt->raw_info[BTC_BTINFO_H3];
4940 a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
4941
4942 if (b->tx_3m != (u32)btinfo.hb3.tx_3m)
4943 cx->cnt_bt[BTC_BCNT_RATECHG]++;
4944 b->tx_3m = (u32)btinfo.hb3.tx_3m;
4945
4946 a2dp->sink = btinfo.hb3.a2dp_sink;
4947
4948 if (b->profile_cnt.now || b->status.map.ble_connect)
4949 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, 1);
4950 else
4951 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, 0);
4952
4953 if (!a2dp->exist_last && a2dp->exist) {
4954 a2dp->vendor_id = 0;
4955 a2dp->flush_time = 0;
4956 a2dp->play_latency = 1;
4957 ieee80211_queue_delayed_work(rtwdev->hw,
4958 &rtwdev->coex_bt_devinfo_work,
4959 RTW89_COEX_BT_DEVINFO_WORK_PERIOD);
4960 }
4961
4962 if (a2dp->exist && (a2dp->flush_time == 0 || a2dp->vendor_id == 0 ||
4963 a2dp->play_latency == 1))
4964 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, 1);
4965 else
4966 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, 0);
4967
4968 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
4969 }
4970
4971 enum btc_wl_mode {
4972 BTC_WL_MODE_HT = 0,
4973 BTC_WL_MODE_VHT = 1,
4974 BTC_WL_MODE_HE = 2,
4975 BTC_WL_MODE_NUM,
4976 };
4977
4978 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
4979 struct rtw89_sta *rtwsta, enum btc_role_state state)
4980 {
4981 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
4982 const struct rtw89_chip_info *chip = rtwdev->chip;
4983 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
4984 struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
4985 struct rtw89_btc *btc = &rtwdev->btc;
4986 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4987 struct rtw89_btc_wl_link_info r = {0};
4988 struct rtw89_btc_wl_link_info *wlinfo = NULL;
4989 u8 mode = 0;
4990
4991 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
4992 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4993 "[BTC], role is STA=%d\n",
4994 vif->type == NL80211_IFTYPE_STATION);
4995 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port);
4996 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
4997 chan->band_type, chan->channel, chan->band_width);
4998 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
4999 state == BTC_ROLE_MSTS_STA_CONN_END);
5000 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5001 "[BTC], bcn_period=%d dtim_period=%d\n",
5002 vif->bss_conf.beacon_int, vif->bss_conf.dtim_period);
5003
5004 if (rtwsta) {
5005 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
5006 rtwsta->mac_id);
5007
5008 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5009 "[BTC], STA support HE=%d VHT=%d HT=%d\n",
5010 sta->deflink.he_cap.has_he,
5011 sta->deflink.vht_cap.vht_supported,
5012 sta->deflink.ht_cap.ht_supported);
5013 if (sta->deflink.he_cap.has_he)
5014 mode |= BIT(BTC_WL_MODE_HE);
5015 if (sta->deflink.vht_cap.vht_supported)
5016 mode |= BIT(BTC_WL_MODE_VHT);
5017 if (sta->deflink.ht_cap.ht_supported)
5018 mode |= BIT(BTC_WL_MODE_HT);
5019
5020 r.mode = mode;
5021 }
5022
5023 if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX)
5024 return;
5025
5026 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5027 "[BTC], wifi_role=%d\n", rtwvif->wifi_role);
5028
5029 r.role = rtwvif->wifi_role;
5030 r.phy = rtwvif->phy_idx;
5031 r.pid = rtwvif->port;
5032 r.active = true;
5033 r.connected = MLME_LINKED;
5034 r.bcn_period = vif->bss_conf.beacon_int;
5035 r.dtim_period = vif->bss_conf.dtim_period;
5036 r.band = chan->band_type;
5037 r.ch = chan->channel;
5038 r.bw = chan->band_width;
5039 ether_addr_copy(r.mac_addr, rtwvif->mac_addr);
5040
5041 if (rtwsta && vif->type == NL80211_IFTYPE_STATION)
5042 r.mac_id = rtwsta->mac_id;
5043
5044 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
5045
5046 wlinfo = &wl->link_info[r.pid];
5047
5048 memcpy(wlinfo, &r, sizeof(*wlinfo));
5049 if (chip->chip_id == RTL8852A)
5050 _update_wl_info(rtwdev);
5051 else
5052 _update_wl_info_v1(rtwdev);
5053
5054 if (wlinfo->role == RTW89_WIFI_ROLE_STATION &&
5055 wlinfo->connected == MLME_NO_LINK)
5056 btc->dm.leak_ap = 0;
5057
5058 if (state == BTC_ROLE_MSTS_STA_CONN_START)
5059 wl->status.map.connecting = 1;
5060 else
5061 wl->status.map.connecting = 0;
5062
5063 if (state == BTC_ROLE_MSTS_STA_DIS_CONN)
5064 wl->status.map._4way = false;
5065
5066 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
5067 }
5068
5069 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state)
5070 {
5071 const struct rtw89_chip_info *chip = rtwdev->chip;
5072 struct rtw89_btc *btc = &rtwdev->btc;
5073 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5074 u32 val;
5075
5076 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
5077 __func__, rf_state);
5078 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
5079
5080 switch (rf_state) {
5081 case BTC_RFCTRL_WL_OFF:
5082 wl->status.map.rf_off = 1;
5083 wl->status.map.lps = BTC_LPS_OFF;
5084 wl->status.map.busy = 0;
5085 break;
5086 case BTC_RFCTRL_FW_CTRL:
5087 wl->status.map.rf_off = 0;
5088 wl->status.map.lps = BTC_LPS_RF_OFF;
5089 wl->status.map.busy = 0;
5090 break;
5091 case BTC_RFCTRL_WL_ON:
5092 default:
5093 wl->status.map.rf_off = 0;
5094 wl->status.map.lps = BTC_LPS_OFF;
5095 break;
5096 }
5097
5098 if (rf_state == BTC_RFCTRL_WL_ON) {
5099 btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] = 0;
5100 rtw89_btc_fw_en_rpt(rtwdev,
5101 RPT_EN_MREG | RPT_EN_BT_VER_INFO, true);
5102 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG;
5103 _write_scbd(rtwdev, val, true);
5104 _update_bt_scbd(rtwdev, true);
5105 chip->ops->btc_init_cfg(rtwdev);
5106 } else {
5107 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false);
5108 if (rf_state == BTC_RFCTRL_WL_OFF)
5109 _write_scbd(rtwdev, BTC_WSCB_ALL, false);
5110 }
5111
5112 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
5113
5114 wl->status.map.rf_off_pre = wl->status.map.rf_off;
5115 wl->status.map.lps_pre = wl->status.map.lps;
5116 }
5117
5118 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path,
5119 enum btc_wl_rfk_type type,
5120 enum btc_wl_rfk_state state)
5121 {
5122 struct rtw89_btc *btc = &rtwdev->btc;
5123 struct rtw89_btc_cx *cx = &btc->cx;
5124 struct rtw89_btc_wl_info *wl = &cx->wl;
5125 bool result = BTC_WRFK_REJECT;
5126
5127 wl->rfk_info.type = type;
5128 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path);
5129 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path);
5130 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path);
5131
5132 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5133 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
5134 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
5135 type, state);
5136
5137 switch (state) {
5138 case BTC_WRFK_START:
5139 result = _chk_wl_rfk_request(rtwdev);
5140 wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP;
5141
5142 _write_scbd(rtwdev, BTC_WSCB_WLRFK, result);
5143
5144 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
5145 break;
5146 case BTC_WRFK_ONESHOT_START:
5147 case BTC_WRFK_ONESHOT_STOP:
5148 if (wl->rfk_info.state == BTC_WRFK_STOP) {
5149 result = BTC_WRFK_REJECT;
5150 } else {
5151 result = BTC_WRFK_ALLOW;
5152 wl->rfk_info.state = state;
5153 }
5154 break;
5155 case BTC_WRFK_STOP:
5156 result = BTC_WRFK_ALLOW;
5157 wl->rfk_info.state = BTC_WRFK_STOP;
5158
5159 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
5160 cancel_delayed_work(&rtwdev->coex_rfk_chk_work);
5161 break;
5162 default:
5163 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5164 "[BTC], %s() warning state=%d\n", __func__, state);
5165 break;
5166 }
5167
5168 if (result == BTC_WRFK_ALLOW) {
5169 if (wl->rfk_info.state == BTC_WRFK_START ||
5170 wl->rfk_info.state == BTC_WRFK_STOP)
5171 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK);
5172
5173 if (wl->rfk_info.state == BTC_WRFK_START)
5174 ieee80211_queue_delayed_work(rtwdev->hw,
5175 &rtwdev->coex_rfk_chk_work,
5176 RTW89_COEX_RFK_CHK_WORK_PERIOD);
5177 }
5178
5179 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5180 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
5181 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
5182
5183 return result == BTC_WRFK_ALLOW;
5184 }
5185
5186 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
5187 enum btc_wl_rfk_type type,
5188 enum btc_wl_rfk_state state)
5189 {
5190 u8 band;
5191 bool allow;
5192 int ret;
5193
5194 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map);
5195
5196 rtw89_debug(rtwdev, RTW89_DBG_RFK,
5197 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n",
5198 band == RTW89_BAND_2G ? "2G" :
5199 band == RTW89_BAND_5G ? "5G" : "6G",
5200 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)),
5201 type,
5202 FIELD_GET(BTC_RFK_PATH_MAP, phy_map),
5203 state == BTC_WRFK_STOP ? "RFK_STOP" :
5204 state == BTC_WRFK_START ? "RFK_START" :
5205 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" :
5206 "ONE-SHOT_STOP");
5207
5208 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) {
5209 _ntfy_wl_rfk(rtwdev, phy_map, type, state);
5210 return;
5211 }
5212
5213 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false,
5214 rtwdev, phy_map, type, state);
5215 if (ret) {
5216 rtw89_warn(rtwdev, "RFK notify timeout\n");
5217 rtwdev->is_bt_iqk_timeout = true;
5218 }
5219 }
5220 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk);
5221
5222 struct rtw89_btc_wl_sta_iter_data {
5223 struct rtw89_dev *rtwdev;
5224 u8 busy_all;
5225 u8 dir_all;
5226 u8 rssi_map_all;
5227 bool is_sta_change;
5228 bool is_traffic_change;
5229 };
5230
5231 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
5232 {
5233 struct rtw89_btc_wl_sta_iter_data *iter_data =
5234 (struct rtw89_btc_wl_sta_iter_data *)data;
5235 struct rtw89_dev *rtwdev = iter_data->rtwdev;
5236 struct rtw89_btc *btc = &rtwdev->btc;
5237 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5238 struct rtw89_btc_wl_link_info *link_info = NULL;
5239 struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
5240 struct rtw89_traffic_stats *link_info_t = NULL;
5241 struct rtw89_vif *rtwvif = rtwsta->rtwvif;
5242 struct rtw89_traffic_stats *stats = &rtwvif->stats;
5243 const struct rtw89_chip_info *chip = rtwdev->chip;
5244 u32 last_tx_rate, last_rx_rate;
5245 u16 last_tx_lvl, last_rx_lvl;
5246 u8 port = rtwvif->port;
5247 u8 rssi;
5248 u8 busy = 0;
5249 u8 dir = 0;
5250 u8 rssi_map = 0;
5251 u8 i = 0;
5252 bool is_sta_change = false, is_traffic_change = false;
5253
5254 rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR;
5255 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
5256
5257 link_info = &wl->link_info[port];
5258 link_info->stat.traffic = rtwvif->stats;
5259 link_info_t = &link_info->stat.traffic;
5260
5261 if (link_info->connected == MLME_NO_LINK) {
5262 link_info->rx_rate_drop_cnt = 0;
5263 return;
5264 }
5265
5266 link_info->stat.rssi = rssi;
5267 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) {
5268 link_info->rssi_state[i] =
5269 _update_rssi_state(rtwdev,
5270 link_info->rssi_state[i],
5271 link_info->stat.rssi,
5272 chip->wl_rssi_thres[i]);
5273 if (BTC_RSSI_LOW(link_info->rssi_state[i]))
5274 rssi_map |= BIT(i);
5275
5276 if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED &&
5277 BTC_RSSI_CHANGE(link_info->rssi_state[i]))
5278 is_sta_change = true;
5279 }
5280 iter_data->rssi_map_all |= rssi_map;
5281
5282 last_tx_rate = link_info_t->tx_rate;
5283 last_rx_rate = link_info_t->rx_rate;
5284 last_tx_lvl = (u16)link_info_t->tx_tfc_lv;
5285 last_rx_lvl = (u16)link_info_t->rx_tfc_lv;
5286
5287 if (stats->tx_tfc_lv != RTW89_TFC_IDLE ||
5288 stats->rx_tfc_lv != RTW89_TFC_IDLE)
5289 busy = 1;
5290
5291 if (stats->tx_tfc_lv > stats->rx_tfc_lv)
5292 dir = RTW89_TFC_UL;
5293 else
5294 dir = RTW89_TFC_DL;
5295
5296 link_info = &wl->link_info[port];
5297 if (link_info->busy != busy || link_info->dir != dir) {
5298 is_sta_change = true;
5299 link_info->busy = busy;
5300 link_info->dir = dir;
5301 }
5302
5303 iter_data->busy_all |= busy;
5304 iter_data->dir_all |= BIT(dir);
5305
5306 if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
5307 last_rx_rate > RTW89_HW_RATE_CCK2 &&
5308 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
5309 link_info->rx_rate_drop_cnt++;
5310
5311 if (last_tx_rate != rtwsta->ra_report.hw_rate ||
5312 last_rx_rate != rtwsta->rx_hw_rate ||
5313 last_tx_lvl != link_info_t->tx_tfc_lv ||
5314 last_rx_lvl != link_info_t->rx_tfc_lv)
5315 is_traffic_change = true;
5316
5317 link_info_t->tx_rate = rtwsta->ra_report.hw_rate;
5318 link_info_t->rx_rate = rtwsta->rx_hw_rate;
5319
5320 wl->role_info.active_role[port].tx_lvl = (u16)stats->tx_tfc_lv;
5321 wl->role_info.active_role[port].rx_lvl = (u16)stats->rx_tfc_lv;
5322 wl->role_info.active_role[port].tx_rate = rtwsta->ra_report.hw_rate;
5323 wl->role_info.active_role[port].rx_rate = rtwsta->rx_hw_rate;
5324
5325 if (is_sta_change)
5326 iter_data->is_sta_change = true;
5327
5328 if (is_traffic_change)
5329 iter_data->is_traffic_change = true;
5330 }
5331
5332 #define BTC_NHM_CHK_INTVL 20
5333
5334 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
5335 {
5336 struct rtw89_btc *btc = &rtwdev->btc;
5337 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5338 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev};
5339 u8 i;
5340
5341 ieee80211_iterate_stations_atomic(rtwdev->hw,
5342 rtw89_btc_ntfy_wl_sta_iter,
5343 &data);
5344
5345 wl->rssi_level = 0;
5346 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++;
5347 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) {
5348 /* set RSSI level 4 ~ 0 if rssi bit map match */
5349 if (data.rssi_map_all & BIT(i - 1)) {
5350 wl->rssi_level = i;
5351 break;
5352 }
5353 }
5354
5355 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n",
5356 __func__, !!wl->status.map.busy);
5357
5358 _write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy));
5359
5360 if (data.is_traffic_change)
5361 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
5362 if (data.is_sta_change) {
5363 wl->status.map.busy = data.busy_all;
5364 wl->status.map.traffic_dir = data.dir_all;
5365 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA);
5366 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >=
5367 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) {
5368 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
5369 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
5370 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] <
5371 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) {
5372 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
5373 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
5374 }
5375 }
5376
5377 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
5378 u32 len, u8 class, u8 func)
5379 {
5380 struct rtw89_btc *btc = &rtwdev->btc;
5381 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
5382 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN];
5383
5384 len -= RTW89_C2H_HEADER_LEN;
5385
5386 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5387 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n",
5388 __func__, len, class, func);
5389
5390 if (class != BTFC_FW_EVENT)
5391 return;
5392
5393 switch (func) {
5394 case BTF_EVNT_RPT:
5395 case BTF_EVNT_BUF_OVERFLOW:
5396 pfwinfo->event[func]++;
5397 /* Don't need rtw89_leave_ps_mode() */
5398 btc_fw_event(rtwdev, func, buf, len);
5399 break;
5400 case BTF_EVNT_BT_INFO:
5401 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5402 "[BTC], handle C2H BT INFO with data %8ph\n", buf);
5403 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++;
5404 _update_bt_info(rtwdev, buf, len);
5405 break;
5406 case BTF_EVNT_BT_SCBD:
5407 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5408 "[BTC], handle C2H BT SCBD with data %8ph\n", buf);
5409 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++;
5410 _update_bt_scbd(rtwdev, false);
5411 break;
5412 case BTF_EVNT_BT_PSD:
5413 break;
5414 case BTF_EVNT_BT_REG:
5415 btc->dbg.rb_done = true;
5416 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf));
5417
5418 break;
5419 case BTF_EVNT_C2H_LOOPBACK:
5420 btc->dbg.rb_done = true;
5421 btc->dbg.rb_val = buf[0];
5422 break;
5423 case BTF_EVNT_CX_RUNINFO:
5424 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
5425 break;
5426 }
5427 }
5428
5429 #define BTC_CX_FW_OFFLOAD 0
5430
5431 static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5432 {
5433 const struct rtw89_chip_info *chip = rtwdev->chip;
5434 struct rtw89_hal *hal = &rtwdev->hal;
5435 struct rtw89_btc *btc = &rtwdev->btc;
5436 struct rtw89_btc_dm *dm = &btc->dm;
5437 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5438 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5439 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
5440
5441 if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
5442 return;
5443
5444 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
5445
5446 seq_printf(m, "========== [BTC COEX INFO (%d)] ==========\n",
5447 chip->chip_id);
5448
5449 ver_main = FIELD_GET(GENMASK(31, 24), chip->para_ver);
5450 ver_sub = FIELD_GET(GENMASK(23, 16), chip->para_ver);
5451 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->para_ver);
5452 id_branch = FIELD_GET(GENMASK(7, 0), chip->para_ver);
5453 seq_printf(m, " %-15s : Coex:%d.%d.%d(branch:%d), ",
5454 "[coex_version]", ver_main, ver_sub, ver_hotfix, id_branch);
5455
5456 if (dm->wl_fw_cx_offload != BTC_CX_FW_OFFLOAD)
5457 dm->error.map.offload_mismatch = true;
5458 else
5459 dm->error.map.offload_mismatch = false;
5460
5461 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
5462 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex);
5463 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex);
5464 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex);
5465 seq_printf(m, "WL_FW_coex:%d.%d.%d(branch:%d)",
5466 ver_main, ver_sub, ver_hotfix, id_branch);
5467
5468 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired);
5469 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired);
5470 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
5471 seq_printf(m, "(%s, desired:%d.%d.%d), ",
5472 (wl->ver_info.fw_coex >= chip->wlcx_desired ?
5473 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
5474
5475 seq_printf(m, "BT_FW_coex:%d(%s, desired:%d)\n",
5476 bt->ver_info.fw_coex,
5477 (bt->ver_info.fw_coex >= chip->btcx_desired ?
5478 "Match" : "Mismatch"), chip->btcx_desired);
5479
5480 if (bt->enable.now && bt->ver_info.fw == 0)
5481 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true);
5482 else
5483 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false);
5484
5485 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw);
5486 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw);
5487 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw);
5488 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw);
5489 seq_printf(m, " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n",
5490 "[sub_module]",
5491 ver_main, ver_sub, ver_hotfix, id_branch,
5492 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM");
5493
5494 seq_printf(m, " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s",
5495 "[hw_info]", btc->mdinfo.cv, btc->mdinfo.rfe_type,
5496 btc->mdinfo.ant.isolation, btc->mdinfo.ant.num,
5497 (btc->mdinfo.ant.num > 1 ? "" : (btc->mdinfo.ant.single_pos ?
5498 "1Ant_Pos:S1, " : "1Ant_Pos:S0, ")));
5499
5500 seq_printf(m, "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n",
5501 btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss,
5502 hal->rx_nss);
5503 }
5504
5505 static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5506 {
5507 struct rtw89_btc *btc = &rtwdev->btc;
5508 struct rtw89_btc_wl_link_info *plink = NULL;
5509 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5510 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5511 struct rtw89_traffic_stats *t;
5512 u8 i;
5513
5514 if (rtwdev->dbcc_en) {
5515 seq_printf(m,
5516 " %-15s : PHY0_band(op:%d/scan:%d/real:%d), ",
5517 "[dbcc_info]", wl_dinfo->op_band[RTW89_PHY_0],
5518 wl_dinfo->scan_band[RTW89_PHY_0],
5519 wl_dinfo->real_band[RTW89_PHY_0]);
5520 seq_printf(m,
5521 "PHY1_band(op:%d/scan:%d/real:%d)\n",
5522 wl_dinfo->op_band[RTW89_PHY_1],
5523 wl_dinfo->scan_band[RTW89_PHY_1],
5524 wl_dinfo->real_band[RTW89_PHY_1]);
5525 }
5526
5527 for (i = 0; i < RTW89_PORT_NUM; i++) {
5528 plink = &btc->cx.wl.link_info[i];
5529
5530 if (!plink->active)
5531 continue;
5532
5533 seq_printf(m,
5534 " [port_%d] : role=%d(phy-%d), connect=%d(client_cnt=%d), mode=%d, center_ch=%d, bw=%d",
5535 plink->pid, (u32)plink->role, plink->phy,
5536 (u32)plink->connected, plink->client_cnt - 1,
5537 (u32)plink->mode, plink->ch, (u32)plink->bw);
5538
5539 if (plink->connected == MLME_NO_LINK)
5540 continue;
5541
5542 seq_printf(m,
5543 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n",
5544 plink->mac_id, plink->tx_time, plink->tx_retry);
5545
5546 seq_printf(m,
5547 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
5548 plink->pid, 110 - plink->stat.rssi,
5549 plink->stat.rssi, plink->busy,
5550 plink->dir == RTW89_TFC_UL ? "UL" : "DL");
5551
5552 t = &plink->stat.traffic;
5553
5554 seq_printf(m,
5555 "tx[rate:%d/busy_level:%d], ",
5556 (u32)t->tx_rate, t->tx_tfc_lv);
5557
5558 seq_printf(m, "rx[rate:%d/busy_level:%d/drop:%d]\n",
5559 (u32)t->rx_rate,
5560 t->rx_tfc_lv, plink->rx_rate_drop_cnt);
5561 }
5562 }
5563
5564 static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5565 {
5566 const struct rtw89_chip_info *chip = rtwdev->chip;
5567 struct rtw89_btc *btc = &rtwdev->btc;
5568 struct rtw89_btc_cx *cx = &btc->cx;
5569 struct rtw89_btc_wl_info *wl = &cx->wl;
5570 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5571 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5572 u8 mode;
5573
5574 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
5575 return;
5576
5577 seq_puts(m, "========== [WL Status] ==========\n");
5578
5579 if (chip->chip_id == RTL8852A)
5580 mode = wl_rinfo->link_mode;
5581 else
5582 mode = wl_rinfo_v1->link_mode;
5583
5584 seq_printf(m, " %-15s : link_mode:%d, ", "[status]", mode);
5585
5586 seq_printf(m,
5587 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ",
5588 wl->status.map.rf_off, wl->status.map.lps,
5589 wl->status.map.scan ? "Y" : "N",
5590 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
5591
5592 seq_printf(m,
5593 "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n",
5594 wl->status.map.connecting ? "Y" : "N",
5595 wl->status.map.roaming ? "Y" : "N",
5596 wl->status.map._4way ? "Y" : "N",
5597 wl->status.map.init_ok ? "Y" : "N");
5598
5599 _show_wl_role_info(rtwdev, m);
5600 }
5601
5602 enum btc_bt_a2dp_type {
5603 BTC_A2DP_LEGACY = 0,
5604 BTC_A2DP_TWS_SNIFF = 1,
5605 BTC_A2DP_TWS_RELAY = 2,
5606 };
5607
5608 static void _show_bt_profile_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5609 {
5610 struct rtw89_btc *btc = &rtwdev->btc;
5611 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
5612 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
5613 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
5614 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
5615 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
5616
5617 if (hfp.exist) {
5618 seq_printf(m, " %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
5619 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"),
5620 bt_linfo->sut_pwr_level[0],
5621 bt_linfo->golden_rx_shift[0]);
5622 }
5623
5624 if (hid.exist) {
5625 seq_printf(m,
5626 "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n",
5627 "[HID]",
5628 hid.type & BTC_HID_218 ? "2/18," : "",
5629 hid.type & BTC_HID_418 ? "4/18," : "",
5630 hid.type & BTC_HID_BLE ? "BLE," : "",
5631 hid.type & BTC_HID_RCU ? "RCU," : "",
5632 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "",
5633 hid.pair_cnt, bt_linfo->sut_pwr_level[1],
5634 bt_linfo->golden_rx_shift[1]);
5635 }
5636
5637 if (a2dp.exist) {
5638 seq_printf(m,
5639 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
5640 "[A2DP]",
5641 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS",
5642 a2dp.bitpool, a2dp.flush_time);
5643
5644 seq_printf(m,
5645 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n",
5646 a2dp.vendor_id, a2dp.device_name,
5647 bt_linfo->sut_pwr_level[2],
5648 bt_linfo->golden_rx_shift[2]);
5649 }
5650
5651 if (pan.exist) {
5652 seq_printf(m, " %-15s : sut_pwr:%d, golden-rx:%d\n",
5653 "[PAN]",
5654 bt_linfo->sut_pwr_level[3],
5655 bt_linfo->golden_rx_shift[3]);
5656 }
5657 }
5658
5659 static void _show_bt_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5660 {
5661 struct rtw89_btc *btc = &rtwdev->btc;
5662 struct rtw89_btc_cx *cx = &btc->cx;
5663 struct rtw89_btc_bt_info *bt = &cx->bt;
5664 struct rtw89_btc_wl_info *wl = &cx->wl;
5665 struct rtw89_btc_module *module = &btc->mdinfo;
5666 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
5667 u8 *afh = bt_linfo->afh_map;
5668
5669 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
5670 return;
5671
5672 seq_puts(m, "========== [BT Status] ==========\n");
5673
5674 seq_printf(m, " %-15s : enable:%s, btg:%s%s, connect:%s, ",
5675 "[status]", bt->enable.now ? "Y" : "N",
5676 bt->btg_type ? "Y" : "N",
5677 (bt->enable.now && (bt->btg_type != module->bt_pos) ?
5678 "(efuse-mismatch!!)" : ""),
5679 (bt_linfo->status.map.connect ? "Y" : "N"));
5680
5681 seq_printf(m, "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n",
5682 bt->igno_wl ? "Y" : "N",
5683 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val);
5684
5685 seq_printf(m, " %-15s : profile:%s%s%s%s%s ",
5686 "[profile]",
5687 (bt_linfo->profile_cnt.now == 0) ? "None," : "",
5688 bt_linfo->hfp_desc.exist ? "HFP," : "",
5689 bt_linfo->hid_desc.exist ? "HID," : "",
5690 bt_linfo->a2dp_desc.exist ?
5691 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "",
5692 bt_linfo->pan_desc.exist ? "PAN," : "");
5693
5694 seq_printf(m,
5695 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n",
5696 bt_linfo->multi_link.now ? "Y" : "N",
5697 bt_linfo->slave_role ? "Slave" : "Master",
5698 bt_linfo->status.map.ble_connect ? "Y" : "N",
5699 bt_linfo->cqddr ? "Y" : "N",
5700 bt_linfo->a2dp_desc.active ? "Y" : "N",
5701 bt_linfo->pan_desc.active ? "Y" : "N");
5702
5703 seq_printf(m,
5704 " %-15s : rssi:%ddBm, tx_rate:%dM, %s%s%s",
5705 "[link]", bt_linfo->rssi - 100,
5706 bt_linfo->tx_3m ? 3 : 2,
5707 bt_linfo->status.map.inq_pag ? " inq-page!!" : "",
5708 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "",
5709 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : "");
5710
5711 seq_printf(m,
5712 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
5713 bt_linfo->relink.now ? " ReLink!!" : "",
5714 afh[0], afh[1], afh[2], afh[3], afh[4],
5715 afh[5], afh[6], afh[7], afh[8], afh[9]);
5716
5717 seq_printf(m, "wl_ch_map[en:%d/ch:%d/bw:%d]\n",
5718 wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw);
5719
5720 seq_printf(m,
5721 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
5722 "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY],
5723 cx->cnt_bt[BTC_BCNT_RELINK], cx->cnt_bt[BTC_BCNT_RATECHG],
5724 cx->cnt_bt[BTC_BCNT_REINIT], cx->cnt_bt[BTC_BCNT_REENABLE]);
5725
5726 seq_printf(m,
5727 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n",
5728 cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH],
5729 cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ],
5730 cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]);
5731
5732 _show_bt_profile_info(rtwdev, m);
5733
5734 seq_printf(m,
5735 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n",
5736 "[bt_info]", bt->raw_info[2], bt->raw_info[3],
5737 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6],
5738 bt->raw_info[7],
5739 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
5740 cx->cnt_bt[BTC_BCNT_INFOUPDATE],
5741 cx->cnt_bt[BTC_BCNT_INFOSAME]);
5742
5743 seq_printf(m,
5744 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)\n",
5745 "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX],
5746 cx->cnt_bt[BTC_BCNT_HIPRI_TX], cx->cnt_bt[BTC_BCNT_LOPRI_RX],
5747 cx->cnt_bt[BTC_BCNT_LOPRI_TX], cx->cnt_bt[BTC_BCNT_POLUT]);
5748 }
5749
5750 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e
5751 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
5752 #define CASE_BTC_POLICY_STR(e) \
5753 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
5754
5755 static const char *steps_to_str(u16 step)
5756 {
5757 switch (step) {
5758 CASE_BTC_RSN_STR(NONE);
5759 CASE_BTC_RSN_STR(NTFY_INIT);
5760 CASE_BTC_RSN_STR(NTFY_SWBAND);
5761 CASE_BTC_RSN_STR(NTFY_WL_STA);
5762 CASE_BTC_RSN_STR(NTFY_RADIO_STATE);
5763 CASE_BTC_RSN_STR(UPDATE_BT_SCBD);
5764 CASE_BTC_RSN_STR(NTFY_WL_RFK);
5765 CASE_BTC_RSN_STR(UPDATE_BT_INFO);
5766 CASE_BTC_RSN_STR(NTFY_SCAN_START);
5767 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH);
5768 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET);
5769 CASE_BTC_RSN_STR(NTFY_POWEROFF);
5770 CASE_BTC_RSN_STR(NTFY_ROLE_INFO);
5771 CASE_BTC_RSN_STR(CMD_SET_COEX);
5772 CASE_BTC_RSN_STR(ACT1_WORK);
5773 CASE_BTC_RSN_STR(BT_DEVINFO_WORK);
5774 CASE_BTC_RSN_STR(RFK_CHK_WORK);
5775
5776 CASE_BTC_ACT_STR(NONE);
5777 CASE_BTC_ACT_STR(WL_ONLY);
5778 CASE_BTC_ACT_STR(WL_5G);
5779 CASE_BTC_ACT_STR(WL_OTHER);
5780 CASE_BTC_ACT_STR(WL_IDLE);
5781 CASE_BTC_ACT_STR(WL_NC);
5782 CASE_BTC_ACT_STR(WL_RFK);
5783 CASE_BTC_ACT_STR(WL_INIT);
5784 CASE_BTC_ACT_STR(WL_OFF);
5785 CASE_BTC_ACT_STR(FREERUN);
5786 CASE_BTC_ACT_STR(BT_WHQL);
5787 CASE_BTC_ACT_STR(BT_RFK);
5788 CASE_BTC_ACT_STR(BT_OFF);
5789 CASE_BTC_ACT_STR(BT_IDLE);
5790 CASE_BTC_ACT_STR(BT_HFP);
5791 CASE_BTC_ACT_STR(BT_HID);
5792 CASE_BTC_ACT_STR(BT_A2DP);
5793 CASE_BTC_ACT_STR(BT_A2DPSINK);
5794 CASE_BTC_ACT_STR(BT_PAN);
5795 CASE_BTC_ACT_STR(BT_A2DP_HID);
5796 CASE_BTC_ACT_STR(BT_A2DP_PAN);
5797 CASE_BTC_ACT_STR(BT_PAN_HID);
5798 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID);
5799 CASE_BTC_ACT_STR(WL_25G_MCC);
5800 CASE_BTC_ACT_STR(WL_2G_MCC);
5801 CASE_BTC_ACT_STR(WL_2G_SCC);
5802 CASE_BTC_ACT_STR(WL_2G_AP);
5803 CASE_BTC_ACT_STR(WL_2G_GO);
5804 CASE_BTC_ACT_STR(WL_2G_GC);
5805 CASE_BTC_ACT_STR(WL_2G_NAN);
5806
5807 CASE_BTC_POLICY_STR(OFF_BT);
5808 CASE_BTC_POLICY_STR(OFF_WL);
5809 CASE_BTC_POLICY_STR(OFF_EQ0);
5810 CASE_BTC_POLICY_STR(OFF_EQ1);
5811 CASE_BTC_POLICY_STR(OFF_EQ2);
5812 CASE_BTC_POLICY_STR(OFF_EQ3);
5813 CASE_BTC_POLICY_STR(OFF_BWB0);
5814 CASE_BTC_POLICY_STR(OFF_BWB1);
5815 CASE_BTC_POLICY_STR(OFF_BWB2);
5816 CASE_BTC_POLICY_STR(OFFB_BWB0);
5817 CASE_BTC_POLICY_STR(OFFE_DEF);
5818 CASE_BTC_POLICY_STR(OFFE_DEF2);
5819 CASE_BTC_POLICY_STR(OFFE_2GBWISOB);
5820 CASE_BTC_POLICY_STR(OFFE_2GISOB);
5821 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB);
5822 CASE_BTC_POLICY_STR(OFFE_WL);
5823 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2);
5824 CASE_BTC_POLICY_STR(FIX_TD3030);
5825 CASE_BTC_POLICY_STR(FIX_TD5050);
5826 CASE_BTC_POLICY_STR(FIX_TD2030);
5827 CASE_BTC_POLICY_STR(FIX_TD4010);
5828 CASE_BTC_POLICY_STR(FIX_TD7010);
5829 CASE_BTC_POLICY_STR(FIX_TD2060);
5830 CASE_BTC_POLICY_STR(FIX_TD3060);
5831 CASE_BTC_POLICY_STR(FIX_TD2080);
5832 CASE_BTC_POLICY_STR(FIX_TDW1B1);
5833 CASE_BTC_POLICY_STR(FIX_TD4020);
5834 CASE_BTC_POLICY_STR(FIX_TD4010ISO);
5835 CASE_BTC_POLICY_STR(PFIX_TD3030);
5836 CASE_BTC_POLICY_STR(PFIX_TD5050);
5837 CASE_BTC_POLICY_STR(PFIX_TD2030);
5838 CASE_BTC_POLICY_STR(PFIX_TD2060);
5839 CASE_BTC_POLICY_STR(PFIX_TD3070);
5840 CASE_BTC_POLICY_STR(PFIX_TD2080);
5841 CASE_BTC_POLICY_STR(PFIX_TDW1B1);
5842 CASE_BTC_POLICY_STR(AUTO_TD50B1);
5843 CASE_BTC_POLICY_STR(AUTO_TD60B1);
5844 CASE_BTC_POLICY_STR(AUTO_TD20B1);
5845 CASE_BTC_POLICY_STR(AUTO_TDW1B1);
5846 CASE_BTC_POLICY_STR(PAUTO_TD50B1);
5847 CASE_BTC_POLICY_STR(PAUTO_TD60B1);
5848 CASE_BTC_POLICY_STR(PAUTO_TD20B1);
5849 CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
5850 CASE_BTC_POLICY_STR(AUTO2_TD3050);
5851 CASE_BTC_POLICY_STR(AUTO2_TD3070);
5852 CASE_BTC_POLICY_STR(AUTO2_TD5050);
5853 CASE_BTC_POLICY_STR(AUTO2_TD6060);
5854 CASE_BTC_POLICY_STR(AUTO2_TD2080);
5855 CASE_BTC_POLICY_STR(AUTO2_TDW1B4);
5856 CASE_BTC_POLICY_STR(PAUTO2_TD3050);
5857 CASE_BTC_POLICY_STR(PAUTO2_TD3070);
5858 CASE_BTC_POLICY_STR(PAUTO2_TD5050);
5859 CASE_BTC_POLICY_STR(PAUTO2_TD6060);
5860 CASE_BTC_POLICY_STR(PAUTO2_TD2080);
5861 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4);
5862 default:
5863 return "unknown step";
5864 }
5865 }
5866
5867 static
5868 void seq_print_segment(struct seq_file *m, const char *prefix, u16 *data,
5869 u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
5870 {
5871 u8 i;
5872 u8 cur_index;
5873
5874 for (i = 0; i < len ; i++) {
5875 if ((i % seg_len) == 0)
5876 seq_printf(m, " %-15s : ", prefix);
5877 cur_index = (start_idx + i) % ring_len;
5878 if (i % 3 == 0)
5879 seq_printf(m, "-> %-20s",
5880 steps_to_str(*(data + cur_index)));
5881 else if (i % 3 == 1)
5882 seq_printf(m, "-> %-15s",
5883 steps_to_str(*(data + cur_index)));
5884 else
5885 seq_printf(m, "-> %-13s",
5886 steps_to_str(*(data + cur_index)));
5887 if (i == (len - 1) || (i % seg_len) == (seg_len - 1))
5888 seq_puts(m, "\n");
5889 }
5890 }
5891
5892 static void _show_dm_step(struct rtw89_dev *rtwdev, struct seq_file *m)
5893 {
5894 struct rtw89_btc *btc = &rtwdev->btc;
5895 struct rtw89_btc_dm *dm = &btc->dm;
5896 u8 start_idx;
5897 u8 len;
5898
5899 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos;
5900 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0;
5901
5902 seq_print_segment(m, "[dm_steps]", dm->dm_step.step, len, 6, start_idx,
5903 ARRAY_SIZE(dm->dm_step.step));
5904 }
5905
5906 static void _show_dm_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5907 {
5908 struct rtw89_btc *btc = &rtwdev->btc;
5909 struct rtw89_btc_module *module = &btc->mdinfo;
5910 struct rtw89_btc_dm *dm = &btc->dm;
5911 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5912 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5913
5914 if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
5915 return;
5916
5917 seq_printf(m, "========== [Mechanism Status %s] ==========\n",
5918 (btc->ctrl.manual ? "(Manual)" : "(Auto)"));
5919
5920 seq_printf(m,
5921 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%ld, run_cnt:%d\n",
5922 "[status]",
5923 module->ant.type == BTC_ANT_SHARED ? "shared" : "dedicated",
5924 steps_to_str(dm->run_reason),
5925 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT),
5926 FIELD_GET(GENMASK(7, 0), dm->set_ant_path),
5927 dm->cnt_dm[BTC_DCNT_RUN]);
5928
5929 _show_dm_step(rtwdev, m);
5930
5931 seq_printf(m, " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ",
5932 "[dm_flag]", dm->wl_only, dm->bt_only, btc->ctrl.igno_bt,
5933 dm->freerun, btc->lps, dm->wl_mimo_ps);
5934
5935 seq_printf(m, "leak_ap:%d, fw_offload:%s%s\n", dm->leak_ap,
5936 (BTC_CX_FW_OFFLOAD ? "Y" : "N"),
5937 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
5938 "" : "(Mismatch!!)"));
5939
5940 if (dm->rf_trx_para.wl_tx_power == 0xff)
5941 seq_printf(m,
5942 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ",
5943 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level);
5944
5945 else
5946 seq_printf(m,
5947 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ",
5948 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level,
5949 dm->rf_trx_para.wl_tx_power);
5950
5951 seq_printf(m,
5952 "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n",
5953 dm->rf_trx_para.wl_rx_gain, dm->rf_trx_para.bt_tx_power,
5954 dm->rf_trx_para.bt_rx_gain,
5955 (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx);
5956
5957 seq_printf(m,
5958 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU\n",
5959 "[dm_ctrl]", dm->wl_tx_limit.enable, dm->wl_tx_limit.tx_time,
5960 dm->wl_tx_limit.tx_retry, btc->bt_req_len);
5961 }
5962
5963 static void _show_error(struct rtw89_dev *rtwdev, struct seq_file *m)
5964 {
5965 struct rtw89_btc *btc = &rtwdev->btc;
5966 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
5967 struct rtw89_btc_fbtc_cysta *pcysta = NULL;
5968
5969 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
5970
5971 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 &&
5972 pcysta->except_cnt == 0 &&
5973 !pfwinfo->len_mismch && !pfwinfo->fver_mismch)
5974 return;
5975
5976 seq_printf(m, " %-15s : ", "[error]");
5977
5978 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
5979 seq_printf(m,
5980 "overflow-cnt: %d, ",
5981 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
5982 }
5983
5984 if (pfwinfo->len_mismch) {
5985 seq_printf(m,
5986 "len-mismatch: 0x%x, ",
5987 pfwinfo->len_mismch);
5988 }
5989
5990 if (pfwinfo->fver_mismch) {
5991 seq_printf(m,
5992 "fver-mismatch: 0x%x, ",
5993 pfwinfo->fver_mismch);
5994 }
5995
5996 /* cycle statistics exceptions */
5997 if (pcysta->exception || pcysta->except_cnt) {
5998 seq_printf(m,
5999 "exception-type: 0x%x, exception-cnt = %d",
6000 pcysta->exception, pcysta->except_cnt);
6001 }
6002 seq_puts(m, "\n");
6003 }
6004
6005 static void _show_fbtc_tdma(struct rtw89_dev *rtwdev, struct seq_file *m)
6006 {
6007 struct rtw89_btc *btc = &rtwdev->btc;
6008 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6009 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6010 struct rtw89_btc_fbtc_tdma *t = NULL;
6011 struct rtw89_btc_fbtc_slot *s = NULL;
6012 struct rtw89_btc_dm *dm = &btc->dm;
6013 u8 i, cnt = 0;
6014
6015 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
6016 if (!pcinfo->valid)
6017 return;
6018
6019 t = &pfwinfo->rpt_fbtc_tdma.finfo;
6020
6021 seq_printf(m,
6022 " %-15s : ", "[tdma_policy]");
6023 seq_printf(m,
6024 "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ",
6025 (u32)t->type,
6026 t->rxflctrl, t->txpause);
6027
6028 seq_printf(m,
6029 "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ",
6030 t->wtgle_n, t->leak_n, t->ext_ctrl);
6031
6032 seq_printf(m,
6033 "policy_type:%d",
6034 (u32)btc->policy_type);
6035
6036 s = pfwinfo->rpt_fbtc_slots.finfo.slot;
6037
6038 for (i = 0; i < CXST_MAX; i++) {
6039 if (dm->update_slot_map == BIT(CXST_MAX) - 1)
6040 break;
6041
6042 if (!(dm->update_slot_map & BIT(i)))
6043 continue;
6044
6045 if (cnt % 6 == 0)
6046 seq_printf(m,
6047 " %-15s : %d[%d/0x%x/%d]",
6048 "[slot_policy]",
6049 (u32)i,
6050 s[i].dur, s[i].cxtbl, s[i].cxtype);
6051 else
6052 seq_printf(m,
6053 ", %d[%d/0x%x/%d]",
6054 (u32)i,
6055 s[i].dur, s[i].cxtbl, s[i].cxtype);
6056 if (cnt % 6 == 5)
6057 seq_puts(m, "\n");
6058 cnt++;
6059 }
6060 seq_puts(m, "\n");
6061 }
6062
6063 static void _show_fbtc_slots(struct rtw89_dev *rtwdev, struct seq_file *m)
6064 {
6065 struct rtw89_btc *btc = &rtwdev->btc;
6066 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6067 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6068 struct rtw89_btc_fbtc_slots *pslots = NULL;
6069 struct rtw89_btc_fbtc_slot s;
6070 u8 i = 0;
6071
6072 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
6073 if (!pcinfo->valid)
6074 return;
6075
6076 pslots = &pfwinfo->rpt_fbtc_slots.finfo;
6077
6078 for (i = 0; i < CXST_MAX; i++) {
6079 s = pslots->slot[i];
6080 if (i % 6 == 0)
6081 seq_printf(m,
6082 " %-15s : %02d[%03d/0x%x/%d]",
6083 "[slot_list]",
6084 (u32)i,
6085 s.dur, s.cxtbl, s.cxtype);
6086 else
6087 seq_printf(m,
6088 ", %02d[%03d/0x%x/%d]",
6089 (u32)i,
6090 s.dur, s.cxtbl, s.cxtype);
6091 if (i % 6 == 5)
6092 seq_puts(m, "\n");
6093 }
6094 }
6095
6096 static void _show_fbtc_cysta(struct rtw89_dev *rtwdev, struct seq_file *m)
6097 {
6098 struct rtw89_btc *btc = &rtwdev->btc;
6099 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6100 struct rtw89_btc_dm *dm = &btc->dm;
6101 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
6102 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6103 struct rtw89_btc_fbtc_cysta *pcysta_le32 = NULL;
6104 struct rtw89_btc_fbtc_cysta_cpu pcysta[1];
6105 union rtw89_btc_fbtc_rxflct r;
6106 u8 i, cnt = 0, slot_pair;
6107 u16 cycle, c_begin, c_end, store_index;
6108
6109 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
6110 if (!pcinfo->valid)
6111 return;
6112
6113 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo;
6114 rtw89_btc_fbtc_cysta_to_cpu(pcysta_le32, pcysta);
6115 seq_printf(m,
6116 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
6117 "[cycle_cnt]", pcysta->cycles, pcysta->bcn_cnt[CXBCN_ALL],
6118 pcysta->bcn_cnt[CXBCN_ALL_OK],
6119 pcysta->bcn_cnt[CXBCN_BT_SLOT],
6120 pcysta->bcn_cnt[CXBCN_BT_OK]);
6121
6122 for (i = 0; i < CXST_MAX; i++) {
6123 if (!pcysta->slot_cnt[i])
6124 continue;
6125 seq_printf(m,
6126 ", %d:%d", (u32)i, pcysta->slot_cnt[i]);
6127 }
6128
6129 if (dm->tdma_now.rxflctrl) {
6130 seq_printf(m,
6131 ", leak_rx:%d", pcysta->leakrx_cnt);
6132 }
6133
6134 if (pcysta->collision_cnt) {
6135 seq_printf(m,
6136 ", collision:%d", pcysta->collision_cnt);
6137 }
6138
6139 if (pcysta->skip_cnt) {
6140 seq_printf(m,
6141 ", skip:%d", pcysta->skip_cnt);
6142 }
6143 seq_puts(m, "\n");
6144
6145 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
6146 "[cycle_time]",
6147 pcysta->tavg_cycle[CXT_WL],
6148 pcysta->tavg_cycle[CXT_BT],
6149 pcysta->tavg_lk / 1000, pcysta->tavg_lk % 1000);
6150 seq_printf(m,
6151 ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
6152 pcysta->tmax_cycle[CXT_WL],
6153 pcysta->tmax_cycle[CXT_BT],
6154 pcysta->tmax_lk / 1000, pcysta->tmax_lk % 1000);
6155 seq_printf(m,
6156 ", maxdiff_t[wl:%d/bt:%d]\n",
6157 pcysta->tmaxdiff_cycle[CXT_WL],
6158 pcysta->tmaxdiff_cycle[CXT_BT]);
6159
6160 if (pcysta->cycles == 0)
6161 return;
6162
6163 /* 1 cycle record 1 wl-slot and 1 bt-slot */
6164 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
6165
6166 if (pcysta->cycles <= slot_pair)
6167 c_begin = 1;
6168 else
6169 c_begin = pcysta->cycles - slot_pair + 1;
6170
6171 c_end = pcysta->cycles;
6172
6173 for (cycle = c_begin; cycle <= c_end; cycle++) {
6174 cnt++;
6175 store_index = ((cycle - 1) % slot_pair) * 2;
6176
6177 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1)
6178 seq_printf(m,
6179 " %-15s : ->b%02d->w%02d", "[cycle_step]",
6180 pcysta->tslot_cycle[store_index],
6181 pcysta->tslot_cycle[store_index + 1]);
6182 else
6183 seq_printf(m,
6184 "->b%02d->w%02d",
6185 pcysta->tslot_cycle[store_index],
6186 pcysta->tslot_cycle[store_index + 1]);
6187 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
6188 seq_puts(m, "\n");
6189 }
6190
6191 if (a2dp->exist) {
6192 seq_printf(m,
6193 " %-15s : a2dp_ept:%d, a2dp_late:%d",
6194 "[a2dp_t_sta]",
6195 pcysta->a2dpept, pcysta->a2dpeptto);
6196
6197 seq_printf(m,
6198 ", avg_t:%d, max_t:%d",
6199 pcysta->tavg_a2dpept, pcysta->tmax_a2dpept);
6200 r.val = dm->tdma_now.rxflctrl;
6201
6202 if (r.type && r.tgln_n) {
6203 seq_printf(m,
6204 ", cycle[PSTDMA:%d/TDMA:%d], ",
6205 pcysta->cycles_a2dp[CXT_FLCTRL_ON],
6206 pcysta->cycles_a2dp[CXT_FLCTRL_OFF]);
6207
6208 seq_printf(m,
6209 "avg_t[PSTDMA:%d/TDMA:%d], ",
6210 pcysta->tavg_a2dp[CXT_FLCTRL_ON],
6211 pcysta->tavg_a2dp[CXT_FLCTRL_OFF]);
6212
6213 seq_printf(m,
6214 "max_t[PSTDMA:%d/TDMA:%d]",
6215 pcysta->tmax_a2dp[CXT_FLCTRL_ON],
6216 pcysta->tmax_a2dp[CXT_FLCTRL_OFF]);
6217 }
6218 seq_puts(m, "\n");
6219 }
6220 }
6221
6222 static void _show_fbtc_nullsta(struct rtw89_dev *rtwdev, struct seq_file *m)
6223 {
6224 struct rtw89_btc *btc = &rtwdev->btc;
6225 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6226 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6227 struct rtw89_btc_fbtc_cynullsta *ns = NULL;
6228 u8 i = 0;
6229
6230 if (!btc->dm.tdma_now.rxflctrl)
6231 return;
6232
6233 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
6234 if (!pcinfo->valid)
6235 return;
6236
6237 ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
6238
6239 seq_printf(m, " %-15s : ", "[null_sta]");
6240
6241 for (i = 0; i < 2; i++) {
6242 if (i != 0)
6243 seq_printf(m, ", null-%d", i);
6244 else
6245 seq_printf(m, "null-%d", i);
6246 seq_printf(m, "[ok:%d/", le32_to_cpu(ns->result[i][1]));
6247 seq_printf(m, "fail:%d/", le32_to_cpu(ns->result[i][0]));
6248 seq_printf(m, "on_time:%d/", le32_to_cpu(ns->result[i][2]));
6249 seq_printf(m, "retry:%d/", le32_to_cpu(ns->result[i][3]));
6250 seq_printf(m, "avg_t:%d.%03d/",
6251 le32_to_cpu(ns->avg_t[i]) / 1000,
6252 le32_to_cpu(ns->avg_t[i]) % 1000);
6253 seq_printf(m, "max_t:%d.%03d]",
6254 le32_to_cpu(ns->max_t[i]) / 1000,
6255 le32_to_cpu(ns->max_t[i]) % 1000);
6256 }
6257 seq_puts(m, "\n");
6258 }
6259
6260 static void _show_fbtc_step(struct rtw89_dev *rtwdev, struct seq_file *m)
6261 {
6262 struct rtw89_btc *btc = &rtwdev->btc;
6263 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6264 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6265 struct rtw89_btc_fbtc_steps *pstep = NULL;
6266 u8 type, val, cnt = 0, state = 0;
6267 bool outloop = false;
6268 u16 i, diff_t, n_start = 0, n_stop = 0;
6269 u16 pos_old, pos_new;
6270
6271 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
6272 if (!pcinfo->valid)
6273 return;
6274
6275 pstep = &pfwinfo->rpt_fbtc_step.finfo;
6276 pos_old = le16_to_cpu(pstep->pos_old);
6277 pos_new = le16_to_cpu(pstep->pos_new);
6278
6279 if (pcinfo->req_fver != pstep->fver)
6280 return;
6281
6282 /* store step info by using ring instead of FIFO*/
6283 do {
6284 switch (state) {
6285 case 0:
6286 n_start = pos_old;
6287 if (pos_new >= pos_old)
6288 n_stop = pos_new;
6289 else
6290 n_stop = btc->ctrl.trace_step - 1;
6291
6292 state = 1;
6293 break;
6294 case 1:
6295 for (i = n_start; i <= n_stop; i++) {
6296 type = pstep->step[i].type;
6297 val = pstep->step[i].val;
6298 diff_t = le16_to_cpu(pstep->step[i].difft);
6299
6300 if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
6301 continue;
6302
6303 if (cnt % 10 == 0)
6304 seq_printf(m, " %-15s : ", "[steps]");
6305
6306 seq_printf(m, "-> %s(%02d)(%02d)",
6307 (type == CXSTEP_SLOT ? "SLT" :
6308 "EVT"), (u32)val, diff_t);
6309 if (cnt % 10 == 9)
6310 seq_puts(m, "\n");
6311 cnt++;
6312 }
6313
6314 state = 2;
6315 break;
6316 case 2:
6317 if (pos_new < pos_old && n_start != 0) {
6318 n_start = 0;
6319 n_stop = pos_new;
6320 state = 1;
6321 } else {
6322 outloop = true;
6323 }
6324 break;
6325 }
6326 } while (!outloop);
6327 }
6328
6329 static void _show_fw_dm_msg(struct rtw89_dev *rtwdev, struct seq_file *m)
6330 {
6331 struct rtw89_btc *btc = &rtwdev->btc;
6332
6333 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
6334 return;
6335
6336 _show_error(rtwdev, m);
6337 _show_fbtc_tdma(rtwdev, m);
6338 _show_fbtc_slots(rtwdev, m);
6339 _show_fbtc_cysta(rtwdev, m);
6340 _show_fbtc_nullsta(rtwdev, m);
6341 _show_fbtc_step(rtwdev, m);
6342 }
6343
6344 static void _show_mreg(struct rtw89_dev *rtwdev, struct seq_file *m)
6345 {
6346 const struct rtw89_chip_info *chip = rtwdev->chip;
6347 struct rtw89_btc *btc = &rtwdev->btc;
6348 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6349 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6350 struct rtw89_btc_fbtc_mreg_val *pmreg = NULL;
6351 struct rtw89_btc_fbtc_gpio_dbg *gdbg = NULL;
6352 struct rtw89_btc_cx *cx = &btc->cx;
6353 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6354 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
6355 struct rtw89_mac_ax_gnt gnt[2] = {0};
6356 u8 i = 0, type = 0, cnt = 0;
6357 u32 val, offset;
6358
6359 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
6360 return;
6361
6362 seq_puts(m, "========== [HW Status] ==========\n");
6363
6364 seq_printf(m,
6365 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
6366 "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
6367 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
6368 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
6369
6370 /* To avoid I/O if WL LPS or power-off */
6371 if (!wl->status.map.lps && !wl->status.map.rf_off) {
6372 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
6373 if (val & (B_AX_GNT_BT_RFC_S0_SW_VAL |
6374 B_AX_GNT_BT_BB_S0_SW_VAL))
6375 gnt[0].gnt_bt = true;
6376 if (val & (B_AX_GNT_BT_RFC_S0_SW_CTRL |
6377 B_AX_GNT_BT_BB_S0_SW_CTRL))
6378 gnt[0].gnt_bt_sw_en = true;
6379 if (val & (B_AX_GNT_WL_RFC_S0_SW_VAL |
6380 B_AX_GNT_WL_BB_S0_SW_VAL))
6381 gnt[0].gnt_wl = true;
6382 if (val & (B_AX_GNT_WL_RFC_S0_SW_CTRL |
6383 B_AX_GNT_WL_BB_S0_SW_CTRL))
6384 gnt[0].gnt_wl_sw_en = true;
6385
6386 if (val & (B_AX_GNT_BT_RFC_S1_SW_VAL |
6387 B_AX_GNT_BT_BB_S1_SW_VAL))
6388 gnt[1].gnt_bt = true;
6389 if (val & (B_AX_GNT_BT_RFC_S1_SW_CTRL |
6390 B_AX_GNT_BT_BB_S1_SW_CTRL))
6391 gnt[1].gnt_bt_sw_en = true;
6392 if (val & (B_AX_GNT_WL_RFC_S1_SW_VAL |
6393 B_AX_GNT_WL_BB_S1_SW_VAL))
6394 gnt[1].gnt_wl = true;
6395 if (val & (B_AX_GNT_WL_RFC_S1_SW_CTRL |
6396 B_AX_GNT_WL_BB_S1_SW_CTRL))
6397 gnt[1].gnt_wl_sw_en = true;
6398
6399 seq_printf(m,
6400 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
6401 "[gnt_status]",
6402 (rtw89_mac_get_ctrl_path(rtwdev) ? "WL" : "BT"),
6403 (gnt[0].gnt_wl_sw_en ? "SW" : "HW"), gnt[0].gnt_wl,
6404 (gnt[0].gnt_bt_sw_en ? "SW" : "HW"), gnt[0].gnt_bt);
6405
6406 seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
6407 (gnt[1].gnt_wl_sw_en ? "SW" : "HW"), gnt[1].gnt_wl,
6408 (gnt[1].gnt_bt_sw_en ? "SW" : "HW"), gnt[1].gnt_bt);
6409 }
6410
6411 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
6412 if (!pcinfo->valid) {
6413 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6414 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
6415 __func__);
6416 return;
6417 }
6418
6419 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo;
6420 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6421 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
6422 __func__, pmreg->reg_num);
6423
6424 for (i = 0; i < pmreg->reg_num; i++) {
6425 type = (u8)le16_to_cpu(chip->mon_reg[i].type);
6426 offset = le32_to_cpu(chip->mon_reg[i].offset);
6427 val = le32_to_cpu(pmreg->mreg_val[i]);
6428
6429 if (cnt % 6 == 0)
6430 seq_printf(m, " %-15s : %d_0x%04x=0x%08x",
6431 "[reg]", (u32)type, offset, val);
6432 else
6433 seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type,
6434 offset, val);
6435 if (cnt % 6 == 5)
6436 seq_puts(m, "\n");
6437 cnt++;
6438 }
6439
6440 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
6441 if (!pcinfo->valid) {
6442 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6443 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n",
6444 __func__);
6445 return;
6446 }
6447
6448 gdbg = &pfwinfo->rpt_fbtc_gpio_dbg.finfo;
6449 if (!gdbg->en_map)
6450 return;
6451
6452 seq_printf(m, " %-15s : enable_map:0x%08x",
6453 "[gpio_dbg]", gdbg->en_map);
6454
6455 for (i = 0; i < BTC_DBG_MAX1; i++) {
6456 if (!(gdbg->en_map & BIT(i)))
6457 continue;
6458 seq_printf(m, ", %d->GPIO%d", (u32)i, gdbg->gpio_map[i]);
6459 }
6460 seq_puts(m, "\n");
6461 }
6462
6463 static void _show_summary(struct rtw89_dev *rtwdev, struct seq_file *m)
6464 {
6465 struct rtw89_btc *btc = &rtwdev->btc;
6466 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6467 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6468 struct rtw89_btc_fbtc_rpt_ctrl *prptctrl = NULL;
6469 struct rtw89_btc_cx *cx = &btc->cx;
6470 struct rtw89_btc_dm *dm = &btc->dm;
6471 struct rtw89_btc_wl_info *wl = &cx->wl;
6472 struct rtw89_btc_bt_info *bt = &cx->bt;
6473 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
6474 u8 i;
6475
6476 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
6477 return;
6478
6479 seq_puts(m, "========== [Statistics] ==========\n");
6480
6481 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
6482 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
6483 prptctrl = &pfwinfo->rpt_ctrl.finfo;
6484
6485 seq_printf(m,
6486 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
6487 "[summary]", pfwinfo->cnt_h2c,
6488 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt,
6489 pfwinfo->cnt_c2h, prptctrl->c2h_cnt);
6490
6491 seq_printf(m,
6492 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
6493 pfwinfo->event[BTF_EVNT_RPT], prptctrl->rpt_cnt,
6494 prptctrl->rpt_enable, dm->error.val);
6495
6496 if (dm->error.map.wl_fw_hang)
6497 seq_puts(m, " (WL FW Hang!!)");
6498 seq_puts(m, "\n");
6499 seq_printf(m,
6500 " %-15s : send_ok:%d, send_fail:%d, recv:%d",
6501 "[mailbox]", prptctrl->mb_send_ok_cnt,
6502 prptctrl->mb_send_fail_cnt, prptctrl->mb_recv_cnt);
6503
6504 seq_printf(m,
6505 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n",
6506 prptctrl->mb_a2dp_empty_cnt,
6507 prptctrl->mb_a2dp_flct_cnt,
6508 prptctrl->mb_a2dp_full_cnt);
6509
6510 seq_printf(m,
6511 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
6512 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
6513 cx->cnt_wl[BTC_WCNT_RFK_GO],
6514 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
6515 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
6516
6517 seq_printf(m,
6518 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
6519 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
6520 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
6521 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
6522 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
6523 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
6524
6525 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
6526 bt->rfk_info.map.timeout = 1;
6527 else
6528 bt->rfk_info.map.timeout = 0;
6529
6530 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
6531 } else {
6532 seq_printf(m,
6533 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
6534 "[summary]", pfwinfo->cnt_h2c,
6535 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
6536 pfwinfo->event[BTF_EVNT_RPT],
6537 btc->fwinfo.rpt_en_map);
6538 seq_puts(m, " (WL FW report invalid!!)\n");
6539 }
6540
6541 for (i = 0; i < BTC_NCNT_NUM; i++)
6542 cnt_sum += dm->cnt_notify[i];
6543
6544 seq_printf(m,
6545 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
6546 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
6547 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
6548
6549 seq_printf(m,
6550 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
6551 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
6552 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
6553 cnt[BTC_NCNT_WL_STA]);
6554
6555 seq_printf(m,
6556 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
6557 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
6558 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
6559 cnt[BTC_NCNT_SPECIAL_PACKET]);
6560
6561 seq_printf(m,
6562 "timer=%d, control=%d, customerize=%d\n",
6563 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
6564 cnt[BTC_NCNT_CUSTOMERIZE]);
6565 }
6566
6567 void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m)
6568 {
6569 struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal;
6570 struct rtw89_btc *btc = &rtwdev->btc;
6571 struct rtw89_btc_cx *cx = &btc->cx;
6572 struct rtw89_btc_bt_info *bt = &cx->bt;
6573
6574 seq_puts(m, "=========================================\n");
6575 seq_printf(m, "WL FW / BT FW %d.%d.%d.%d / NA\n",
6576 fw_suit->major_ver, fw_suit->minor_ver,
6577 fw_suit->sub_ver, fw_suit->sub_idex);
6578 seq_printf(m, "manual %d\n", btc->ctrl.manual);
6579
6580 seq_puts(m, "=========================================\n");
6581
6582 seq_printf(m, "\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)",
6583 "[bt_info]",
6584 bt->raw_info[2], bt->raw_info[3],
6585 bt->raw_info[4], bt->raw_info[5],
6586 bt->raw_info[6], bt->raw_info[7],
6587 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
6588 cx->cnt_bt[BTC_BCNT_INFOUPDATE],
6589 cx->cnt_bt[BTC_BCNT_INFOSAME]);
6590
6591 seq_puts(m, "\n=========================================\n");
6592
6593 _show_cx_info(rtwdev, m);
6594 _show_wl_info(rtwdev, m);
6595 _show_bt_info(rtwdev, m);
6596 _show_dm_info(rtwdev, m);
6597 _show_fw_dm_msg(rtwdev, m);
6598 _show_mreg(rtwdev, m);
6599 _show_summary(rtwdev, m);
6600 }
Cache object: bafaa4522fc3eeee1ff25debe91e4ed5
|