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