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
_send_fw_cmd(struct rtw89_dev * rtwdev,u8 h2c_class,u8 h2c_func,void * param,u16 len)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
_reset_btc_var(struct rtw89_dev * rtwdev,u8 type)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
_chk_btc_err(struct rtw89_dev * rtwdev,u8 type,u32 cnt)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
_update_bt_report(struct rtw89_dev * rtwdev,u8 rpt_type,u8 * pfinfo)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
rtw89_btc_fbtc_cysta_to_cpu(const struct rtw89_btc_fbtc_cysta * src,struct rtw89_btc_fbtc_cysta_cpu * dst)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
_chk_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * prptbuf,u32 index)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
_parse_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * pbuf,u32 buf_len)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
_append_tdma(struct rtw89_dev * rtwdev)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
_append_slot(struct rtw89_dev * rtwdev)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
rtw89_btc_fw_en_rpt(struct rtw89_dev * rtwdev,u32 rpt_map,bool rpt_state)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
rtw89_btc_fw_set_slots(struct rtw89_dev * rtwdev,u8 num,struct rtw89_btc_fbtc_slot * s)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
btc_fw_set_monreg(struct rtw89_dev * rtwdev)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
_update_dm_step(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason_or_action)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
_fw_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)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
_fw_set_drv_info(struct rtw89_dev * rtwdev,u8 type)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
btc_fw_event(struct rtw89_dev * rtwdev,u8 evt_id,void * data,u32 len)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
_set_gnt_wl(struct rtw89_dev * rtwdev,u8 phy_map,u8 state)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
_set_bt_ignore_wlan_act(struct rtw89_dev * rtwdev,u8 enable)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
_set_wl_tx_power(struct rtw89_dev * rtwdev,u32 level)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
_set_wl_rx_gain(struct rtw89_dev * rtwdev,u32 level)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
_set_bt_tx_power(struct rtw89_dev * rtwdev,u8 level)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
_set_bt_rx_gain(struct rtw89_dev * rtwdev,u8 level)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
_set_rf_trx_para(struct rtw89_dev * rtwdev)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
_update_btc_state_map(struct rtw89_dev * rtwdev)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
_set_bt_afh_info(struct rtw89_dev * rtwdev)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
_check_freerun(struct rtw89_dev * rtwdev)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
_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)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 */
rtw89_btc_set_policy(struct rtw89_dev * rtwdev,u16 policy_type)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
rtw89_btc_set_policy_v1(struct rtw89_dev * rtwdev,u16 policy_type)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
_set_gnt_bt(struct rtw89_dev * rtwdev,u8 phy_map,u8 state)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
_set_bt_plut(struct rtw89_dev * rtwdev,u8 phy_map,u8 tx_val,u8 rx_val)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
_set_ant(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)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
_action_wl_only(struct rtw89_dev * rtwdev)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
_action_wl_init(struct rtw89_dev * rtwdev)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
_action_wl_off(struct rtw89_dev * rtwdev)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
_action_freerun(struct rtw89_dev * rtwdev)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
_action_bt_whql(struct rtw89_dev * rtwdev)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
_action_bt_off(struct rtw89_dev * rtwdev)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
_action_bt_idle(struct rtw89_dev * rtwdev)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
_action_bt_hfp(struct rtw89_dev * rtwdev)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
_action_bt_hid(struct rtw89_dev * rtwdev)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
_action_bt_a2dp(struct rtw89_dev * rtwdev)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
_action_bt_a2dpsink(struct rtw89_dev * rtwdev)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
_action_bt_pan(struct rtw89_dev * rtwdev)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
_action_bt_a2dp_hid(struct rtw89_dev * rtwdev)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
_action_bt_a2dp_pan(struct rtw89_dev * rtwdev)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
_action_bt_pan_hid(struct rtw89_dev * rtwdev)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
_action_bt_a2dp_pan_hid(struct rtw89_dev * rtwdev)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
_action_wl_5g(struct rtw89_dev * rtwdev)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
_action_wl_other(struct rtw89_dev * rtwdev)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
_action_wl_nc(struct rtw89_dev * rtwdev)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
_action_wl_rfk(struct rtw89_dev * rtwdev)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
_set_btg_ctrl(struct rtw89_dev * rtwdev)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
rtw89_tx_time_iter(void * data,struct ieee80211_sta * sta)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
_set_wl_tx_limit(struct rtw89_dev * rtwdev)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
_set_bt_rx_agc(struct rtw89_dev * rtwdev)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 */
_action_common(struct rtw89_dev * rtwdev)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
_action_by_bt(struct rtw89_dev * rtwdev)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
_action_wl_2g_sta(struct rtw89_dev * rtwdev)3662 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev)
3663 {
3664 _action_by_bt(rtwdev);
3665 }
3666
_action_wl_scan(struct rtw89_dev * rtwdev)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
_action_wl_25g_mcc(struct rtw89_dev * rtwdev)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
_action_wl_2g_mcc(struct rtw89_dev * rtwdev)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
_action_wl_2g_scc(struct rtw89_dev * rtwdev)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
_action_wl_2g_scc_v1(struct rtw89_dev * rtwdev)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
_action_wl_2g_ap(struct rtw89_dev * rtwdev)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
_action_wl_2g_go(struct rtw89_dev * rtwdev)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
_action_wl_2g_gc(struct rtw89_dev * rtwdev)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
_action_wl_2g_nan(struct rtw89_dev * rtwdev)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
_read_scbd(struct rtw89_dev * rtwdev)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
_write_scbd(struct rtw89_dev * rtwdev,u32 val,bool state)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
_update_rssi_state(struct rtw89_dev * rtwdev,u8 pre_state,u8 rssi,u8 thresh)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
_update_dbcc_band(struct rtw89_dev * rtwdev,enum rtw89_phy_idx phy_idx)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
_update_wl_info(struct rtw89_dev * rtwdev)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 #if defined(__linux__)
4096 "[BTC], cnt_connect = %d, link_mode = %d\n",
4097 cnt_connect, wl_rinfo->link_mode);
4098 #elif defined(__FreeBSD__)
4099 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
4100 cnt_connect, cnt_connecting, wl_rinfo->link_mode);
4101 #endif
4102
4103 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
4104 }
4105
_update_wl_info_v1(struct rtw89_dev * rtwdev)4106 static void _update_wl_info_v1(struct rtw89_dev *rtwdev)
4107 {
4108 struct rtw89_btc *btc = &rtwdev->btc;
4109 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4110 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
4111 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
4112 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4113 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
4114 u8 cnt_2g = 0, cnt_5g = 0, phy;
4115 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
4116 bool b2g = false, b5g = false, client_joined = false;
4117 u8 i;
4118
4119 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
4120
4121 for (i = 0; i < RTW89_PORT_NUM; i++) {
4122 if (!wl_linfo[i].active)
4123 continue;
4124
4125 cnt_active++;
4126 wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role;
4127 wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid;
4128 wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy;
4129 wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band;
4130 wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
4131 wl_rinfo->active_role_v1[cnt_active - 1].connected = 0;
4132
4133 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
4134
4135 phy = wl_linfo[i].phy;
4136
4137 if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
4138 wl_dinfo->role[phy] = wl_linfo[i].role;
4139 wl_dinfo->op_band[phy] = wl_linfo[i].band;
4140 _update_dbcc_band(rtwdev, phy);
4141 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
4142 }
4143
4144 if (wl_linfo[i].connected == MLME_NO_LINK) {
4145 continue;
4146 } else if (wl_linfo[i].connected == MLME_LINKING) {
4147 cnt_connecting++;
4148 } else {
4149 cnt_connect++;
4150 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
4151 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
4152 wl_linfo[i].client_cnt > 1)
4153 client_joined = true;
4154 }
4155
4156 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
4157 wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch;
4158 wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw;
4159 wl_rinfo->active_role_v1[cnt_active - 1].connected = 1;
4160
4161 /* only care 2 roles + BT coex */
4162 if (wl_linfo[i].band != RTW89_BAND_2G) {
4163 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
4164 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
4165 cnt_5g++;
4166 b5g = true;
4167 } else {
4168 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
4169 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
4170 cnt_2g++;
4171 b2g = true;
4172 }
4173 }
4174
4175 wl_rinfo->connect_cnt = cnt_connect;
4176
4177 /* Be careful to change the following sequence!! */
4178 if (cnt_connect == 0) {
4179 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
4180 wl_rinfo->role_map.role.none = 1;
4181 } else if (!b2g && b5g) {
4182 wl_rinfo->link_mode = BTC_WLINK_5G;
4183 } else if (wl_rinfo->role_map.role.nan) {
4184 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
4185 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
4186 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4187 } else if (b2g && b5g && cnt_connect == 2) {
4188 if (rtwdev->dbcc_en) {
4189 switch (wl_dinfo->role[RTW89_PHY_0]) {
4190 case RTW89_WIFI_ROLE_STATION:
4191 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4192 break;
4193 case RTW89_WIFI_ROLE_P2P_GO:
4194 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
4195 break;
4196 case RTW89_WIFI_ROLE_P2P_CLIENT:
4197 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
4198 break;
4199 case RTW89_WIFI_ROLE_AP:
4200 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
4201 break;
4202 default:
4203 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4204 break;
4205 }
4206 } else {
4207 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
4208 }
4209 } else if (!b5g && cnt_connect == 2) {
4210 if (wl_rinfo->role_map.role.station &&
4211 (wl_rinfo->role_map.role.p2p_go ||
4212 wl_rinfo->role_map.role.p2p_gc ||
4213 wl_rinfo->role_map.role.ap)) {
4214 if (wl_2g_ch[0] == wl_2g_ch[1])
4215 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
4216 else
4217 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
4218 } else {
4219 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
4220 }
4221 } else if (!b5g && cnt_connect == 1) {
4222 if (wl_rinfo->role_map.role.station)
4223 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4224 else if (wl_rinfo->role_map.role.ap)
4225 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
4226 else if (wl_rinfo->role_map.role.p2p_go)
4227 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
4228 else if (wl_rinfo->role_map.role.p2p_gc)
4229 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
4230 else
4231 wl_rinfo->link_mode = BTC_WLINK_OTHER;
4232 }
4233
4234 /* if no client_joined, don't care P2P-GO/AP role */
4235 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
4236 if (!client_joined) {
4237 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
4238 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
4239 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
4240 wl_rinfo->connect_cnt = 1;
4241 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
4242 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
4243 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
4244 wl_rinfo->connect_cnt = 0;
4245 }
4246 }
4247 }
4248
4249 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4250 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
4251 cnt_connect, cnt_connecting, wl_rinfo->link_mode);
4252
4253 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
4254 }
4255
4256 #define BTC_CHK_HANG_MAX 3
4257 #define BTC_SCB_INV_VALUE GENMASK(31, 0)
4258
rtw89_coex_act1_work(struct work_struct * work)4259 void rtw89_coex_act1_work(struct work_struct *work)
4260 {
4261 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4262 coex_act1_work.work);
4263 struct rtw89_btc *btc = &rtwdev->btc;
4264 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4265 struct rtw89_btc_cx *cx = &btc->cx;
4266 struct rtw89_btc_wl_info *wl = &cx->wl;
4267
4268 mutex_lock(&rtwdev->mutex);
4269 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
4270 dm->cnt_notify[BTC_NCNT_TIMER]++;
4271 if (wl->status.map._4way)
4272 wl->status.map._4way = false;
4273 if (wl->status.map.connecting)
4274 wl->status.map.connecting = false;
4275
4276 _run_coex(rtwdev, BTC_RSN_ACT1_WORK);
4277 mutex_unlock(&rtwdev->mutex);
4278 }
4279
rtw89_coex_bt_devinfo_work(struct work_struct * work)4280 void rtw89_coex_bt_devinfo_work(struct work_struct *work)
4281 {
4282 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4283 coex_bt_devinfo_work.work);
4284 struct rtw89_btc *btc = &rtwdev->btc;
4285 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4286 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
4287
4288 mutex_lock(&rtwdev->mutex);
4289 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
4290 dm->cnt_notify[BTC_NCNT_TIMER]++;
4291 a2dp->play_latency = 0;
4292 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK);
4293 mutex_unlock(&rtwdev->mutex);
4294 }
4295
rtw89_coex_rfk_chk_work(struct work_struct * work)4296 void rtw89_coex_rfk_chk_work(struct work_struct *work)
4297 {
4298 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4299 coex_rfk_chk_work.work);
4300 struct rtw89_btc *btc = &rtwdev->btc;
4301 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4302 struct rtw89_btc_cx *cx = &btc->cx;
4303 struct rtw89_btc_wl_info *wl = &cx->wl;
4304
4305 mutex_lock(&rtwdev->mutex);
4306 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
4307 dm->cnt_notify[BTC_NCNT_TIMER]++;
4308 if (wl->rfk_info.state != BTC_WRFK_STOP) {
4309 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4310 "[BTC], %s(): RFK timeout\n", __func__);
4311 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++;
4312 dm->error.map.wl_rfk_timeout = true;
4313 wl->rfk_info.state = BTC_WRFK_STOP;
4314 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
4315 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK);
4316 }
4317 mutex_unlock(&rtwdev->mutex);
4318 }
4319
_update_bt_scbd(struct rtw89_dev * rtwdev,bool only_update)4320 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update)
4321 {
4322 const struct rtw89_chip_info *chip = rtwdev->chip;
4323 struct rtw89_btc *btc = &rtwdev->btc;
4324 struct rtw89_btc_cx *cx = &btc->cx;
4325 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4326 u32 val;
4327 bool status_change = false;
4328
4329 if (!chip->scbd)
4330 return;
4331
4332 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
4333
4334 val = _read_scbd(rtwdev);
4335 if (val == BTC_SCB_INV_VALUE) {
4336 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4337 "[BTC], %s(): return by invalid scbd value\n",
4338 __func__);
4339 return;
4340 }
4341
4342 if (!(val & BTC_BSCB_ON) ||
4343 btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] >= BTC_CHK_HANG_MAX)
4344 bt->enable.now = 0;
4345 else
4346 bt->enable.now = 1;
4347
4348 if (bt->enable.now != bt->enable.last)
4349 status_change = true;
4350
4351 /* reset bt info if bt re-enable */
4352 if (bt->enable.now && !bt->enable.last) {
4353 _reset_btc_var(rtwdev, BTC_RESET_BTINFO);
4354 cx->cnt_bt[BTC_BCNT_REENABLE]++;
4355 bt->enable.now = 1;
4356 }
4357
4358 bt->enable.last = bt->enable.now;
4359 bt->scbd = val;
4360 bt->mbx_avl = !!(val & BTC_BSCB_ACT);
4361
4362 if (bt->whql_test != !!(val & BTC_BSCB_WHQL))
4363 status_change = true;
4364
4365 bt->whql_test = !!(val & BTC_BSCB_WHQL);
4366 bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE;
4367 bt->link_info.a2dp_desc.active = !!(val & BTC_BSCB_A2DP_ACT);
4368
4369 /* if rfk run 1->0 */
4370 if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN))
4371 status_change = true;
4372
4373 bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN);
4374 bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ);
4375 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
4376 bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT);
4377 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
4378
4379 if (!only_update && status_change)
4380 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
4381 }
4382
_chk_wl_rfk_request(struct rtw89_dev * rtwdev)4383 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev)
4384 {
4385 struct rtw89_btc *btc = &rtwdev->btc;
4386 struct rtw89_btc_cx *cx = &btc->cx;
4387 struct rtw89_btc_bt_info *bt = &cx->bt;
4388
4389 _update_bt_scbd(rtwdev, true);
4390
4391 cx->cnt_wl[BTC_WCNT_RFK_REQ]++;
4392
4393 if ((bt->rfk_info.map.run || bt->rfk_info.map.req) &&
4394 !bt->rfk_info.map.timeout) {
4395 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++;
4396 } else {
4397 cx->cnt_wl[BTC_WCNT_RFK_GO]++;
4398 return true;
4399 }
4400 return false;
4401 }
4402
4403 static
_run_coex(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason)4404 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
4405 {
4406 const struct rtw89_chip_info *chip = rtwdev->chip;
4407 struct rtw89_btc *btc = &rtwdev->btc;
4408 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4409 struct rtw89_btc_cx *cx = &btc->cx;
4410 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4411 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
4412 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
4413 u8 mode;
4414
4415 lockdep_assert_held(&rtwdev->mutex);
4416
4417 dm->run_reason = reason;
4418 _update_dm_step(rtwdev, reason);
4419 _update_btc_state_map(rtwdev);
4420
4421 if (chip->chip_id == RTL8852A)
4422 mode = wl_rinfo->link_mode;
4423 else
4424 mode = wl_rinfo_v1->link_mode;
4425
4426 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
4427 __func__, reason, mode);
4428 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
4429 __func__, dm->wl_only, dm->bt_only);
4430
4431 /* Be careful to change the following function sequence!! */
4432 if (btc->ctrl.manual) {
4433 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4434 "[BTC], %s(): return for Manual CTRL!!\n",
4435 __func__);
4436 return;
4437 }
4438
4439 if (btc->ctrl.igno_bt &&
4440 (reason == BTC_RSN_UPDATE_BT_INFO ||
4441 reason == BTC_RSN_UPDATE_BT_SCBD)) {
4442 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4443 "[BTC], %s(): return for Stop Coex DM!!\n",
4444 __func__);
4445 return;
4446 }
4447
4448 if (!wl->status.map.init_ok) {
4449 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4450 "[BTC], %s(): return for WL init fail!!\n",
4451 __func__);
4452 return;
4453 }
4454
4455 if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
4456 wl->status.map.lps_pre == wl->status.map.lps &&
4457 (reason == BTC_RSN_NTFY_POWEROFF ||
4458 reason == BTC_RSN_NTFY_RADIO_STATE)) {
4459 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4460 "[BTC], %s(): return for WL rf off state no change!!\n",
4461 __func__);
4462 return;
4463 }
4464
4465 dm->cnt_dm[BTC_DCNT_RUN]++;
4466
4467 if (btc->ctrl.always_freerun) {
4468 _action_freerun(rtwdev);
4469 btc->ctrl.igno_bt = true;
4470 goto exit;
4471 }
4472
4473 if (dm->wl_only) {
4474 _action_wl_only(rtwdev);
4475 btc->ctrl.igno_bt = true;
4476 goto exit;
4477 }
4478
4479 if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) {
4480 _action_wl_off(rtwdev);
4481 btc->ctrl.igno_bt = true;
4482 goto exit;
4483 }
4484
4485 btc->ctrl.igno_bt = false;
4486 dm->freerun = false;
4487
4488 if (reason == BTC_RSN_NTFY_INIT) {
4489 _action_wl_init(rtwdev);
4490 goto exit;
4491 }
4492
4493 if (!cx->bt.enable.now && !cx->other.type) {
4494 _action_bt_off(rtwdev);
4495 goto exit;
4496 }
4497
4498 if (cx->bt.whql_test) {
4499 _action_bt_whql(rtwdev);
4500 goto exit;
4501 }
4502
4503 if (wl->rfk_info.state != BTC_WRFK_STOP) {
4504 _action_wl_rfk(rtwdev);
4505 goto exit;
4506 }
4507
4508 if (cx->state_map == BTC_WLINKING) {
4509 if (mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_2G_STA ||
4510 mode == BTC_WLINK_5G) {
4511 _action_wl_scan(rtwdev);
4512 goto exit;
4513 }
4514 }
4515
4516 if (wl->status.map.scan) {
4517 _action_wl_scan(rtwdev);
4518 goto exit;
4519 }
4520
4521 switch (mode) {
4522 case BTC_WLINK_NOLINK:
4523 _action_wl_nc(rtwdev);
4524 break;
4525 case BTC_WLINK_2G_STA:
4526 _action_wl_2g_sta(rtwdev);
4527 break;
4528 case BTC_WLINK_2G_AP:
4529 _action_wl_2g_ap(rtwdev);
4530 break;
4531 case BTC_WLINK_2G_GO:
4532 _action_wl_2g_go(rtwdev);
4533 break;
4534 case BTC_WLINK_2G_GC:
4535 _action_wl_2g_gc(rtwdev);
4536 break;
4537 case BTC_WLINK_2G_SCC:
4538 if (chip->chip_id == RTL8852A)
4539 _action_wl_2g_scc(rtwdev);
4540 else if (chip->chip_id == RTL8852C)
4541 _action_wl_2g_scc_v1(rtwdev);
4542 break;
4543 case BTC_WLINK_2G_MCC:
4544 _action_wl_2g_mcc(rtwdev);
4545 break;
4546 case BTC_WLINK_25G_MCC:
4547 _action_wl_25g_mcc(rtwdev);
4548 break;
4549 case BTC_WLINK_5G:
4550 _action_wl_5g(rtwdev);
4551 break;
4552 case BTC_WLINK_2G_NAN:
4553 _action_wl_2g_nan(rtwdev);
4554 break;
4555 default:
4556 _action_wl_other(rtwdev);
4557 break;
4558 }
4559
4560 exit:
4561 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__);
4562 _action_common(rtwdev);
4563 }
4564
rtw89_btc_ntfy_poweron(struct rtw89_dev * rtwdev)4565 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
4566 {
4567 struct rtw89_btc *btc = &rtwdev->btc;
4568
4569 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4570 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++;
4571 }
4572
rtw89_btc_ntfy_poweroff(struct rtw89_dev * rtwdev)4573 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
4574 {
4575 struct rtw89_btc *btc = &rtwdev->btc;
4576 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4577
4578 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4579 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
4580
4581 btc->cx.wl.status.map.rf_off = 1;
4582 btc->cx.wl.status.map.busy = 0;
4583 wl->status.map.lps = BTC_LPS_OFF;
4584
4585 _write_scbd(rtwdev, BTC_WSCB_ALL, false);
4586 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
4587
4588 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
4589
4590 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
4591 }
4592
_set_init_info(struct rtw89_dev * rtwdev)4593 static void _set_init_info(struct rtw89_dev *rtwdev)
4594 {
4595 const struct rtw89_chip_info *chip = rtwdev->chip;
4596 struct rtw89_btc *btc = &rtwdev->btc;
4597 struct rtw89_btc_dm *dm = &btc->dm;
4598 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4599
4600 dm->init_info.wl_only = (u8)dm->wl_only;
4601 dm->init_info.bt_only = (u8)dm->bt_only;
4602 dm->init_info.wl_init_ok = (u8)wl->status.map.init_ok;
4603 dm->init_info.dbcc_en = rtwdev->dbcc_en;
4604 dm->init_info.cx_other = btc->cx.other.type;
4605 dm->init_info.wl_guard_ch = chip->afh_guard_ch;
4606 dm->init_info.module = btc->mdinfo;
4607 }
4608
rtw89_btc_ntfy_init(struct rtw89_dev * rtwdev,u8 mode)4609 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
4610 {
4611 struct rtw89_btc *btc = &rtwdev->btc;
4612 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4613 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4614 const struct rtw89_chip_info *chip = rtwdev->chip;
4615
4616 _reset_btc_var(rtwdev, BTC_RESET_ALL);
4617 btc->dm.run_reason = BTC_RSN_NONE;
4618 btc->dm.run_action = BTC_ACT_NONE;
4619 btc->ctrl.igno_bt = true;
4620
4621 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4622 "[BTC], %s(): mode=%d\n", __func__, mode);
4623
4624 dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
4625 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0;
4626 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0;
4627 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0;
4628
4629 chip->ops->btc_set_rfe(rtwdev);
4630 chip->ops->btc_init_cfg(rtwdev);
4631
4632 if (!wl->status.map.init_ok) {
4633 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4634 "[BTC], %s(): return for WL init fail!!\n",
4635 __func__);
4636 dm->error.map.init = true;
4637 return;
4638 }
4639
4640 _write_scbd(rtwdev,
4641 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
4642 _update_bt_scbd(rtwdev, true);
4643 if (rtw89_mac_get_ctrl_path(rtwdev)) {
4644 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4645 "[BTC], %s(): PTA owner warning!!\n",
4646 __func__);
4647 dm->error.map.pta_owner = true;
4648 }
4649
4650 _set_init_info(rtwdev);
4651 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR);
4652 rtw89_btc_fw_set_slots(rtwdev, CXST_MAX, dm->slot);
4653 btc_fw_set_monreg(rtwdev);
4654 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
4655 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
4656
4657 _run_coex(rtwdev, BTC_RSN_NTFY_INIT);
4658 }
4659
rtw89_btc_ntfy_scan_start(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)4660 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
4661 {
4662 struct rtw89_btc *btc = &rtwdev->btc;
4663 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4664
4665 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4666 "[BTC], %s(): phy_idx=%d, band=%d\n",
4667 __func__, phy_idx, band);
4668 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
4669 wl->status.map.scan = true;
4670 wl->scan_info.band[phy_idx] = band;
4671 wl->scan_info.phy_map |= BIT(phy_idx);
4672 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
4673
4674 if (rtwdev->dbcc_en) {
4675 wl->dbcc_info.scan_band[phy_idx] = band;
4676 _update_dbcc_band(rtwdev, phy_idx);
4677 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
4678 }
4679
4680 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START);
4681 }
4682
rtw89_btc_ntfy_scan_finish(struct rtw89_dev * rtwdev,u8 phy_idx)4683 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
4684 {
4685 struct rtw89_btc *btc = &rtwdev->btc;
4686 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4687
4688 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4689 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
4690 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
4691
4692 wl->status.map.scan = false;
4693 wl->scan_info.phy_map &= ~BIT(phy_idx);
4694 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
4695
4696 if (rtwdev->dbcc_en) {
4697 _update_dbcc_band(rtwdev, phy_idx);
4698 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
4699 }
4700
4701 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
4702 }
4703
rtw89_btc_ntfy_switch_band(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)4704 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
4705 {
4706 struct rtw89_btc *btc = &rtwdev->btc;
4707 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4708
4709 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4710 "[BTC], %s(): phy_idx=%d, band=%d\n",
4711 __func__, phy_idx, band);
4712 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
4713
4714 wl->scan_info.band[phy_idx] = band;
4715 wl->scan_info.phy_map |= BIT(phy_idx);
4716 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
4717
4718 if (rtwdev->dbcc_en) {
4719 wl->dbcc_info.scan_band[phy_idx] = band;
4720 _update_dbcc_band(rtwdev, phy_idx);
4721 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
4722 }
4723 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND);
4724 }
4725
rtw89_btc_ntfy_specific_packet(struct rtw89_dev * rtwdev,enum btc_pkt_type pkt_type)4726 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev,
4727 enum btc_pkt_type pkt_type)
4728 {
4729 struct rtw89_btc *btc = &rtwdev->btc;
4730 struct rtw89_btc_cx *cx = &btc->cx;
4731 struct rtw89_btc_wl_info *wl = &cx->wl;
4732 struct rtw89_btc_bt_link_info *b = &cx->bt.link_info;
4733 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
4734 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
4735 u32 cnt;
4736 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD;
4737 bool delay_work = false;
4738
4739 switch (pkt_type) {
4740 case PACKET_DHCP:
4741 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP];
4742 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4743 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt);
4744 wl->status.map.connecting = true;
4745 delay_work = true;
4746 break;
4747 case PACKET_EAPOL:
4748 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
4749 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4750 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt);
4751 wl->status.map._4way = true;
4752 delay_work = true;
4753 if (hfp->exist || hid->exist)
4754 delay /= 2;
4755 break;
4756 case PACKET_EAPOL_END:
4757 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
4758 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4759 "[BTC], %s(): EAPOL_End cnt=%d\n",
4760 __func__, cnt);
4761 wl->status.map._4way = false;
4762 cancel_delayed_work(&rtwdev->coex_act1_work);
4763 break;
4764 case PACKET_ARP:
4765 cnt = ++cx->cnt_wl[BTC_WCNT_ARP];
4766 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4767 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt);
4768 return;
4769 case PACKET_ICMP:
4770 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4771 "[BTC], %s(): ICMP pkt\n", __func__);
4772 return;
4773 default:
4774 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4775 "[BTC], %s(): unknown packet type %d\n",
4776 __func__, pkt_type);
4777 return;
4778 }
4779
4780 if (delay_work) {
4781 cancel_delayed_work(&rtwdev->coex_act1_work);
4782 ieee80211_queue_delayed_work(rtwdev->hw,
4783 &rtwdev->coex_act1_work, delay);
4784 }
4785
4786 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
4787 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET);
4788 }
4789
rtw89_btc_ntfy_eapol_packet_work(struct work_struct * work)4790 void rtw89_btc_ntfy_eapol_packet_work(struct work_struct *work)
4791 {
4792 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4793 btc.eapol_notify_work);
4794
4795 mutex_lock(&rtwdev->mutex);
4796 rtw89_leave_ps_mode(rtwdev);
4797 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL);
4798 mutex_unlock(&rtwdev->mutex);
4799 }
4800
rtw89_btc_ntfy_arp_packet_work(struct work_struct * work)4801 void rtw89_btc_ntfy_arp_packet_work(struct work_struct *work)
4802 {
4803 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4804 btc.arp_notify_work);
4805
4806 mutex_lock(&rtwdev->mutex);
4807 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP);
4808 mutex_unlock(&rtwdev->mutex);
4809 }
4810
rtw89_btc_ntfy_dhcp_packet_work(struct work_struct * work)4811 void rtw89_btc_ntfy_dhcp_packet_work(struct work_struct *work)
4812 {
4813 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4814 btc.dhcp_notify_work);
4815
4816 mutex_lock(&rtwdev->mutex);
4817 rtw89_leave_ps_mode(rtwdev);
4818 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP);
4819 mutex_unlock(&rtwdev->mutex);
4820 }
4821
rtw89_btc_ntfy_icmp_packet_work(struct work_struct * work)4822 void rtw89_btc_ntfy_icmp_packet_work(struct work_struct *work)
4823 {
4824 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
4825 btc.icmp_notify_work);
4826
4827 mutex_lock(&rtwdev->mutex);
4828 rtw89_leave_ps_mode(rtwdev);
4829 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP);
4830 mutex_unlock(&rtwdev->mutex);
4831 }
4832
_update_bt_info(struct rtw89_dev * rtwdev,u8 * buf,u32 len)4833 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
4834 {
4835 const struct rtw89_chip_info *chip = rtwdev->chip;
4836 struct rtw89_btc *btc = &rtwdev->btc;
4837 struct rtw89_btc_cx *cx = &btc->cx;
4838 struct rtw89_btc_bt_info *bt = &cx->bt;
4839 struct rtw89_btc_bt_link_info *b = &bt->link_info;
4840 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
4841 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
4842 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
4843 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc;
4844 union btc_btinfo btinfo;
4845
4846 if (buf[BTC_BTINFO_L1] != 6)
4847 return;
4848
4849 if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) {
4850 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4851 "[BTC], %s(): return by bt-info duplicate!!\n",
4852 __func__);
4853 cx->cnt_bt[BTC_BCNT_INFOSAME]++;
4854 return;
4855 }
4856
4857 memcpy(bt->raw_info, buf, BTC_BTINFO_MAX);
4858
4859 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4860 "[BTC], %s(): bt_info[2]=0x%02x\n",
4861 __func__, bt->raw_info[2]);
4862
4863 /* reset to mo-connect before update */
4864 b->status.val = BTC_BLINK_NOCONNECT;
4865 b->profile_cnt.last = b->profile_cnt.now;
4866 b->relink.last = b->relink.now;
4867 a2dp->exist_last = a2dp->exist;
4868 b->multi_link.last = b->multi_link.now;
4869 bt->inq_pag.last = bt->inq_pag.now;
4870 b->profile_cnt.now = 0;
4871 hid->type = 0;
4872
4873 /* parse raw info low-Byte2 */
4874 btinfo.val = bt->raw_info[BTC_BTINFO_L2];
4875 b->status.map.connect = btinfo.lb2.connect;
4876 b->status.map.sco_busy = btinfo.lb2.sco_busy;
4877 b->status.map.acl_busy = btinfo.lb2.acl_busy;
4878 b->status.map.inq_pag = btinfo.lb2.inq_pag;
4879 bt->inq_pag.now = btinfo.lb2.inq_pag;
4880 cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
4881
4882 hfp->exist = btinfo.lb2.hfp;
4883 b->profile_cnt.now += (u8)hfp->exist;
4884 hid->exist = btinfo.lb2.hid;
4885 b->profile_cnt.now += (u8)hid->exist;
4886 a2dp->exist = btinfo.lb2.a2dp;
4887 b->profile_cnt.now += (u8)a2dp->exist;
4888 pan->active = btinfo.lb2.pan;
4889
4890 /* parse raw info low-Byte3 */
4891 btinfo.val = bt->raw_info[BTC_BTINFO_L3];
4892 if (btinfo.lb3.retry != 0)
4893 cx->cnt_bt[BTC_BCNT_RETRY]++;
4894 b->cqddr = btinfo.lb3.cqddr;
4895 cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
4896 bt->inq = btinfo.lb3.inq;
4897 cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
4898 bt->pag = btinfo.lb3.pag;
4899
4900 b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
4901 /* parse raw info high-Byte0 */
4902 btinfo.val = bt->raw_info[BTC_BTINFO_H0];
4903 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/
4904 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi);
4905
4906 /* parse raw info high-Byte1 */
4907 btinfo.val = bt->raw_info[BTC_BTINFO_H1];
4908 b->status.map.ble_connect = btinfo.hb1.ble_connect;
4909 if (btinfo.hb1.ble_connect)
4910 hid->type |= (hid->exist ? BTC_HID_BLE : BTC_HID_RCU);
4911
4912 cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
4913 bt->reinit = btinfo.hb1.reinit;
4914 cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
4915 b->relink.now = btinfo.hb1.relink;
4916 cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
4917 bt->igno_wl = btinfo.hb1.igno_wl;
4918
4919 if (bt->igno_wl && !cx->wl.status.map.rf_off)
4920 _set_bt_ignore_wlan_act(rtwdev, false);
4921
4922 hid->type |= (btinfo.hb1.voice ? BTC_HID_RCU_VOICE : 0);
4923 bt->ble_scan_en = btinfo.hb1.ble_scan;
4924
4925 cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
4926 b->role_sw = btinfo.hb1.role_sw;
4927
4928 b->multi_link.now = btinfo.hb1.multi_link;
4929
4930 /* parse raw info high-Byte2 */
4931 btinfo.val = bt->raw_info[BTC_BTINFO_H2];
4932 pan->exist = btinfo.hb2.pan_active;
4933 b->profile_cnt.now += (u8)pan->exist;
4934
4935 cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
4936 b->afh_update = btinfo.hb2.afh_update;
4937 a2dp->active = btinfo.hb2.a2dp_active;
4938 b->slave_role = btinfo.hb2.slave;
4939 hid->slot_info = btinfo.hb2.hid_slot;
4940 hid->pair_cnt = btinfo.hb2.hid_cnt;
4941 hid->type |= (hid->slot_info == BTC_HID_218 ?
4942 BTC_HID_218 : BTC_HID_418);
4943 /* parse raw info high-Byte3 */
4944 btinfo.val = bt->raw_info[BTC_BTINFO_H3];
4945 a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
4946
4947 if (b->tx_3m != (u32)btinfo.hb3.tx_3m)
4948 cx->cnt_bt[BTC_BCNT_RATECHG]++;
4949 b->tx_3m = (u32)btinfo.hb3.tx_3m;
4950
4951 a2dp->sink = btinfo.hb3.a2dp_sink;
4952
4953 if (b->profile_cnt.now || b->status.map.ble_connect)
4954 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, 1);
4955 else
4956 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, 0);
4957
4958 if (!a2dp->exist_last && a2dp->exist) {
4959 a2dp->vendor_id = 0;
4960 a2dp->flush_time = 0;
4961 a2dp->play_latency = 1;
4962 ieee80211_queue_delayed_work(rtwdev->hw,
4963 &rtwdev->coex_bt_devinfo_work,
4964 RTW89_COEX_BT_DEVINFO_WORK_PERIOD);
4965 }
4966
4967 if (a2dp->exist && (a2dp->flush_time == 0 || a2dp->vendor_id == 0 ||
4968 a2dp->play_latency == 1))
4969 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, 1);
4970 else
4971 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, 0);
4972
4973 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
4974 }
4975
4976 enum btc_wl_mode {
4977 BTC_WL_MODE_HT = 0,
4978 BTC_WL_MODE_VHT = 1,
4979 BTC_WL_MODE_HE = 2,
4980 BTC_WL_MODE_NUM,
4981 };
4982
rtw89_btc_ntfy_role_info(struct rtw89_dev * rtwdev,struct rtw89_vif * rtwvif,struct rtw89_sta * rtwsta,enum btc_role_state state)4983 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
4984 struct rtw89_sta *rtwsta, enum btc_role_state state)
4985 {
4986 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
4987 const struct rtw89_chip_info *chip = rtwdev->chip;
4988 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
4989 struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
4990 struct rtw89_btc *btc = &rtwdev->btc;
4991 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4992 struct rtw89_btc_wl_link_info r = {0};
4993 struct rtw89_btc_wl_link_info *wlinfo = NULL;
4994 u8 mode = 0;
4995
4996 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
4997 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4998 "[BTC], role is STA=%d\n",
4999 vif->type == NL80211_IFTYPE_STATION);
5000 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port);
5001 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
5002 chan->band_type, chan->channel, chan->band_width);
5003 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
5004 state == BTC_ROLE_MSTS_STA_CONN_END);
5005 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5006 "[BTC], bcn_period=%d dtim_period=%d\n",
5007 vif->bss_conf.beacon_int, vif->bss_conf.dtim_period);
5008
5009 if (rtwsta) {
5010 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
5011 rtwsta->mac_id);
5012
5013 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5014 "[BTC], STA support HE=%d VHT=%d HT=%d\n",
5015 sta->deflink.he_cap.has_he,
5016 sta->deflink.vht_cap.vht_supported,
5017 sta->deflink.ht_cap.ht_supported);
5018 if (sta->deflink.he_cap.has_he)
5019 mode |= BIT(BTC_WL_MODE_HE);
5020 if (sta->deflink.vht_cap.vht_supported)
5021 mode |= BIT(BTC_WL_MODE_VHT);
5022 if (sta->deflink.ht_cap.ht_supported)
5023 mode |= BIT(BTC_WL_MODE_HT);
5024
5025 r.mode = mode;
5026 }
5027
5028 if (rtwvif->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX)
5029 return;
5030
5031 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5032 "[BTC], wifi_role=%d\n", rtwvif->wifi_role);
5033
5034 r.role = rtwvif->wifi_role;
5035 r.phy = rtwvif->phy_idx;
5036 r.pid = rtwvif->port;
5037 r.active = true;
5038 r.connected = MLME_LINKED;
5039 r.bcn_period = vif->bss_conf.beacon_int;
5040 r.dtim_period = vif->bss_conf.dtim_period;
5041 r.band = chan->band_type;
5042 r.ch = chan->channel;
5043 r.bw = chan->band_width;
5044 ether_addr_copy(r.mac_addr, rtwvif->mac_addr);
5045
5046 if (rtwsta && vif->type == NL80211_IFTYPE_STATION)
5047 r.mac_id = rtwsta->mac_id;
5048
5049 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
5050
5051 wlinfo = &wl->link_info[r.pid];
5052
5053 memcpy(wlinfo, &r, sizeof(*wlinfo));
5054 if (chip->chip_id == RTL8852A)
5055 _update_wl_info(rtwdev);
5056 else
5057 _update_wl_info_v1(rtwdev);
5058
5059 if (wlinfo->role == RTW89_WIFI_ROLE_STATION &&
5060 wlinfo->connected == MLME_NO_LINK)
5061 btc->dm.leak_ap = 0;
5062
5063 if (state == BTC_ROLE_MSTS_STA_CONN_START)
5064 wl->status.map.connecting = 1;
5065 else
5066 wl->status.map.connecting = 0;
5067
5068 if (state == BTC_ROLE_MSTS_STA_DIS_CONN)
5069 wl->status.map._4way = false;
5070
5071 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
5072 }
5073
rtw89_btc_ntfy_radio_state(struct rtw89_dev * rtwdev,enum btc_rfctrl rf_state)5074 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state)
5075 {
5076 const struct rtw89_chip_info *chip = rtwdev->chip;
5077 struct rtw89_btc *btc = &rtwdev->btc;
5078 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5079 u32 val;
5080
5081 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
5082 __func__, rf_state);
5083 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
5084
5085 switch (rf_state) {
5086 case BTC_RFCTRL_WL_OFF:
5087 wl->status.map.rf_off = 1;
5088 wl->status.map.lps = BTC_LPS_OFF;
5089 wl->status.map.busy = 0;
5090 break;
5091 case BTC_RFCTRL_FW_CTRL:
5092 wl->status.map.rf_off = 0;
5093 wl->status.map.lps = BTC_LPS_RF_OFF;
5094 wl->status.map.busy = 0;
5095 break;
5096 case BTC_RFCTRL_WL_ON:
5097 default:
5098 wl->status.map.rf_off = 0;
5099 wl->status.map.lps = BTC_LPS_OFF;
5100 break;
5101 }
5102
5103 if (rf_state == BTC_RFCTRL_WL_ON) {
5104 btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] = 0;
5105 rtw89_btc_fw_en_rpt(rtwdev,
5106 RPT_EN_MREG | RPT_EN_BT_VER_INFO, true);
5107 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG;
5108 _write_scbd(rtwdev, val, true);
5109 _update_bt_scbd(rtwdev, true);
5110 chip->ops->btc_init_cfg(rtwdev);
5111 } else {
5112 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false);
5113 if (rf_state == BTC_RFCTRL_WL_OFF)
5114 _write_scbd(rtwdev, BTC_WSCB_ALL, false);
5115 }
5116
5117 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
5118
5119 wl->status.map.rf_off_pre = wl->status.map.rf_off;
5120 wl->status.map.lps_pre = wl->status.map.lps;
5121 }
5122
_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_path,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)5123 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path,
5124 enum btc_wl_rfk_type type,
5125 enum btc_wl_rfk_state state)
5126 {
5127 struct rtw89_btc *btc = &rtwdev->btc;
5128 struct rtw89_btc_cx *cx = &btc->cx;
5129 struct rtw89_btc_wl_info *wl = &cx->wl;
5130 bool result = BTC_WRFK_REJECT;
5131
5132 wl->rfk_info.type = type;
5133 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path);
5134 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path);
5135 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path);
5136
5137 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5138 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
5139 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
5140 type, state);
5141
5142 switch (state) {
5143 case BTC_WRFK_START:
5144 result = _chk_wl_rfk_request(rtwdev);
5145 wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP;
5146
5147 _write_scbd(rtwdev, BTC_WSCB_WLRFK, result);
5148
5149 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
5150 break;
5151 case BTC_WRFK_ONESHOT_START:
5152 case BTC_WRFK_ONESHOT_STOP:
5153 if (wl->rfk_info.state == BTC_WRFK_STOP) {
5154 result = BTC_WRFK_REJECT;
5155 } else {
5156 result = BTC_WRFK_ALLOW;
5157 wl->rfk_info.state = state;
5158 }
5159 break;
5160 case BTC_WRFK_STOP:
5161 result = BTC_WRFK_ALLOW;
5162 wl->rfk_info.state = BTC_WRFK_STOP;
5163
5164 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
5165 cancel_delayed_work(&rtwdev->coex_rfk_chk_work);
5166 break;
5167 default:
5168 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5169 "[BTC], %s() warning state=%d\n", __func__, state);
5170 break;
5171 }
5172
5173 if (result == BTC_WRFK_ALLOW) {
5174 if (wl->rfk_info.state == BTC_WRFK_START ||
5175 wl->rfk_info.state == BTC_WRFK_STOP)
5176 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK);
5177
5178 if (wl->rfk_info.state == BTC_WRFK_START)
5179 ieee80211_queue_delayed_work(rtwdev->hw,
5180 &rtwdev->coex_rfk_chk_work,
5181 RTW89_COEX_RFK_CHK_WORK_PERIOD);
5182 }
5183
5184 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5185 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
5186 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
5187
5188 return result == BTC_WRFK_ALLOW;
5189 }
5190
rtw89_btc_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_map,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)5191 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
5192 enum btc_wl_rfk_type type,
5193 enum btc_wl_rfk_state state)
5194 {
5195 u8 band;
5196 bool allow;
5197 int ret;
5198
5199 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map);
5200
5201 rtw89_debug(rtwdev, RTW89_DBG_RFK,
5202 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n",
5203 band == RTW89_BAND_2G ? "2G" :
5204 band == RTW89_BAND_5G ? "5G" : "6G",
5205 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)),
5206 type,
5207 FIELD_GET(BTC_RFK_PATH_MAP, phy_map),
5208 state == BTC_WRFK_STOP ? "RFK_STOP" :
5209 state == BTC_WRFK_START ? "RFK_START" :
5210 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" :
5211 "ONE-SHOT_STOP");
5212
5213 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) {
5214 _ntfy_wl_rfk(rtwdev, phy_map, type, state);
5215 return;
5216 }
5217
5218 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false,
5219 rtwdev, phy_map, type, state);
5220 if (ret) {
5221 rtw89_warn(rtwdev, "RFK notify timeout\n");
5222 rtwdev->is_bt_iqk_timeout = true;
5223 }
5224 }
5225 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk);
5226
5227 struct rtw89_btc_wl_sta_iter_data {
5228 struct rtw89_dev *rtwdev;
5229 u8 busy_all;
5230 u8 dir_all;
5231 u8 rssi_map_all;
5232 bool is_sta_change;
5233 bool is_traffic_change;
5234 };
5235
rtw89_btc_ntfy_wl_sta_iter(void * data,struct ieee80211_sta * sta)5236 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
5237 {
5238 struct rtw89_btc_wl_sta_iter_data *iter_data =
5239 (struct rtw89_btc_wl_sta_iter_data *)data;
5240 struct rtw89_dev *rtwdev = iter_data->rtwdev;
5241 struct rtw89_btc *btc = &rtwdev->btc;
5242 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5243 struct rtw89_btc_wl_link_info *link_info = NULL;
5244 struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
5245 struct rtw89_traffic_stats *link_info_t = NULL;
5246 struct rtw89_vif *rtwvif = rtwsta->rtwvif;
5247 struct rtw89_traffic_stats *stats = &rtwvif->stats;
5248 const struct rtw89_chip_info *chip = rtwdev->chip;
5249 u32 last_tx_rate, last_rx_rate;
5250 u16 last_tx_lvl, last_rx_lvl;
5251 u8 port = rtwvif->port;
5252 u8 rssi;
5253 u8 busy = 0;
5254 u8 dir = 0;
5255 u8 rssi_map = 0;
5256 u8 i = 0;
5257 bool is_sta_change = false, is_traffic_change = false;
5258
5259 rssi = ewma_rssi_read(&rtwsta->avg_rssi) >> RSSI_FACTOR;
5260 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
5261
5262 link_info = &wl->link_info[port];
5263 link_info->stat.traffic = rtwvif->stats;
5264 link_info_t = &link_info->stat.traffic;
5265
5266 if (link_info->connected == MLME_NO_LINK) {
5267 link_info->rx_rate_drop_cnt = 0;
5268 return;
5269 }
5270
5271 link_info->stat.rssi = rssi;
5272 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) {
5273 link_info->rssi_state[i] =
5274 _update_rssi_state(rtwdev,
5275 link_info->rssi_state[i],
5276 link_info->stat.rssi,
5277 chip->wl_rssi_thres[i]);
5278 if (BTC_RSSI_LOW(link_info->rssi_state[i]))
5279 rssi_map |= BIT(i);
5280
5281 if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED &&
5282 BTC_RSSI_CHANGE(link_info->rssi_state[i]))
5283 is_sta_change = true;
5284 }
5285 iter_data->rssi_map_all |= rssi_map;
5286
5287 last_tx_rate = link_info_t->tx_rate;
5288 last_rx_rate = link_info_t->rx_rate;
5289 last_tx_lvl = (u16)link_info_t->tx_tfc_lv;
5290 last_rx_lvl = (u16)link_info_t->rx_tfc_lv;
5291
5292 if (stats->tx_tfc_lv != RTW89_TFC_IDLE ||
5293 stats->rx_tfc_lv != RTW89_TFC_IDLE)
5294 busy = 1;
5295
5296 if (stats->tx_tfc_lv > stats->rx_tfc_lv)
5297 dir = RTW89_TFC_UL;
5298 else
5299 dir = RTW89_TFC_DL;
5300
5301 link_info = &wl->link_info[port];
5302 if (link_info->busy != busy || link_info->dir != dir) {
5303 is_sta_change = true;
5304 link_info->busy = busy;
5305 link_info->dir = dir;
5306 }
5307
5308 iter_data->busy_all |= busy;
5309 iter_data->dir_all |= BIT(dir);
5310
5311 if (rtwsta->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
5312 last_rx_rate > RTW89_HW_RATE_CCK2 &&
5313 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
5314 link_info->rx_rate_drop_cnt++;
5315
5316 if (last_tx_rate != rtwsta->ra_report.hw_rate ||
5317 last_rx_rate != rtwsta->rx_hw_rate ||
5318 last_tx_lvl != link_info_t->tx_tfc_lv ||
5319 last_rx_lvl != link_info_t->rx_tfc_lv)
5320 is_traffic_change = true;
5321
5322 link_info_t->tx_rate = rtwsta->ra_report.hw_rate;
5323 link_info_t->rx_rate = rtwsta->rx_hw_rate;
5324
5325 wl->role_info.active_role[port].tx_lvl = (u16)stats->tx_tfc_lv;
5326 wl->role_info.active_role[port].rx_lvl = (u16)stats->rx_tfc_lv;
5327 wl->role_info.active_role[port].tx_rate = rtwsta->ra_report.hw_rate;
5328 wl->role_info.active_role[port].rx_rate = rtwsta->rx_hw_rate;
5329
5330 if (is_sta_change)
5331 iter_data->is_sta_change = true;
5332
5333 if (is_traffic_change)
5334 iter_data->is_traffic_change = true;
5335 }
5336
5337 #define BTC_NHM_CHK_INTVL 20
5338
rtw89_btc_ntfy_wl_sta(struct rtw89_dev * rtwdev)5339 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
5340 {
5341 struct rtw89_btc *btc = &rtwdev->btc;
5342 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5343 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev};
5344 u8 i;
5345
5346 ieee80211_iterate_stations_atomic(rtwdev->hw,
5347 rtw89_btc_ntfy_wl_sta_iter,
5348 &data);
5349
5350 wl->rssi_level = 0;
5351 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++;
5352 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) {
5353 /* set RSSI level 4 ~ 0 if rssi bit map match */
5354 if (data.rssi_map_all & BIT(i - 1)) {
5355 wl->rssi_level = i;
5356 break;
5357 }
5358 }
5359
5360 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n",
5361 __func__, !!wl->status.map.busy);
5362
5363 _write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy));
5364
5365 if (data.is_traffic_change)
5366 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
5367 if (data.is_sta_change) {
5368 wl->status.map.busy = data.busy_all;
5369 wl->status.map.traffic_dir = data.dir_all;
5370 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA);
5371 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >=
5372 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) {
5373 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
5374 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
5375 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] <
5376 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) {
5377 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
5378 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
5379 }
5380 }
5381
rtw89_btc_c2h_handle(struct rtw89_dev * rtwdev,struct sk_buff * skb,u32 len,u8 class,u8 func)5382 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
5383 u32 len, u8 class, u8 func)
5384 {
5385 struct rtw89_btc *btc = &rtwdev->btc;
5386 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
5387 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN];
5388
5389 len -= RTW89_C2H_HEADER_LEN;
5390
5391 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5392 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n",
5393 __func__, len, class, func);
5394
5395 if (class != BTFC_FW_EVENT)
5396 return;
5397
5398 switch (func) {
5399 case BTF_EVNT_RPT:
5400 case BTF_EVNT_BUF_OVERFLOW:
5401 pfwinfo->event[func]++;
5402 /* Don't need rtw89_leave_ps_mode() */
5403 btc_fw_event(rtwdev, func, buf, len);
5404 break;
5405 case BTF_EVNT_BT_INFO:
5406 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5407 "[BTC], handle C2H BT INFO with data %8ph\n", buf);
5408 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++;
5409 _update_bt_info(rtwdev, buf, len);
5410 break;
5411 case BTF_EVNT_BT_SCBD:
5412 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5413 "[BTC], handle C2H BT SCBD with data %8ph\n", buf);
5414 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++;
5415 _update_bt_scbd(rtwdev, false);
5416 break;
5417 case BTF_EVNT_BT_PSD:
5418 break;
5419 case BTF_EVNT_BT_REG:
5420 btc->dbg.rb_done = true;
5421 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf));
5422
5423 break;
5424 case BTF_EVNT_C2H_LOOPBACK:
5425 btc->dbg.rb_done = true;
5426 btc->dbg.rb_val = buf[0];
5427 break;
5428 case BTF_EVNT_CX_RUNINFO:
5429 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
5430 break;
5431 }
5432 }
5433
5434 #define BTC_CX_FW_OFFLOAD 0
5435
_show_cx_info(struct rtw89_dev * rtwdev,struct seq_file * m)5436 static void _show_cx_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5437 {
5438 const struct rtw89_chip_info *chip = rtwdev->chip;
5439 struct rtw89_hal *hal = &rtwdev->hal;
5440 struct rtw89_btc *btc = &rtwdev->btc;
5441 struct rtw89_btc_dm *dm = &btc->dm;
5442 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5443 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5444 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
5445
5446 if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
5447 return;
5448
5449 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
5450
5451 seq_printf(m, "========== [BTC COEX INFO (%d)] ==========\n",
5452 chip->chip_id);
5453
5454 ver_main = FIELD_GET(GENMASK(31, 24), chip->para_ver);
5455 ver_sub = FIELD_GET(GENMASK(23, 16), chip->para_ver);
5456 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->para_ver);
5457 id_branch = FIELD_GET(GENMASK(7, 0), chip->para_ver);
5458 seq_printf(m, " %-15s : Coex:%d.%d.%d(branch:%d), ",
5459 "[coex_version]", ver_main, ver_sub, ver_hotfix, id_branch);
5460
5461 if (dm->wl_fw_cx_offload != BTC_CX_FW_OFFLOAD)
5462 dm->error.map.offload_mismatch = true;
5463 else
5464 dm->error.map.offload_mismatch = false;
5465
5466 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
5467 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex);
5468 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex);
5469 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex);
5470 seq_printf(m, "WL_FW_coex:%d.%d.%d(branch:%d)",
5471 ver_main, ver_sub, ver_hotfix, id_branch);
5472
5473 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired);
5474 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired);
5475 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
5476 seq_printf(m, "(%s, desired:%d.%d.%d), ",
5477 (wl->ver_info.fw_coex >= chip->wlcx_desired ?
5478 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
5479
5480 seq_printf(m, "BT_FW_coex:%d(%s, desired:%d)\n",
5481 bt->ver_info.fw_coex,
5482 (bt->ver_info.fw_coex >= chip->btcx_desired ?
5483 "Match" : "Mismatch"), chip->btcx_desired);
5484
5485 if (bt->enable.now && bt->ver_info.fw == 0)
5486 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true);
5487 else
5488 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false);
5489
5490 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw);
5491 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw);
5492 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw);
5493 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw);
5494 seq_printf(m, " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n",
5495 "[sub_module]",
5496 ver_main, ver_sub, ver_hotfix, id_branch,
5497 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM");
5498
5499 seq_printf(m, " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s",
5500 "[hw_info]", btc->mdinfo.cv, btc->mdinfo.rfe_type,
5501 btc->mdinfo.ant.isolation, btc->mdinfo.ant.num,
5502 (btc->mdinfo.ant.num > 1 ? "" : (btc->mdinfo.ant.single_pos ?
5503 "1Ant_Pos:S1, " : "1Ant_Pos:S0, ")));
5504
5505 seq_printf(m, "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n",
5506 btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss,
5507 hal->rx_nss);
5508 }
5509
_show_wl_role_info(struct rtw89_dev * rtwdev,struct seq_file * m)5510 static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5511 {
5512 struct rtw89_btc *btc = &rtwdev->btc;
5513 struct rtw89_btc_wl_link_info *plink = NULL;
5514 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5515 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5516 struct rtw89_traffic_stats *t;
5517 u8 i;
5518
5519 if (rtwdev->dbcc_en) {
5520 seq_printf(m,
5521 " %-15s : PHY0_band(op:%d/scan:%d/real:%d), ",
5522 "[dbcc_info]", wl_dinfo->op_band[RTW89_PHY_0],
5523 wl_dinfo->scan_band[RTW89_PHY_0],
5524 wl_dinfo->real_band[RTW89_PHY_0]);
5525 seq_printf(m,
5526 "PHY1_band(op:%d/scan:%d/real:%d)\n",
5527 wl_dinfo->op_band[RTW89_PHY_1],
5528 wl_dinfo->scan_band[RTW89_PHY_1],
5529 wl_dinfo->real_band[RTW89_PHY_1]);
5530 }
5531
5532 for (i = 0; i < RTW89_PORT_NUM; i++) {
5533 plink = &btc->cx.wl.link_info[i];
5534
5535 if (!plink->active)
5536 continue;
5537
5538 seq_printf(m,
5539 " [port_%d] : role=%d(phy-%d), connect=%d(client_cnt=%d), mode=%d, center_ch=%d, bw=%d",
5540 plink->pid, (u32)plink->role, plink->phy,
5541 (u32)plink->connected, plink->client_cnt - 1,
5542 (u32)plink->mode, plink->ch, (u32)plink->bw);
5543
5544 if (plink->connected == MLME_NO_LINK)
5545 continue;
5546
5547 seq_printf(m,
5548 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n",
5549 plink->mac_id, plink->tx_time, plink->tx_retry);
5550
5551 seq_printf(m,
5552 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
5553 plink->pid, 110 - plink->stat.rssi,
5554 plink->stat.rssi, plink->busy,
5555 plink->dir == RTW89_TFC_UL ? "UL" : "DL");
5556
5557 t = &plink->stat.traffic;
5558
5559 seq_printf(m,
5560 "tx[rate:%d/busy_level:%d], ",
5561 (u32)t->tx_rate, t->tx_tfc_lv);
5562
5563 seq_printf(m, "rx[rate:%d/busy_level:%d/drop:%d]\n",
5564 (u32)t->rx_rate,
5565 t->rx_tfc_lv, plink->rx_rate_drop_cnt);
5566 }
5567 }
5568
_show_wl_info(struct rtw89_dev * rtwdev,struct seq_file * m)5569 static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5570 {
5571 const struct rtw89_chip_info *chip = rtwdev->chip;
5572 struct rtw89_btc *btc = &rtwdev->btc;
5573 struct rtw89_btc_cx *cx = &btc->cx;
5574 struct rtw89_btc_wl_info *wl = &cx->wl;
5575 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5576 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5577 u8 mode;
5578
5579 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
5580 return;
5581
5582 seq_puts(m, "========== [WL Status] ==========\n");
5583
5584 if (chip->chip_id == RTL8852A)
5585 mode = wl_rinfo->link_mode;
5586 else
5587 mode = wl_rinfo_v1->link_mode;
5588
5589 seq_printf(m, " %-15s : link_mode:%d, ", "[status]", mode);
5590
5591 seq_printf(m,
5592 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ",
5593 wl->status.map.rf_off, wl->status.map.lps,
5594 wl->status.map.scan ? "Y" : "N",
5595 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
5596
5597 seq_printf(m,
5598 "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n",
5599 wl->status.map.connecting ? "Y" : "N",
5600 wl->status.map.roaming ? "Y" : "N",
5601 wl->status.map._4way ? "Y" : "N",
5602 wl->status.map.init_ok ? "Y" : "N");
5603
5604 _show_wl_role_info(rtwdev, m);
5605 }
5606
5607 enum btc_bt_a2dp_type {
5608 BTC_A2DP_LEGACY = 0,
5609 BTC_A2DP_TWS_SNIFF = 1,
5610 BTC_A2DP_TWS_RELAY = 2,
5611 };
5612
_show_bt_profile_info(struct rtw89_dev * rtwdev,struct seq_file * m)5613 static void _show_bt_profile_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5614 {
5615 struct rtw89_btc *btc = &rtwdev->btc;
5616 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
5617 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
5618 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
5619 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
5620 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
5621
5622 if (hfp.exist) {
5623 seq_printf(m, " %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
5624 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"),
5625 bt_linfo->sut_pwr_level[0],
5626 bt_linfo->golden_rx_shift[0]);
5627 }
5628
5629 if (hid.exist) {
5630 seq_printf(m,
5631 "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n",
5632 "[HID]",
5633 hid.type & BTC_HID_218 ? "2/18," : "",
5634 hid.type & BTC_HID_418 ? "4/18," : "",
5635 hid.type & BTC_HID_BLE ? "BLE," : "",
5636 hid.type & BTC_HID_RCU ? "RCU," : "",
5637 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "",
5638 hid.pair_cnt, bt_linfo->sut_pwr_level[1],
5639 bt_linfo->golden_rx_shift[1]);
5640 }
5641
5642 if (a2dp.exist) {
5643 seq_printf(m,
5644 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
5645 "[A2DP]",
5646 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS",
5647 a2dp.bitpool, a2dp.flush_time);
5648
5649 seq_printf(m,
5650 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n",
5651 a2dp.vendor_id, a2dp.device_name,
5652 bt_linfo->sut_pwr_level[2],
5653 bt_linfo->golden_rx_shift[2]);
5654 }
5655
5656 if (pan.exist) {
5657 seq_printf(m, " %-15s : sut_pwr:%d, golden-rx:%d\n",
5658 "[PAN]",
5659 bt_linfo->sut_pwr_level[3],
5660 bt_linfo->golden_rx_shift[3]);
5661 }
5662 }
5663
_show_bt_info(struct rtw89_dev * rtwdev,struct seq_file * m)5664 static void _show_bt_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5665 {
5666 struct rtw89_btc *btc = &rtwdev->btc;
5667 struct rtw89_btc_cx *cx = &btc->cx;
5668 struct rtw89_btc_bt_info *bt = &cx->bt;
5669 struct rtw89_btc_wl_info *wl = &cx->wl;
5670 struct rtw89_btc_module *module = &btc->mdinfo;
5671 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
5672 u8 *afh = bt_linfo->afh_map;
5673
5674 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
5675 return;
5676
5677 seq_puts(m, "========== [BT Status] ==========\n");
5678
5679 seq_printf(m, " %-15s : enable:%s, btg:%s%s, connect:%s, ",
5680 "[status]", bt->enable.now ? "Y" : "N",
5681 bt->btg_type ? "Y" : "N",
5682 (bt->enable.now && (bt->btg_type != module->bt_pos) ?
5683 "(efuse-mismatch!!)" : ""),
5684 (bt_linfo->status.map.connect ? "Y" : "N"));
5685
5686 seq_printf(m, "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n",
5687 bt->igno_wl ? "Y" : "N",
5688 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val);
5689
5690 seq_printf(m, " %-15s : profile:%s%s%s%s%s ",
5691 "[profile]",
5692 (bt_linfo->profile_cnt.now == 0) ? "None," : "",
5693 bt_linfo->hfp_desc.exist ? "HFP," : "",
5694 bt_linfo->hid_desc.exist ? "HID," : "",
5695 bt_linfo->a2dp_desc.exist ?
5696 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "",
5697 bt_linfo->pan_desc.exist ? "PAN," : "");
5698
5699 seq_printf(m,
5700 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n",
5701 bt_linfo->multi_link.now ? "Y" : "N",
5702 bt_linfo->slave_role ? "Slave" : "Master",
5703 bt_linfo->status.map.ble_connect ? "Y" : "N",
5704 bt_linfo->cqddr ? "Y" : "N",
5705 bt_linfo->a2dp_desc.active ? "Y" : "N",
5706 bt_linfo->pan_desc.active ? "Y" : "N");
5707
5708 seq_printf(m,
5709 " %-15s : rssi:%ddBm, tx_rate:%dM, %s%s%s",
5710 "[link]", bt_linfo->rssi - 100,
5711 bt_linfo->tx_3m ? 3 : 2,
5712 bt_linfo->status.map.inq_pag ? " inq-page!!" : "",
5713 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "",
5714 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : "");
5715
5716 seq_printf(m,
5717 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
5718 bt_linfo->relink.now ? " ReLink!!" : "",
5719 afh[0], afh[1], afh[2], afh[3], afh[4],
5720 afh[5], afh[6], afh[7], afh[8], afh[9]);
5721
5722 seq_printf(m, "wl_ch_map[en:%d/ch:%d/bw:%d]\n",
5723 wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw);
5724
5725 seq_printf(m,
5726 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
5727 "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY],
5728 cx->cnt_bt[BTC_BCNT_RELINK], cx->cnt_bt[BTC_BCNT_RATECHG],
5729 cx->cnt_bt[BTC_BCNT_REINIT], cx->cnt_bt[BTC_BCNT_REENABLE]);
5730
5731 seq_printf(m,
5732 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n",
5733 cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH],
5734 cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ],
5735 cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]);
5736
5737 _show_bt_profile_info(rtwdev, m);
5738
5739 seq_printf(m,
5740 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n",
5741 "[bt_info]", bt->raw_info[2], bt->raw_info[3],
5742 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6],
5743 bt->raw_info[7],
5744 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
5745 cx->cnt_bt[BTC_BCNT_INFOUPDATE],
5746 cx->cnt_bt[BTC_BCNT_INFOSAME]);
5747
5748 seq_printf(m,
5749 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)\n",
5750 "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX],
5751 cx->cnt_bt[BTC_BCNT_HIPRI_TX], cx->cnt_bt[BTC_BCNT_LOPRI_RX],
5752 cx->cnt_bt[BTC_BCNT_LOPRI_TX], cx->cnt_bt[BTC_BCNT_POLUT]);
5753 }
5754
5755 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e
5756 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
5757 #define CASE_BTC_POLICY_STR(e) \
5758 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
5759
steps_to_str(u16 step)5760 static const char *steps_to_str(u16 step)
5761 {
5762 switch (step) {
5763 CASE_BTC_RSN_STR(NONE);
5764 CASE_BTC_RSN_STR(NTFY_INIT);
5765 CASE_BTC_RSN_STR(NTFY_SWBAND);
5766 CASE_BTC_RSN_STR(NTFY_WL_STA);
5767 CASE_BTC_RSN_STR(NTFY_RADIO_STATE);
5768 CASE_BTC_RSN_STR(UPDATE_BT_SCBD);
5769 CASE_BTC_RSN_STR(NTFY_WL_RFK);
5770 CASE_BTC_RSN_STR(UPDATE_BT_INFO);
5771 CASE_BTC_RSN_STR(NTFY_SCAN_START);
5772 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH);
5773 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET);
5774 CASE_BTC_RSN_STR(NTFY_POWEROFF);
5775 CASE_BTC_RSN_STR(NTFY_ROLE_INFO);
5776 CASE_BTC_RSN_STR(CMD_SET_COEX);
5777 CASE_BTC_RSN_STR(ACT1_WORK);
5778 CASE_BTC_RSN_STR(BT_DEVINFO_WORK);
5779 CASE_BTC_RSN_STR(RFK_CHK_WORK);
5780
5781 CASE_BTC_ACT_STR(NONE);
5782 CASE_BTC_ACT_STR(WL_ONLY);
5783 CASE_BTC_ACT_STR(WL_5G);
5784 CASE_BTC_ACT_STR(WL_OTHER);
5785 CASE_BTC_ACT_STR(WL_IDLE);
5786 CASE_BTC_ACT_STR(WL_NC);
5787 CASE_BTC_ACT_STR(WL_RFK);
5788 CASE_BTC_ACT_STR(WL_INIT);
5789 CASE_BTC_ACT_STR(WL_OFF);
5790 CASE_BTC_ACT_STR(FREERUN);
5791 CASE_BTC_ACT_STR(BT_WHQL);
5792 CASE_BTC_ACT_STR(BT_RFK);
5793 CASE_BTC_ACT_STR(BT_OFF);
5794 CASE_BTC_ACT_STR(BT_IDLE);
5795 CASE_BTC_ACT_STR(BT_HFP);
5796 CASE_BTC_ACT_STR(BT_HID);
5797 CASE_BTC_ACT_STR(BT_A2DP);
5798 CASE_BTC_ACT_STR(BT_A2DPSINK);
5799 CASE_BTC_ACT_STR(BT_PAN);
5800 CASE_BTC_ACT_STR(BT_A2DP_HID);
5801 CASE_BTC_ACT_STR(BT_A2DP_PAN);
5802 CASE_BTC_ACT_STR(BT_PAN_HID);
5803 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID);
5804 CASE_BTC_ACT_STR(WL_25G_MCC);
5805 CASE_BTC_ACT_STR(WL_2G_MCC);
5806 CASE_BTC_ACT_STR(WL_2G_SCC);
5807 CASE_BTC_ACT_STR(WL_2G_AP);
5808 CASE_BTC_ACT_STR(WL_2G_GO);
5809 CASE_BTC_ACT_STR(WL_2G_GC);
5810 CASE_BTC_ACT_STR(WL_2G_NAN);
5811
5812 CASE_BTC_POLICY_STR(OFF_BT);
5813 CASE_BTC_POLICY_STR(OFF_WL);
5814 CASE_BTC_POLICY_STR(OFF_EQ0);
5815 CASE_BTC_POLICY_STR(OFF_EQ1);
5816 CASE_BTC_POLICY_STR(OFF_EQ2);
5817 CASE_BTC_POLICY_STR(OFF_EQ3);
5818 CASE_BTC_POLICY_STR(OFF_BWB0);
5819 CASE_BTC_POLICY_STR(OFF_BWB1);
5820 CASE_BTC_POLICY_STR(OFF_BWB2);
5821 CASE_BTC_POLICY_STR(OFFB_BWB0);
5822 CASE_BTC_POLICY_STR(OFFE_DEF);
5823 CASE_BTC_POLICY_STR(OFFE_DEF2);
5824 CASE_BTC_POLICY_STR(OFFE_2GBWISOB);
5825 CASE_BTC_POLICY_STR(OFFE_2GISOB);
5826 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB);
5827 CASE_BTC_POLICY_STR(OFFE_WL);
5828 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2);
5829 CASE_BTC_POLICY_STR(FIX_TD3030);
5830 CASE_BTC_POLICY_STR(FIX_TD5050);
5831 CASE_BTC_POLICY_STR(FIX_TD2030);
5832 CASE_BTC_POLICY_STR(FIX_TD4010);
5833 CASE_BTC_POLICY_STR(FIX_TD7010);
5834 CASE_BTC_POLICY_STR(FIX_TD2060);
5835 CASE_BTC_POLICY_STR(FIX_TD3060);
5836 CASE_BTC_POLICY_STR(FIX_TD2080);
5837 CASE_BTC_POLICY_STR(FIX_TDW1B1);
5838 CASE_BTC_POLICY_STR(FIX_TD4020);
5839 CASE_BTC_POLICY_STR(FIX_TD4010ISO);
5840 CASE_BTC_POLICY_STR(PFIX_TD3030);
5841 CASE_BTC_POLICY_STR(PFIX_TD5050);
5842 CASE_BTC_POLICY_STR(PFIX_TD2030);
5843 CASE_BTC_POLICY_STR(PFIX_TD2060);
5844 CASE_BTC_POLICY_STR(PFIX_TD3070);
5845 CASE_BTC_POLICY_STR(PFIX_TD2080);
5846 CASE_BTC_POLICY_STR(PFIX_TDW1B1);
5847 CASE_BTC_POLICY_STR(AUTO_TD50B1);
5848 CASE_BTC_POLICY_STR(AUTO_TD60B1);
5849 CASE_BTC_POLICY_STR(AUTO_TD20B1);
5850 CASE_BTC_POLICY_STR(AUTO_TDW1B1);
5851 CASE_BTC_POLICY_STR(PAUTO_TD50B1);
5852 CASE_BTC_POLICY_STR(PAUTO_TD60B1);
5853 CASE_BTC_POLICY_STR(PAUTO_TD20B1);
5854 CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
5855 CASE_BTC_POLICY_STR(AUTO2_TD3050);
5856 CASE_BTC_POLICY_STR(AUTO2_TD3070);
5857 CASE_BTC_POLICY_STR(AUTO2_TD5050);
5858 CASE_BTC_POLICY_STR(AUTO2_TD6060);
5859 CASE_BTC_POLICY_STR(AUTO2_TD2080);
5860 CASE_BTC_POLICY_STR(AUTO2_TDW1B4);
5861 CASE_BTC_POLICY_STR(PAUTO2_TD3050);
5862 CASE_BTC_POLICY_STR(PAUTO2_TD3070);
5863 CASE_BTC_POLICY_STR(PAUTO2_TD5050);
5864 CASE_BTC_POLICY_STR(PAUTO2_TD6060);
5865 CASE_BTC_POLICY_STR(PAUTO2_TD2080);
5866 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4);
5867 default:
5868 return "unknown step";
5869 }
5870 }
5871
5872 static
seq_print_segment(struct seq_file * m,const char * prefix,u16 * data,u8 len,u8 seg_len,u8 start_idx,u8 ring_len)5873 void seq_print_segment(struct seq_file *m, const char *prefix, u16 *data,
5874 u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
5875 {
5876 u8 i;
5877 u8 cur_index;
5878
5879 for (i = 0; i < len ; i++) {
5880 if ((i % seg_len) == 0)
5881 seq_printf(m, " %-15s : ", prefix);
5882 cur_index = (start_idx + i) % ring_len;
5883 if (i % 3 == 0)
5884 seq_printf(m, "-> %-20s",
5885 steps_to_str(*(data + cur_index)));
5886 else if (i % 3 == 1)
5887 seq_printf(m, "-> %-15s",
5888 steps_to_str(*(data + cur_index)));
5889 else
5890 seq_printf(m, "-> %-13s",
5891 steps_to_str(*(data + cur_index)));
5892 if (i == (len - 1) || (i % seg_len) == (seg_len - 1))
5893 seq_puts(m, "\n");
5894 }
5895 }
5896
_show_dm_step(struct rtw89_dev * rtwdev,struct seq_file * m)5897 static void _show_dm_step(struct rtw89_dev *rtwdev, struct seq_file *m)
5898 {
5899 struct rtw89_btc *btc = &rtwdev->btc;
5900 struct rtw89_btc_dm *dm = &btc->dm;
5901 u8 start_idx;
5902 u8 len;
5903
5904 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos;
5905 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0;
5906
5907 seq_print_segment(m, "[dm_steps]", dm->dm_step.step, len, 6, start_idx,
5908 ARRAY_SIZE(dm->dm_step.step));
5909 }
5910
_show_dm_info(struct rtw89_dev * rtwdev,struct seq_file * m)5911 static void _show_dm_info(struct rtw89_dev *rtwdev, struct seq_file *m)
5912 {
5913 struct rtw89_btc *btc = &rtwdev->btc;
5914 struct rtw89_btc_module *module = &btc->mdinfo;
5915 struct rtw89_btc_dm *dm = &btc->dm;
5916 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5917 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5918
5919 if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
5920 return;
5921
5922 seq_printf(m, "========== [Mechanism Status %s] ==========\n",
5923 (btc->ctrl.manual ? "(Manual)" : "(Auto)"));
5924
5925 seq_printf(m,
5926 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%ld, run_cnt:%d\n",
5927 "[status]",
5928 module->ant.type == BTC_ANT_SHARED ? "shared" : "dedicated",
5929 steps_to_str(dm->run_reason),
5930 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT),
5931 FIELD_GET(GENMASK(7, 0), dm->set_ant_path),
5932 dm->cnt_dm[BTC_DCNT_RUN]);
5933
5934 _show_dm_step(rtwdev, m);
5935
5936 seq_printf(m, " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ",
5937 "[dm_flag]", dm->wl_only, dm->bt_only, btc->ctrl.igno_bt,
5938 dm->freerun, btc->lps, dm->wl_mimo_ps);
5939
5940 seq_printf(m, "leak_ap:%d, fw_offload:%s%s\n", dm->leak_ap,
5941 (BTC_CX_FW_OFFLOAD ? "Y" : "N"),
5942 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
5943 "" : "(Mismatch!!)"));
5944
5945 if (dm->rf_trx_para.wl_tx_power == 0xff)
5946 seq_printf(m,
5947 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ",
5948 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level);
5949
5950 else
5951 seq_printf(m,
5952 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ",
5953 "[trx_ctrl]", wl->rssi_level, dm->trx_para_level,
5954 dm->rf_trx_para.wl_tx_power);
5955
5956 seq_printf(m,
5957 "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n",
5958 dm->rf_trx_para.wl_rx_gain, dm->rf_trx_para.bt_tx_power,
5959 dm->rf_trx_para.bt_rx_gain,
5960 (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx);
5961
5962 seq_printf(m,
5963 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU\n",
5964 "[dm_ctrl]", dm->wl_tx_limit.enable, dm->wl_tx_limit.tx_time,
5965 dm->wl_tx_limit.tx_retry, btc->bt_req_len);
5966 }
5967
_show_error(struct rtw89_dev * rtwdev,struct seq_file * m)5968 static void _show_error(struct rtw89_dev *rtwdev, struct seq_file *m)
5969 {
5970 struct rtw89_btc *btc = &rtwdev->btc;
5971 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
5972 struct rtw89_btc_fbtc_cysta *pcysta = NULL;
5973
5974 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
5975
5976 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 &&
5977 pcysta->except_cnt == 0 &&
5978 !pfwinfo->len_mismch && !pfwinfo->fver_mismch)
5979 return;
5980
5981 seq_printf(m, " %-15s : ", "[error]");
5982
5983 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
5984 seq_printf(m,
5985 "overflow-cnt: %d, ",
5986 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
5987 }
5988
5989 if (pfwinfo->len_mismch) {
5990 seq_printf(m,
5991 "len-mismatch: 0x%x, ",
5992 pfwinfo->len_mismch);
5993 }
5994
5995 if (pfwinfo->fver_mismch) {
5996 seq_printf(m,
5997 "fver-mismatch: 0x%x, ",
5998 pfwinfo->fver_mismch);
5999 }
6000
6001 /* cycle statistics exceptions */
6002 if (pcysta->exception || pcysta->except_cnt) {
6003 seq_printf(m,
6004 "exception-type: 0x%x, exception-cnt = %d",
6005 pcysta->exception, pcysta->except_cnt);
6006 }
6007 seq_puts(m, "\n");
6008 }
6009
_show_fbtc_tdma(struct rtw89_dev * rtwdev,struct seq_file * m)6010 static void _show_fbtc_tdma(struct rtw89_dev *rtwdev, struct seq_file *m)
6011 {
6012 struct rtw89_btc *btc = &rtwdev->btc;
6013 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6014 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6015 struct rtw89_btc_fbtc_tdma *t = NULL;
6016 struct rtw89_btc_fbtc_slot *s = NULL;
6017 struct rtw89_btc_dm *dm = &btc->dm;
6018 u8 i, cnt = 0;
6019
6020 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
6021 if (!pcinfo->valid)
6022 return;
6023
6024 t = &pfwinfo->rpt_fbtc_tdma.finfo;
6025
6026 seq_printf(m,
6027 " %-15s : ", "[tdma_policy]");
6028 seq_printf(m,
6029 "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ",
6030 (u32)t->type,
6031 t->rxflctrl, t->txpause);
6032
6033 seq_printf(m,
6034 "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ",
6035 t->wtgle_n, t->leak_n, t->ext_ctrl);
6036
6037 seq_printf(m,
6038 "policy_type:%d",
6039 (u32)btc->policy_type);
6040
6041 s = pfwinfo->rpt_fbtc_slots.finfo.slot;
6042
6043 for (i = 0; i < CXST_MAX; i++) {
6044 if (dm->update_slot_map == BIT(CXST_MAX) - 1)
6045 break;
6046
6047 if (!(dm->update_slot_map & BIT(i)))
6048 continue;
6049
6050 if (cnt % 6 == 0)
6051 seq_printf(m,
6052 " %-15s : %d[%d/0x%x/%d]",
6053 "[slot_policy]",
6054 (u32)i,
6055 s[i].dur, s[i].cxtbl, s[i].cxtype);
6056 else
6057 seq_printf(m,
6058 ", %d[%d/0x%x/%d]",
6059 (u32)i,
6060 s[i].dur, s[i].cxtbl, s[i].cxtype);
6061 if (cnt % 6 == 5)
6062 seq_puts(m, "\n");
6063 cnt++;
6064 }
6065 seq_puts(m, "\n");
6066 }
6067
_show_fbtc_slots(struct rtw89_dev * rtwdev,struct seq_file * m)6068 static void _show_fbtc_slots(struct rtw89_dev *rtwdev, struct seq_file *m)
6069 {
6070 struct rtw89_btc *btc = &rtwdev->btc;
6071 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6072 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6073 struct rtw89_btc_fbtc_slots *pslots = NULL;
6074 struct rtw89_btc_fbtc_slot s;
6075 u8 i = 0;
6076
6077 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
6078 if (!pcinfo->valid)
6079 return;
6080
6081 pslots = &pfwinfo->rpt_fbtc_slots.finfo;
6082
6083 for (i = 0; i < CXST_MAX; i++) {
6084 s = pslots->slot[i];
6085 if (i % 6 == 0)
6086 seq_printf(m,
6087 " %-15s : %02d[%03d/0x%x/%d]",
6088 "[slot_list]",
6089 (u32)i,
6090 s.dur, s.cxtbl, s.cxtype);
6091 else
6092 seq_printf(m,
6093 ", %02d[%03d/0x%x/%d]",
6094 (u32)i,
6095 s.dur, s.cxtbl, s.cxtype);
6096 if (i % 6 == 5)
6097 seq_puts(m, "\n");
6098 }
6099 }
6100
_show_fbtc_cysta(struct rtw89_dev * rtwdev,struct seq_file * m)6101 static void _show_fbtc_cysta(struct rtw89_dev *rtwdev, struct seq_file *m)
6102 {
6103 struct rtw89_btc *btc = &rtwdev->btc;
6104 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6105 struct rtw89_btc_dm *dm = &btc->dm;
6106 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
6107 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6108 struct rtw89_btc_fbtc_cysta *pcysta_le32 = NULL;
6109 struct rtw89_btc_fbtc_cysta_cpu pcysta[1];
6110 union rtw89_btc_fbtc_rxflct r;
6111 u8 i, cnt = 0, slot_pair;
6112 u16 cycle, c_begin, c_end, store_index;
6113
6114 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
6115 if (!pcinfo->valid)
6116 return;
6117
6118 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo;
6119 rtw89_btc_fbtc_cysta_to_cpu(pcysta_le32, pcysta);
6120 seq_printf(m,
6121 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
6122 "[cycle_cnt]", pcysta->cycles, pcysta->bcn_cnt[CXBCN_ALL],
6123 pcysta->bcn_cnt[CXBCN_ALL_OK],
6124 pcysta->bcn_cnt[CXBCN_BT_SLOT],
6125 pcysta->bcn_cnt[CXBCN_BT_OK]);
6126
6127 for (i = 0; i < CXST_MAX; i++) {
6128 if (!pcysta->slot_cnt[i])
6129 continue;
6130 seq_printf(m,
6131 ", %d:%d", (u32)i, pcysta->slot_cnt[i]);
6132 }
6133
6134 if (dm->tdma_now.rxflctrl) {
6135 seq_printf(m,
6136 ", leak_rx:%d", pcysta->leakrx_cnt);
6137 }
6138
6139 if (pcysta->collision_cnt) {
6140 seq_printf(m,
6141 ", collision:%d", pcysta->collision_cnt);
6142 }
6143
6144 if (pcysta->skip_cnt) {
6145 seq_printf(m,
6146 ", skip:%d", pcysta->skip_cnt);
6147 }
6148 seq_puts(m, "\n");
6149
6150 seq_printf(m, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
6151 "[cycle_time]",
6152 pcysta->tavg_cycle[CXT_WL],
6153 pcysta->tavg_cycle[CXT_BT],
6154 pcysta->tavg_lk / 1000, pcysta->tavg_lk % 1000);
6155 seq_printf(m,
6156 ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
6157 pcysta->tmax_cycle[CXT_WL],
6158 pcysta->tmax_cycle[CXT_BT],
6159 pcysta->tmax_lk / 1000, pcysta->tmax_lk % 1000);
6160 seq_printf(m,
6161 ", maxdiff_t[wl:%d/bt:%d]\n",
6162 pcysta->tmaxdiff_cycle[CXT_WL],
6163 pcysta->tmaxdiff_cycle[CXT_BT]);
6164
6165 if (pcysta->cycles == 0)
6166 return;
6167
6168 /* 1 cycle record 1 wl-slot and 1 bt-slot */
6169 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
6170
6171 if (pcysta->cycles <= slot_pair)
6172 c_begin = 1;
6173 else
6174 c_begin = pcysta->cycles - slot_pair + 1;
6175
6176 c_end = pcysta->cycles;
6177
6178 for (cycle = c_begin; cycle <= c_end; cycle++) {
6179 cnt++;
6180 store_index = ((cycle - 1) % slot_pair) * 2;
6181
6182 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1)
6183 seq_printf(m,
6184 " %-15s : ->b%02d->w%02d", "[cycle_step]",
6185 pcysta->tslot_cycle[store_index],
6186 pcysta->tslot_cycle[store_index + 1]);
6187 else
6188 seq_printf(m,
6189 "->b%02d->w%02d",
6190 pcysta->tslot_cycle[store_index],
6191 pcysta->tslot_cycle[store_index + 1]);
6192 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
6193 seq_puts(m, "\n");
6194 }
6195
6196 if (a2dp->exist) {
6197 seq_printf(m,
6198 " %-15s : a2dp_ept:%d, a2dp_late:%d",
6199 "[a2dp_t_sta]",
6200 pcysta->a2dpept, pcysta->a2dpeptto);
6201
6202 seq_printf(m,
6203 ", avg_t:%d, max_t:%d",
6204 pcysta->tavg_a2dpept, pcysta->tmax_a2dpept);
6205 r.val = dm->tdma_now.rxflctrl;
6206
6207 if (r.type && r.tgln_n) {
6208 seq_printf(m,
6209 ", cycle[PSTDMA:%d/TDMA:%d], ",
6210 pcysta->cycles_a2dp[CXT_FLCTRL_ON],
6211 pcysta->cycles_a2dp[CXT_FLCTRL_OFF]);
6212
6213 seq_printf(m,
6214 "avg_t[PSTDMA:%d/TDMA:%d], ",
6215 pcysta->tavg_a2dp[CXT_FLCTRL_ON],
6216 pcysta->tavg_a2dp[CXT_FLCTRL_OFF]);
6217
6218 seq_printf(m,
6219 "max_t[PSTDMA:%d/TDMA:%d]",
6220 pcysta->tmax_a2dp[CXT_FLCTRL_ON],
6221 pcysta->tmax_a2dp[CXT_FLCTRL_OFF]);
6222 }
6223 seq_puts(m, "\n");
6224 }
6225 }
6226
_show_fbtc_nullsta(struct rtw89_dev * rtwdev,struct seq_file * m)6227 static void _show_fbtc_nullsta(struct rtw89_dev *rtwdev, struct seq_file *m)
6228 {
6229 struct rtw89_btc *btc = &rtwdev->btc;
6230 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6231 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6232 struct rtw89_btc_fbtc_cynullsta *ns = NULL;
6233 u8 i = 0;
6234
6235 if (!btc->dm.tdma_now.rxflctrl)
6236 return;
6237
6238 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
6239 if (!pcinfo->valid)
6240 return;
6241
6242 ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
6243
6244 seq_printf(m, " %-15s : ", "[null_sta]");
6245
6246 for (i = 0; i < 2; i++) {
6247 if (i != 0)
6248 seq_printf(m, ", null-%d", i);
6249 else
6250 seq_printf(m, "null-%d", i);
6251 seq_printf(m, "[ok:%d/", le32_to_cpu(ns->result[i][1]));
6252 seq_printf(m, "fail:%d/", le32_to_cpu(ns->result[i][0]));
6253 seq_printf(m, "on_time:%d/", le32_to_cpu(ns->result[i][2]));
6254 seq_printf(m, "retry:%d/", le32_to_cpu(ns->result[i][3]));
6255 seq_printf(m, "avg_t:%d.%03d/",
6256 le32_to_cpu(ns->avg_t[i]) / 1000,
6257 le32_to_cpu(ns->avg_t[i]) % 1000);
6258 seq_printf(m, "max_t:%d.%03d]",
6259 le32_to_cpu(ns->max_t[i]) / 1000,
6260 le32_to_cpu(ns->max_t[i]) % 1000);
6261 }
6262 seq_puts(m, "\n");
6263 }
6264
_show_fbtc_step(struct rtw89_dev * rtwdev,struct seq_file * m)6265 static void _show_fbtc_step(struct rtw89_dev *rtwdev, struct seq_file *m)
6266 {
6267 struct rtw89_btc *btc = &rtwdev->btc;
6268 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6269 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6270 struct rtw89_btc_fbtc_steps *pstep = NULL;
6271 u8 type, val, cnt = 0, state = 0;
6272 bool outloop = false;
6273 u16 i, diff_t, n_start = 0, n_stop = 0;
6274 u16 pos_old, pos_new;
6275
6276 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
6277 if (!pcinfo->valid)
6278 return;
6279
6280 pstep = &pfwinfo->rpt_fbtc_step.finfo;
6281 pos_old = le16_to_cpu(pstep->pos_old);
6282 pos_new = le16_to_cpu(pstep->pos_new);
6283
6284 if (pcinfo->req_fver != pstep->fver)
6285 return;
6286
6287 /* store step info by using ring instead of FIFO*/
6288 do {
6289 switch (state) {
6290 case 0:
6291 n_start = pos_old;
6292 if (pos_new >= pos_old)
6293 n_stop = pos_new;
6294 else
6295 n_stop = btc->ctrl.trace_step - 1;
6296
6297 state = 1;
6298 break;
6299 case 1:
6300 for (i = n_start; i <= n_stop; i++) {
6301 type = pstep->step[i].type;
6302 val = pstep->step[i].val;
6303 diff_t = le16_to_cpu(pstep->step[i].difft);
6304
6305 if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
6306 continue;
6307
6308 if (cnt % 10 == 0)
6309 seq_printf(m, " %-15s : ", "[steps]");
6310
6311 seq_printf(m, "-> %s(%02d)(%02d)",
6312 (type == CXSTEP_SLOT ? "SLT" :
6313 "EVT"), (u32)val, diff_t);
6314 if (cnt % 10 == 9)
6315 seq_puts(m, "\n");
6316 cnt++;
6317 }
6318
6319 state = 2;
6320 break;
6321 case 2:
6322 if (pos_new < pos_old && n_start != 0) {
6323 n_start = 0;
6324 n_stop = pos_new;
6325 state = 1;
6326 } else {
6327 outloop = true;
6328 }
6329 break;
6330 }
6331 } while (!outloop);
6332 }
6333
_show_fw_dm_msg(struct rtw89_dev * rtwdev,struct seq_file * m)6334 static void _show_fw_dm_msg(struct rtw89_dev *rtwdev, struct seq_file *m)
6335 {
6336 struct rtw89_btc *btc = &rtwdev->btc;
6337
6338 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
6339 return;
6340
6341 _show_error(rtwdev, m);
6342 _show_fbtc_tdma(rtwdev, m);
6343 _show_fbtc_slots(rtwdev, m);
6344 _show_fbtc_cysta(rtwdev, m);
6345 _show_fbtc_nullsta(rtwdev, m);
6346 _show_fbtc_step(rtwdev, m);
6347 }
6348
_show_mreg(struct rtw89_dev * rtwdev,struct seq_file * m)6349 static void _show_mreg(struct rtw89_dev *rtwdev, struct seq_file *m)
6350 {
6351 const struct rtw89_chip_info *chip = rtwdev->chip;
6352 struct rtw89_btc *btc = &rtwdev->btc;
6353 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6354 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6355 struct rtw89_btc_fbtc_mreg_val *pmreg = NULL;
6356 struct rtw89_btc_fbtc_gpio_dbg *gdbg = NULL;
6357 struct rtw89_btc_cx *cx = &btc->cx;
6358 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6359 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
6360 struct rtw89_mac_ax_gnt gnt[2] = {0};
6361 u8 i = 0, type = 0, cnt = 0;
6362 u32 val, offset;
6363
6364 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
6365 return;
6366
6367 seq_puts(m, "========== [HW Status] ==========\n");
6368
6369 seq_printf(m,
6370 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
6371 "[scoreboard]", wl->scbd, cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
6372 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
6373 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
6374
6375 /* To avoid I/O if WL LPS or power-off */
6376 if (!wl->status.map.lps && !wl->status.map.rf_off) {
6377 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
6378 if (val & (B_AX_GNT_BT_RFC_S0_SW_VAL |
6379 B_AX_GNT_BT_BB_S0_SW_VAL))
6380 gnt[0].gnt_bt = true;
6381 if (val & (B_AX_GNT_BT_RFC_S0_SW_CTRL |
6382 B_AX_GNT_BT_BB_S0_SW_CTRL))
6383 gnt[0].gnt_bt_sw_en = true;
6384 if (val & (B_AX_GNT_WL_RFC_S0_SW_VAL |
6385 B_AX_GNT_WL_BB_S0_SW_VAL))
6386 gnt[0].gnt_wl = true;
6387 if (val & (B_AX_GNT_WL_RFC_S0_SW_CTRL |
6388 B_AX_GNT_WL_BB_S0_SW_CTRL))
6389 gnt[0].gnt_wl_sw_en = true;
6390
6391 if (val & (B_AX_GNT_BT_RFC_S1_SW_VAL |
6392 B_AX_GNT_BT_BB_S1_SW_VAL))
6393 gnt[1].gnt_bt = true;
6394 if (val & (B_AX_GNT_BT_RFC_S1_SW_CTRL |
6395 B_AX_GNT_BT_BB_S1_SW_CTRL))
6396 gnt[1].gnt_bt_sw_en = true;
6397 if (val & (B_AX_GNT_WL_RFC_S1_SW_VAL |
6398 B_AX_GNT_WL_BB_S1_SW_VAL))
6399 gnt[1].gnt_wl = true;
6400 if (val & (B_AX_GNT_WL_RFC_S1_SW_CTRL |
6401 B_AX_GNT_WL_BB_S1_SW_CTRL))
6402 gnt[1].gnt_wl_sw_en = true;
6403
6404 seq_printf(m,
6405 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
6406 "[gnt_status]",
6407 (rtw89_mac_get_ctrl_path(rtwdev) ? "WL" : "BT"),
6408 (gnt[0].gnt_wl_sw_en ? "SW" : "HW"), gnt[0].gnt_wl,
6409 (gnt[0].gnt_bt_sw_en ? "SW" : "HW"), gnt[0].gnt_bt);
6410
6411 seq_printf(m, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
6412 (gnt[1].gnt_wl_sw_en ? "SW" : "HW"), gnt[1].gnt_wl,
6413 (gnt[1].gnt_bt_sw_en ? "SW" : "HW"), gnt[1].gnt_bt);
6414 }
6415
6416 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
6417 if (!pcinfo->valid) {
6418 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6419 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
6420 __func__);
6421 return;
6422 }
6423
6424 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo;
6425 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6426 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
6427 __func__, pmreg->reg_num);
6428
6429 for (i = 0; i < pmreg->reg_num; i++) {
6430 type = (u8)le16_to_cpu(chip->mon_reg[i].type);
6431 offset = le32_to_cpu(chip->mon_reg[i].offset);
6432 val = le32_to_cpu(pmreg->mreg_val[i]);
6433
6434 if (cnt % 6 == 0)
6435 seq_printf(m, " %-15s : %d_0x%04x=0x%08x",
6436 "[reg]", (u32)type, offset, val);
6437 else
6438 seq_printf(m, ", %d_0x%04x=0x%08x", (u32)type,
6439 offset, val);
6440 if (cnt % 6 == 5)
6441 seq_puts(m, "\n");
6442 cnt++;
6443 }
6444
6445 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
6446 if (!pcinfo->valid) {
6447 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6448 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n",
6449 __func__);
6450 return;
6451 }
6452
6453 gdbg = &pfwinfo->rpt_fbtc_gpio_dbg.finfo;
6454 if (!gdbg->en_map)
6455 return;
6456
6457 seq_printf(m, " %-15s : enable_map:0x%08x",
6458 "[gpio_dbg]", gdbg->en_map);
6459
6460 for (i = 0; i < BTC_DBG_MAX1; i++) {
6461 if (!(gdbg->en_map & BIT(i)))
6462 continue;
6463 seq_printf(m, ", %d->GPIO%d", (u32)i, gdbg->gpio_map[i]);
6464 }
6465 seq_puts(m, "\n");
6466 }
6467
_show_summary(struct rtw89_dev * rtwdev,struct seq_file * m)6468 static void _show_summary(struct rtw89_dev *rtwdev, struct seq_file *m)
6469 {
6470 struct rtw89_btc *btc = &rtwdev->btc;
6471 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
6472 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
6473 struct rtw89_btc_fbtc_rpt_ctrl *prptctrl = NULL;
6474 struct rtw89_btc_cx *cx = &btc->cx;
6475 struct rtw89_btc_dm *dm = &btc->dm;
6476 struct rtw89_btc_wl_info *wl = &cx->wl;
6477 struct rtw89_btc_bt_info *bt = &cx->bt;
6478 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
6479 u8 i;
6480
6481 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
6482 return;
6483
6484 seq_puts(m, "========== [Statistics] ==========\n");
6485
6486 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
6487 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
6488 prptctrl = &pfwinfo->rpt_ctrl.finfo;
6489
6490 seq_printf(m,
6491 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
6492 "[summary]", pfwinfo->cnt_h2c,
6493 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt,
6494 pfwinfo->cnt_c2h, prptctrl->c2h_cnt);
6495
6496 seq_printf(m,
6497 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
6498 pfwinfo->event[BTF_EVNT_RPT], prptctrl->rpt_cnt,
6499 prptctrl->rpt_enable, dm->error.val);
6500
6501 if (dm->error.map.wl_fw_hang)
6502 seq_puts(m, " (WL FW Hang!!)");
6503 seq_puts(m, "\n");
6504 seq_printf(m,
6505 " %-15s : send_ok:%d, send_fail:%d, recv:%d",
6506 "[mailbox]", prptctrl->mb_send_ok_cnt,
6507 prptctrl->mb_send_fail_cnt, prptctrl->mb_recv_cnt);
6508
6509 seq_printf(m,
6510 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n",
6511 prptctrl->mb_a2dp_empty_cnt,
6512 prptctrl->mb_a2dp_flct_cnt,
6513 prptctrl->mb_a2dp_full_cnt);
6514
6515 seq_printf(m,
6516 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
6517 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
6518 cx->cnt_wl[BTC_WCNT_RFK_GO],
6519 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
6520 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
6521
6522 seq_printf(m,
6523 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
6524 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
6525 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
6526 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
6527 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
6528 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
6529
6530 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
6531 bt->rfk_info.map.timeout = 1;
6532 else
6533 bt->rfk_info.map.timeout = 0;
6534
6535 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
6536 } else {
6537 seq_printf(m,
6538 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
6539 "[summary]", pfwinfo->cnt_h2c,
6540 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
6541 pfwinfo->event[BTF_EVNT_RPT],
6542 btc->fwinfo.rpt_en_map);
6543 seq_puts(m, " (WL FW report invalid!!)\n");
6544 }
6545
6546 for (i = 0; i < BTC_NCNT_NUM; i++)
6547 cnt_sum += dm->cnt_notify[i];
6548
6549 seq_printf(m,
6550 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
6551 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
6552 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
6553
6554 seq_printf(m,
6555 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
6556 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
6557 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
6558 cnt[BTC_NCNT_WL_STA]);
6559
6560 seq_printf(m,
6561 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
6562 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
6563 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
6564 cnt[BTC_NCNT_SPECIAL_PACKET]);
6565
6566 seq_printf(m,
6567 "timer=%d, control=%d, customerize=%d\n",
6568 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
6569 cnt[BTC_NCNT_CUSTOMERIZE]);
6570 }
6571
rtw89_btc_dump_info(struct rtw89_dev * rtwdev,struct seq_file * m)6572 void rtw89_btc_dump_info(struct rtw89_dev *rtwdev, struct seq_file *m)
6573 {
6574 struct rtw89_fw_suit *fw_suit = &rtwdev->fw.normal;
6575 struct rtw89_btc *btc = &rtwdev->btc;
6576 struct rtw89_btc_cx *cx = &btc->cx;
6577 struct rtw89_btc_bt_info *bt = &cx->bt;
6578
6579 seq_puts(m, "=========================================\n");
6580 seq_printf(m, "WL FW / BT FW %d.%d.%d.%d / NA\n",
6581 fw_suit->major_ver, fw_suit->minor_ver,
6582 fw_suit->sub_ver, fw_suit->sub_idex);
6583 seq_printf(m, "manual %d\n", btc->ctrl.manual);
6584
6585 seq_puts(m, "=========================================\n");
6586
6587 seq_printf(m, "\n\r %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)",
6588 "[bt_info]",
6589 bt->raw_info[2], bt->raw_info[3],
6590 bt->raw_info[4], bt->raw_info[5],
6591 bt->raw_info[6], bt->raw_info[7],
6592 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
6593 cx->cnt_bt[BTC_BCNT_INFOUPDATE],
6594 cx->cnt_bt[BTC_BCNT_INFOSAME]);
6595
6596 seq_puts(m, "\n=========================================\n");
6597
6598 _show_cx_info(rtwdev, m);
6599 _show_wl_info(rtwdev, m);
6600 _show_bt_info(rtwdev, m);
6601 _show_dm_info(rtwdev, m);
6602 _show_fw_dm_msg(rtwdev, m);
6603 _show_mreg(rtwdev, m);
6604 _show_summary(rtwdev, m);
6605 }
6606