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