1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2019-2020 Realtek Corporation
3 */
4
5 #include "chan.h"
6 #include "coex.h"
7 #include "debug.h"
8 #include "fw.h"
9 #include "mac.h"
10 #include "phy.h"
11 #include "ps.h"
12 #include "reg.h"
13
14 #define RTW89_COEX_VERSION 0x09180113
15 #define FCXDEF_STEP 50 /* MUST <= FCXMAX_STEP and match with wl fw*/
16 #define BTC_E2G_LIMIT_DEF 80
17
18 enum btc_fbtc_tdma_template {
19 CXTD_OFF = 0x0,
20 CXTD_OFF_B2,
21 CXTD_OFF_EXT,
22 CXTD_FIX,
23 CXTD_PFIX,
24 CXTD_AUTO,
25 CXTD_PAUTO,
26 CXTD_AUTO2,
27 CXTD_PAUTO2,
28 CXTD_MAX,
29 };
30
31 enum btc_fbtc_tdma_type {
32 CXTDMA_OFF = 0x0,
33 CXTDMA_FIX = 0x1,
34 CXTDMA_AUTO = 0x2,
35 CXTDMA_AUTO2 = 0x3,
36 CXTDMA_MAX
37 };
38
39 enum btc_fbtc_tdma_rx_flow_ctrl {
40 CXFLC_OFF = 0x0,
41 CXFLC_NULLP = 0x1,
42 CXFLC_QOSNULL = 0x2,
43 CXFLC_CTS = 0x3,
44 CXFLC_MAX
45 };
46
47 enum btc_fbtc_tdma_wlan_tx_pause {
48 CXTPS_OFF = 0x0, /* no wl tx pause*/
49 CXTPS_ON = 0x1,
50 CXTPS_MAX
51 };
52
53 enum btc_mlme_state {
54 MLME_NO_LINK,
55 MLME_LINKING,
56 MLME_LINKED,
57 };
58
59 struct btc_fbtc_1slot {
60 u8 fver;
61 u8 sid; /* slot id */
62 struct rtw89_btc_fbtc_slot slot;
63 } __packed;
64
65 static const struct rtw89_btc_fbtc_tdma t_def[] = {
66 [CXTD_OFF] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
67 [CXTD_OFF_B2] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 1, 0, 0},
68 [CXTD_OFF_EXT] = { CXTDMA_OFF, CXFLC_OFF, CXTPS_OFF, 0, 0, 2, 0, 0},
69 [CXTD_FIX] = { CXTDMA_FIX, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
70 [CXTD_PFIX] = { CXTDMA_FIX, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0},
71 [CXTD_AUTO] = { CXTDMA_AUTO, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
72 [CXTD_PAUTO] = { CXTDMA_AUTO, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0},
73 [CXTD_AUTO2] = {CXTDMA_AUTO2, CXFLC_OFF, CXTPS_OFF, 0, 0, 0, 0, 0},
74 [CXTD_PAUTO2] = {CXTDMA_AUTO2, CXFLC_NULLP, CXTPS_ON, 0, 5, 0, 0, 0}
75 };
76
77 #define __DEF_FBTC_SLOT(__dur, __cxtbl, __cxtype) \
78 { .dur = cpu_to_le16(__dur), .cxtbl = cpu_to_le32(__cxtbl), \
79 .cxtype = cpu_to_le16(__cxtype),}
80
81 static const struct rtw89_btc_fbtc_slot s_def[] = {
82 [CXST_OFF] = __DEF_FBTC_SLOT(100, 0x55555555, SLOT_MIX),
83 [CXST_B2W] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_ISO),
84 [CXST_W1] = __DEF_FBTC_SLOT(70, 0xea5a5a5a, SLOT_ISO),
85 [CXST_W2] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO),
86 [CXST_W2B] = __DEF_FBTC_SLOT(15, 0xea5a5a5a, SLOT_ISO),
87 [CXST_B1] = __DEF_FBTC_SLOT(250, 0xe5555555, SLOT_MIX),
88 [CXST_B2] = __DEF_FBTC_SLOT(7, 0xea5a5a5a, SLOT_MIX),
89 [CXST_B3] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX),
90 [CXST_B4] = __DEF_FBTC_SLOT(50, 0xe5555555, SLOT_MIX),
91 [CXST_LK] = __DEF_FBTC_SLOT(20, 0xea5a5a5a, SLOT_ISO),
92 [CXST_BLK] = __DEF_FBTC_SLOT(500, 0x55555555, SLOT_MIX),
93 [CXST_E2G] = __DEF_FBTC_SLOT(5, 0xea5a5a5a, SLOT_MIX),
94 [CXST_E5G] = __DEF_FBTC_SLOT(5, 0xffffffff, SLOT_ISO),
95 [CXST_EBT] = __DEF_FBTC_SLOT(5, 0xe5555555, SLOT_MIX),
96 [CXST_ENULL] = __DEF_FBTC_SLOT(5, 0x55555555, SLOT_MIX),
97 [CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX),
98 [CXST_W1FDD] = __DEF_FBTC_SLOT(50, 0xffffffff, SLOT_ISO),
99 [CXST_B1FDD] = __DEF_FBTC_SLOT(50, 0xffffdfff, SLOT_ISO),
100 };
101
102 static const u32 cxtbl[] = {
103 0xffffffff, /* 0 */
104 0xaaaaaaaa, /* 1 */
105 0xe5555555, /* 2 */
106 0xee555555, /* 3 */
107 0xd5555555, /* 4 */
108 0x5a5a5a5a, /* 5 */
109 0xfa5a5a5a, /* 6 */
110 0xda5a5a5a, /* 7 */
111 0xea5a5a5a, /* 8 */
112 0x6a5a5aaa, /* 9 */
113 0x6a5a6a5a, /* 10 */
114 0x6a5a6aaa, /* 11 */
115 0x6afa5afa, /* 12 */
116 0xaaaa5aaa, /* 13 */
117 0xaaffffaa, /* 14 */
118 0xaa5555aa, /* 15 */
119 0xfafafafa, /* 16 */
120 0xffffddff, /* 17 */
121 0xdaffdaff, /* 18 */
122 0xfafadafa, /* 19 */
123 0xea6a6a6a, /* 20 */
124 0xea55556a, /* 21 */
125 0xaafafafa, /* 22 */
126 0xfafaaafa, /* 23 */
127 0xfafffaff, /* 24 */
128 0xea6a5a5a, /* 25 */
129 0xfaff5aff, /* 26 */
130 0xffffdfff, /* 27 */
131 0xe6555555, /* 28 */
132 };
133
134 static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
135 /* firmware version must be in decreasing order for each chip */
136 {RTL8922D, RTW89_FW_VER_CODE(0, 35, 111, 0),
137 .fcxbtcrpt = 11, .fcxtdma = 8, .fcxslots = 7, .fcxcysta = 8,
138 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8,
139 .fcxbtver = 8, .fcxbtscan = 8, .fcxbtafh = 8, .fcxbtdevinfo = 8,
140 .fwlrole = 10, .frptmap = 5, .fcxctrl = 9, .fcxinit = 11,
141 .fwevntrptl = 1, .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800,
142 .max_role_num = 6, .fcxosi = 6, .fcxmlo = 2, .bt_desired = 8,
143 .fcxtrx = 9,
144 },
145 {RTL8922D, RTW89_FW_VER_CODE(0, 35, 94, 0),
146 .fcxbtcrpt = 11, .fcxtdma = 8, .fcxslots = 7, .fcxcysta = 8,
147 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8,
148 .fcxbtver = 8, .fcxbtscan = 8, .fcxbtafh = 8, .fcxbtdevinfo = 8,
149 .fwlrole = 10, .frptmap = 5, .fcxctrl = 9, .fcxinit = 10,
150 .fwevntrptl = 1, .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800,
151 .max_role_num = 6, .fcxosi = 6, .fcxmlo = 2, .bt_desired = 8,
152 .fcxtrx = 9,
153 },
154 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 133, 0),
155 .fcxbtcrpt = 9, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
156 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8,
157 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
158 .fwlrole = 7, .frptmap = 5, .fcxctrl = 7, .fcxinit = 107,
159 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 103, .info_buf = 1800,
160 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
161 .fcxtrx = 107,
162 },
163 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 122, 0),
164 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
165 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
166 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
167 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
168 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 1, .info_buf = 1800,
169 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
170 .fcxtrx = 0,
171 },
172 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 90, 0),
173 .fcxbtcrpt = 7, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
174 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
175 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
176 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
177 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 1, .info_buf = 1800,
178 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
179 .fcxtrx = 0,
180 },
181 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 111, 0),
182 .fcxbtcrpt = 11, .fcxtdma = 8, .fcxslots = 7, .fcxcysta = 8,
183 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8,
184 .fcxbtver = 8, .fcxbtscan = 8, .fcxbtafh = 8, .fcxbtdevinfo = 8,
185 .fwlrole = 10, .frptmap = 5, .fcxctrl = 9, .fcxinit = 11,
186 .fwevntrptl = 1, .fwc2hfunc = 4, .drvinfo_ver = 3, .info_buf = 1800,
187 .max_role_num = 6, .fcxosi = 6, .fcxmlo = 2, .bt_desired = 8,
188 .fcxtrx = 9,
189 },
190 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 71, 0),
191 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
192 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
193 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
194 .fwlrole = 8, .frptmap = 4, .fcxctrl = 7, .fcxinit = 7,
195 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_ver = 3, .info_buf = 1800,
196 .max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9,
197 .fcxtrx = 7,
198 },
199 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 63, 0),
200 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
201 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
202 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
203 .fwlrole = 8, .frptmap = 4, .fcxctrl = 7, .fcxinit = 7,
204 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_ver = 2, .info_buf = 1800,
205 .max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9,
206 .fcxtrx = 0,
207 },
208 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0),
209 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
210 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
211 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
212 .fwlrole = 8, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
213 .fwevntrptl = 1, .fwc2hfunc = 1, .drvinfo_ver = 1, .info_buf = 1800,
214 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
215 .fcxtrx = 0,
216 },
217 {RTL8851B, RTW89_FW_VER_CODE(0, 29, 133, 0),
218 .fcxbtcrpt = 9, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
219 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8,
220 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
221 .fwlrole = 7, .frptmap = 5, .fcxctrl = 7, .fcxinit = 107,
222 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 103, .info_buf = 1800,
223 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
224 .fcxtrx = 107,
225 },
226 {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0),
227 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5,
228 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1,
229 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1,
230 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
231 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1800,
232 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
233 .fcxtrx = 0,
234 },
235 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 97, 0),
236 .fcxbtcrpt = 4, .fcxtdma = 4, .fcxslots = 2, .fcxcysta = 105,
237 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1,
238 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1,
239 .fwlrole = 101, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
240 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280,
241 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
242 .fcxtrx = 107,
243 },
244 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0),
245 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
246 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
247 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
248 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
249 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280,
250 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
251 .fcxtrx = 0,
252 },
253 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0),
254 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
255 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
256 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
257 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0,
258 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280,
259 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
260 .fcxtrx = 0,
261 },
262 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0),
263 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
264 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
265 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
266 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0,
267 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280,
268 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
269 .fcxtrx = 0,
270 },
271 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 133, 0),
272 .fcxbtcrpt = 9, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
273 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 8,
274 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
275 .fwlrole = 7, .frptmap = 105, .fcxctrl = 7, .fcxinit = 107,
276 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 103, .info_buf = 1800,
277 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
278 .fcxtrx = 107,
279 },
280 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 122, 0),
281 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
282 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
283 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
284 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
285 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_ver = 1, .info_buf = 1800,
286 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
287 .fcxtrx = 0,
288 },
289 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0),
290 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5,
291 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1,
292 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1,
293 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
294 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1800,
295 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
296 .fcxtrx = 0,
297 },
298 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0),
299 .fcxbtcrpt = 5, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 4,
300 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
301 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
302 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
303 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1800,
304 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
305 .fcxtrx = 0,
306 },
307 {RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0),
308 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
309 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
310 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
311 .fwlrole = 1, .frptmap = 1, .fcxctrl = 1, .fcxinit = 0,
312 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1280,
313 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
314 .fcxtrx = 0,
315 },
316 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0),
317 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
318 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
319 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
320 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
321 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_ver = 0, .info_buf = 1280,
322 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
323 .fcxtrx = 0,
324 },
325 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0),
326 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2,
327 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1,
328 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
329 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0,
330 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_ver = 0, .info_buf = 1024,
331 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
332 .fcxtrx = 0,
333 },
334
335 /* keep it to be the last as default entry */
336 {0, RTW89_FW_VER_CODE(0, 0, 0, 0),
337 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2,
338 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1,
339 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
340 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0,
341 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_ver = 0, .info_buf = 1024,
342 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
343 .fcxtrx = 0,
344 },
345 };
346
347 #define RTW89_DEFAULT_BTC_VER_IDX (ARRAY_SIZE(rtw89_btc_ver_defs) - 1)
348
349 static const union rtw89_btc_wl_state_map btc_scanning_map = {
350 .map = {
351 .scan = 1,
352 .dhcp = 1,
353 .roaming = 1,
354 .transacting = 1,
355 ._4way = 1,
356 .handshake = 1,
357 },
358 };
359
chip_id_to_bt_rom_code_id(u32 id)360 static u32 chip_id_to_bt_rom_code_id(u32 id)
361 {
362 switch (id) {
363 case RTL8852A:
364 case RTL8852B:
365 case RTL8852C:
366 case RTL8852BT:
367 return 0x8852;
368 case RTL8851B:
369 return 0x8851;
370 case RTL8922A:
371 case RTL8922D:
372 return 0x8922;
373 default:
374 return 0;
375 }
376 }
377
378 #define CASE_BTC_MLME_STATE(e) case MLME_##e: return #e
379
id_to_mlme_state(u32 id)380 static const char *id_to_mlme_state(u32 id)
381 {
382 switch (id) {
383 CASE_BTC_MLME_STATE(NO_LINK);
384 CASE_BTC_MLME_STATE(LINKING);
385 CASE_BTC_MLME_STATE(LINKED);
386 default:
387 return "unknown";
388 }
389 }
390
chip_id_str(u32 id)391 static char *chip_id_str(u32 id)
392 {
393 switch (id) {
394 case RTL8852A:
395 return "RTL8852A";
396 case RTL8852B:
397 return "RTL8852B";
398 case RTL8852C:
399 return "RTL8852C";
400 case RTL8852BT:
401 return "RTL8852BT";
402 case RTL8851B:
403 return "RTL8851B";
404 case RTL8922A:
405 return "RTL8922A";
406 case RTL8922D:
407 return "RTL8922D";
408 default:
409 return "UNKNOWN";
410 }
411 }
412
413 struct rtw89_btc_btf_tlv {
414 u8 type;
415 u8 len;
416 u8 val[];
417 } __packed;
418
419 struct rtw89_btc_btf_tlv_v7 {
420 u8 type;
421 u8 ver;
422 u8 len;
423 u8 val[];
424 } __packed;
425
426 enum btc_btf_set_report_en {
427 RPT_EN_TDMA,
428 RPT_EN_CYCLE,
429 RPT_EN_MREG,
430 RPT_EN_BT_VER_INFO,
431 RPT_EN_BT_SCAN_INFO,
432 RPT_EN_BT_DEVICE_INFO,
433 RPT_EN_BT_AFH_MAP,
434 RPT_EN_BT_AFH_MAP_LE,
435 RPT_EN_BT_TX_PWR_LVL,
436 RPT_EN_FW_STEP_INFO,
437 RPT_EN_TEST,
438 RPT_EN_WL_ALL,
439 RPT_EN_BT_ALL,
440 RPT_EN_ALL,
441 RPT_EN_MONITER,
442 };
443
444 struct rtw89_btc_btf_set_report_v1 {
445 u8 fver;
446 __le32 enable;
447 __le32 para;
448 } __packed;
449
450 struct rtw89_btc_btf_set_report_v8 {
451 u8 type;
452 u8 fver;
453 u8 len;
454 __le32 map;
455 } __packed;
456
457 union rtw89_fbtc_rtp_ctrl {
458 struct rtw89_btc_btf_set_report_v1 v1;
459 struct rtw89_btc_btf_set_report_v8 v8;
460 };
461
462 #define BTF_SET_SLOT_TABLE_VER 1
463 struct rtw89_btc_btf_set_slot_table {
464 u8 fver;
465 u8 tbl_num;
466 struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num);
467 } __packed;
468
469 struct rtw89_btc_btf_set_slot_table_v7 {
470 u8 type;
471 u8 ver;
472 u8 len;
473 struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX];
474 } __packed;
475
476 struct rtw89_btc_btf_set_mon_reg_v1 {
477 u8 fver;
478 u8 reg_num;
479 struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num);
480 } __packed;
481
482 struct rtw89_btc_btf_set_mon_reg_v7 {
483 u8 type;
484 u8 fver;
485 u8 len;
486 struct rtw89_btc_fbtc_mreg regs[] __counted_by(len);
487 } __packed;
488
489 union rtw89_fbtc_set_mon_reg {
490 struct rtw89_btc_btf_set_mon_reg_v1 v1;
491 struct rtw89_btc_btf_set_mon_reg_v7 v7;
492 } __packed;
493
494 enum btc_btf_set_cx_policy {
495 CXPOLICY_TDMA = 0x0,
496 CXPOLICY_SLOT = 0x1,
497 CXPOLICY_TYPE = 0x2,
498 CXPOLICY_MAX,
499 };
500
501 enum btc_b2w_scoreboard {
502 BTC_BSCB_ACT = BIT(0),
503 BTC_BSCB_ON = BIT(1),
504 BTC_BSCB_WHQL = BIT(2),
505 BTC_BSCB_BT_S1 = BIT(3),
506 BTC_BSCB_A2DP_ACT = BIT(4),
507 BTC_BSCB_RFK_RUN = BIT(5),
508 BTC_BSCB_RFK_REQ = BIT(6),
509 BTC_BSCB_LPS = BIT(7),
510 BTC_BSCB_BT_LNAB0 = BIT(8),
511 BTC_BSCB_BT_LNAB1 = BIT(10),
512 BTC_BSCB_WLRFK = BIT(11),
513 BTC_BSCB_BT_HILNA = BIT(13),
514 BTC_BSCB_BT_HILNA_56G = BIT(14),
515 BTC_BSCB_CTCODE = BIT(15),
516 BTC_BSCB_BT_CONNECT = BIT(16),
517 BTC_BSCB_BT_CONNECT_56G = BIT(17),
518 BTC_BSCB_BT_LNAB0_56G = BIT(18),
519 BTC_BSCB_BT_LNAB1_56G = BIT(19),
520 BTC_BSCB_BT_15DOT4 = BIT(24),
521 BTC_BSCB_BT_PROTECT = BIT(27),
522 BTC_BSCB_PAN_ACT = BIT(28),
523 BTC_BSCB_HFP_ACT = BIT(29),
524 BTC_BSCB_PATCH_CODE = BIT(30),
525 BTC_BSCB_ALL = GENMASK(30, 0),
526 };
527
528 enum btc_phymap {
529 BTC_PHY_0 = BIT(0),
530 BTC_PHY_1 = BIT(1),
531 BTC_PHY_ALL = BIT(0) | BIT(1),
532 };
533
534 enum btc_cx_state_map {
535 BTC_WIDLE = 0,
536 BTC_WBUSY_BNOSCAN,
537 BTC_WBUSY_BSCAN,
538 BTC_WSCAN_BNOSCAN,
539 BTC_WSCAN_BSCAN,
540 BTC_WLINKING
541 };
542
543 enum btc_ant_phase {
544 BTC_ANT_WPOWERON = 0,
545 BTC_ANT_WINIT,
546 BTC_ANT_WONLY,
547 BTC_ANT_WOFF,
548 BTC_ANT_W2G,
549 BTC_ANT_FDD,
550 BTC_ANT_W25G,
551 BTC_ANT_FREERUN,
552 BTC_ANT_WRFK,
553 BTC_ANT_WRFK2,
554 BTC_ANT_PTA, /* for Multi-PTA, each hw-band has its own PTA */
555 BTC_ANT_MAX
556 };
557
558 enum btc_plt {
559 BTC_PLT_NONE = 0,
560 BTC_PLT_LTE_RX = BIT(0),
561 BTC_PLT_GNT_BT_TX = BIT(1),
562 BTC_PLT_GNT_BT_RX = BIT(2),
563 BTC_PLT_GNT_WL = BIT(3),
564 BTC_PLT_BT = BIT(1) | BIT(2),
565 BTC_PLT_ALL = 0xf
566 };
567
568 enum btc_cx_poicy_main_type {
569 BTC_CXP_OFF = 0,
570 BTC_CXP_OFFB,
571 BTC_CXP_OFFE,
572 BTC_CXP_FIX,
573 BTC_CXP_PFIX,
574 BTC_CXP_AUTO,
575 BTC_CXP_PAUTO,
576 BTC_CXP_AUTO2,
577 BTC_CXP_PAUTO2,
578 BTC_CXP_MANUAL,
579 BTC_CXP_USERDEF0,
580 BTC_CXP_MAIN_MAX
581 };
582
583 enum btc_bslot_length {
584 BTC_BSLOT_A2DP_HID = 60,
585 BTC_BSLOT_A2DP = 50,
586 BTC_BSLOT_A2DP_2 = 40,
587 BTC_BSLOT_INQ = 30,
588 BTC_BSLOT_IDLE = 20,
589 };
590
591 enum btc_cx_poicy_type {
592 /* TDMA off + pri: BT > WL */
593 BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0,
594
595 /* TDMA off + pri: WL > BT */
596 BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1,
597
598 /* TDMA off + pri: BT = WL */
599 BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2,
600
601 /* TDMA off + pri: BT = WL > BT_Lo */
602 BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3,
603
604 /* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */
605 BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4,
606
607 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
608 BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5,
609
610 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
611 BTC_CXP_OFF_EQ4 = (BTC_CXP_OFF << 8) | 6,
612
613 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
614 BTC_CXP_OFF_EQ5 = (BTC_CXP_OFF << 8) | 7,
615
616 /* TDMA off + pri: BT_Hi > WL > BT_Lo */
617 BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 8,
618
619 /* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
620 BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 9,
621
622 /* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
623 BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 10,
624
625 /* TDMA off + pri: WL_Hi-Tx = BT */
626 BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 11,
627
628 /* TDMA off + pri: WL > BT, Block-BT*/
629 BTC_CXP_OFF_WL2 = (BTC_CXP_OFF << 8) | 12,
630
631 /* TDMA off+Bcn-Protect + pri: BT_Hi > WL > BT_Lo */
632 BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
633
634 /* TDMA off+Bcn-Protect + pri: BT_Hi_Tx = WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
635 BTC_CXP_OFFB_BWB1 = (BTC_CXP_OFFB << 8) | 1,
636
637 /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
638 BTC_CXP_OFFB_BWB2 = (BTC_CXP_OFFB << 8) | 2,
639
640 /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx = BT*/
641 BTC_CXP_OFFB_BWB3 = (BTC_CXP_OFFB << 8) | 3,
642
643 /* TDMA off+Bcn-Protect + pri: BT > WL*/
644 BTC_CXP_OFFB_BWB4 = (BTC_CXP_OFFB << 8) | 4,
645
646 /* TDMA off + Ext-Ctrl + pri: default */
647 BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0,
648
649 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
650 BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1,
651
652 /* TDMA off + Ext-Ctrl + pri: default */
653 BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2,
654
655 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
656 BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3,
657
658 /* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */
659 BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4,
660
661 /* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */
662 BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5,
663
664 /* TDMA off + Ext-Ctrl + pri: default */
665 BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6,
666
667 /* TDMA Fix slot-0: W1:B1 = 30:30 */
668 BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0,
669
670 /* TDMA Fix slot-1: W1:B1 = 50:50 */
671 BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1,
672
673 /* TDMA Fix slot-2: W1:B1 = 20:30 */
674 BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2,
675
676 /* TDMA Fix slot-3: W1:B1 = 40:10 */
677 BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3,
678
679 /* TDMA Fix slot-4: W1:B1 = 70:10 */
680 BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4,
681
682 /* TDMA Fix slot-5: W1:B1 = 20:60 */
683 BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5,
684
685 /* TDMA Fix slot-6: W1:B1 = 30:60 */
686 BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6,
687
688 /* TDMA Fix slot-7: W1:B1 = 20:80 */
689 BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7,
690
691 /* TDMA Fix slot-8: W1:B1 = user-define */
692 BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8,
693
694 /* TDMA Fix slot-9: W1:B1 = 40:10 */
695 BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 9,
696
697 /* TDMA Fix slot-10: W1:B1 = 40:10 */
698 BTC_CXP_FIX_TD4010ISO_DL = (BTC_CXP_FIX << 8) | 10,
699
700 /* TDMA Fix slot-11: W1:B1 = 40:10 */
701 BTC_CXP_FIX_TD4010ISO_UL = (BTC_CXP_FIX << 8) | 11,
702
703 /* PS-TDMA Fix slot-0: W1:B1 = 30:30 */
704 BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0,
705
706 /* PS-TDMA Fix slot-1: W1:B1 = 50:50 */
707 BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1,
708
709 /* PS-TDMA Fix slot-2: W1:B1 = 20:30 */
710 BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2,
711
712 /* PS-TDMA Fix slot-3: W1:B1 = 20:60 */
713 BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3,
714
715 /* PS-TDMA Fix slot-4: W1:B1 = 30:70 */
716 BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4,
717
718 /* PS-TDMA Fix slot-5: W1:B1 = 20:80 */
719 BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5,
720
721 /* PS-TDMA Fix slot-6: W1:B1 = user-define */
722 BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6,
723
724 /* TDMA Auto slot-0: W1:B1 = 50:200 */
725 BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0,
726
727 /* TDMA Auto slot-1: W1:B1 = 60:200 */
728 BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1,
729
730 /* TDMA Auto slot-2: W1:B1 = 20:200 */
731 BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2,
732
733 /* TDMA Auto slot-3: W1:B1 = user-define */
734 BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3,
735
736 /* PS-TDMA Auto slot-0: W1:B1 = 50:200 */
737 BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0,
738
739 /* PS-TDMA Auto slot-1: W1:B1 = 60:200 */
740 BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1,
741
742 /* PS-TDMA Auto slot-2: W1:B1 = 20:200 */
743 BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2,
744
745 /* PS-TDMA Auto slot-3: W1:B1 = user-define */
746 BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3,
747
748 /* TDMA Auto slot2-0: W1:B4 = 30:50 */
749 BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0,
750
751 /* TDMA Auto slot2-1: W1:B4 = 30:70 */
752 BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1,
753
754 /* TDMA Auto slot2-2: W1:B4 = 50:50 */
755 BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2,
756
757 /* TDMA Auto slot2-3: W1:B4 = 60:60 */
758 BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3,
759
760 /* TDMA Auto slot2-4: W1:B4 = 20:80 */
761 BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4,
762
763 /* TDMA Auto slot2-5: W1:B4 = user-define */
764 BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5,
765
766 /* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */
767 BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0,
768
769 /* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */
770 BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1,
771
772 /* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */
773 BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2,
774
775 /* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */
776 BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3,
777
778 /* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */
779 BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4,
780
781 /* PS-TDMA Auto slot2-5: W1:B4 = user-define */
782 BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5,
783
784 BTC_CXP_MAX = 0xffff
785 };
786
787 enum btc_wl_rfk_result {
788 BTC_WRFK_REJECT = 0,
789 BTC_WRFK_ALLOW = 1,
790 };
791
792 enum btc_coex_info_map_en {
793 BTC_COEX_INFO_CX = BIT(0),
794 BTC_COEX_INFO_WL = BIT(1),
795 BTC_COEX_INFO_BT = BIT(2),
796 BTC_COEX_INFO_DM = BIT(3),
797 BTC_COEX_INFO_MREG = BIT(4),
798 BTC_COEX_INFO_SUMMARY = BIT(5),
799 BTC_COEX_INFO_ALL = GENMASK(7, 0),
800 };
801
802 #define BTC_CXP_MASK GENMASK(15, 8)
803
804 enum btc_w2b_scoreboard {
805 BTC_WSCB_ACTIVE = BIT(0),
806 BTC_WSCB_ON = BIT(1),
807 BTC_WSCB_SCAN = BIT(2),
808 BTC_WSCB_UNDERTEST = BIT(3),
809 BTC_WSCB_RXGAIN = BIT(4),
810 BTC_WSCB_5GHICH = BIT(6),
811 BTC_WSCB_WLBUSY = BIT(7),
812 BTC_WSCB_EXTFEM = BIT(8),
813 BTC_WSCB_TDMA = BIT(9),
814 BTC_WSCB_FIX2M = BIT(10),
815 BTC_WSCB_WLRFK = BIT(11),
816 BTC_WSCB_RXSCAN_PRI = BIT(12),
817 BTC_WSCB_BT_HILNA = BIT(13),
818 BTC_WSCB_BTLOG = BIT(14),
819 BTC_WSCB_CTCODE = BIT(15),
820 BTC_WSCB_RXGAIN_56G = BIT(16),
821 BTC_WSCB_BT_HILNA_56G = BIT(17),
822 BTC_WSCB_ALL = GENMASK(23, 0),
823 };
824
825 enum btc_wl_link_mode_v0 {
826 BTC_WLINK_V0_NOLINK = 0x0,
827 BTC_WLINK_V0_2G_STA,
828 BTC_WLINK_V0_2G_AP,
829 BTC_WLINK_V0_2G_GO,
830 BTC_WLINK_V0_2G_GC,
831 BTC_WLINK_V0_2G_SCC,
832 BTC_WLINK_V0_2G_MCC,
833 BTC_WLINK_V0_25G_MCC,
834 BTC_WLINK_V0_25G_DBCC,
835 BTC_WLINK_V0_5G,
836 BTC_WLINK_V0_2G_NAN,
837 BTC_WLINK_V0_OTHER,
838 BTC_WLINK_V0_MAX
839 };
840
841 enum btc_wl_link_mode_v1 {
842 BTC_WLINK_NOLINK = 0x0,
843 BTC_WLINK_STA,
844 BTC_WLINK_AP,
845 BTC_WLINK_GO,
846 BTC_WLINK_GC,
847 BTC_WLINK_SCC,
848 BTC_WLINK_SB_MCC,
849 BTC_WLINK_DB_MCC, /* 2+0/0+2 Dual-RF-band MCC */
850 BTC_WLINK_MAX
851 };
852
853 #define CASE_BTC_WL_LINK_MODE(e) case BTC_WLINK_## e: return #e
854
id_to_linkmode(u8 id)855 static const char *id_to_linkmode(u8 id)
856 {
857 switch (id) {
858 CASE_BTC_WL_LINK_MODE(NOLINK);
859 CASE_BTC_WL_LINK_MODE(STA);
860 CASE_BTC_WL_LINK_MODE(AP);
861 CASE_BTC_WL_LINK_MODE(GO);
862 CASE_BTC_WL_LINK_MODE(GC);
863 CASE_BTC_WL_LINK_MODE(SCC);
864 CASE_BTC_WL_LINK_MODE(SB_MCC);
865 CASE_BTC_WL_LINK_MODE(DB_MCC);
866 default:
867 return "unknown";
868 }
869 }
870
871 enum btc_wl_mrole_type {
872 BTC_WLMROLE_NONE = 0x0,
873 BTC_WLMROLE_STA_GC,
874 BTC_WLMROLE_STA_GC_NOA,
875 BTC_WLMROLE_STA_GO,
876 BTC_WLMROLE_STA_GO_NOA,
877 BTC_WLMROLE_STA_STA,
878 BTC_WLMROLE_MAX
879 };
880
881 enum btc_bt_hid_type {
882 BTC_HID_218 = BIT(0),
883 BTC_HID_418 = BIT(1),
884 BTC_HID_BLE = BIT(2),
885 BTC_HID_RCU = BIT(3),
886 BTC_HID_RCU_VOICE = BIT(4),
887 BTC_HID_OTHER_LEGACY = BIT(5)
888 };
889
890 enum btc_reset_module {
891 BTC_RESET_CX = BIT(0),
892 BTC_RESET_DM = BIT(1),
893 BTC_RESET_CTRL = BIT(2),
894 BTC_RESET_CXDM = BIT(0) | BIT(1),
895 BTC_RESET_BTINFO = BIT(3),
896 BTC_RESET_MDINFO = BIT(4),
897 BTC_RESET_BT_PSD_DM = BIT(5),
898 BTC_RESET_BTINFO2 = BIT(6),
899 BTC_RESET_ALL = GENMASK(7, 0),
900 };
901
902 enum btc_gnt_state {
903 BTC_GNT_HW = 0,
904 BTC_GNT_SW_LO,
905 BTC_GNT_SW_HI,
906 BTC_GNT_MAX,
907
908 BTC_GNT_SET_SKIP = 0xff,
909 };
910
911 enum btc_ctr_path {
912 BTC_CTRL_BY_BT = 0,
913 BTC_CTRL_BY_WL
914 };
915
916 enum btc_wlact_state {
917 BTC_WLACT_HW = 0,
918 BTC_WLACT_SW_LO,
919 BTC_WLACT_SW_HI,
920 BTC_WLACT_MAX,
921 };
922
923 enum btc_wl_max_tx_time {
924 BTC_MAX_TX_TIME_L1 = 500,
925 BTC_MAX_TX_TIME_L2 = 1000,
926 BTC_MAX_TX_TIME_L3 = 2000,
927 BTC_MAX_TX_TIME_DEF = 5280
928 };
929
930 enum btc_wl_max_tx_retry {
931 BTC_MAX_TX_RETRY_L1 = 7,
932 BTC_MAX_TX_RETRY_L2 = 15,
933 BTC_MAX_TX_RETRY_DEF = 31,
934 };
935
936 enum btc_reason_and_action {
937 BTC_RSN_NONE,
938 BTC_RSN_NTFY_INIT,
939 BTC_RSN_NTFY_SWBAND,
940 BTC_RSN_NTFY_WL_STA,
941 BTC_RSN_NTFY_RADIO_STATE,
942 BTC_RSN_UPDATE_BT_SCBD,
943 BTC_RSN_NTFY_WL_RFK,
944 BTC_RSN_UPDATE_BT_INFO,
945 BTC_RSN_NTFY_SCAN_START,
946 BTC_RSN_NTFY_SCAN_FINISH,
947 BTC_RSN_NTFY_SPECIFIC_PACKET,
948 BTC_RSN_NTFY_POWEROFF,
949 BTC_RSN_NTFY_ROLE_INFO,
950 BTC_RSN_CMD_SET_COEX,
951 BTC_RSN_ACT1_WORK,
952 BTC_RSN_BT_DEVINFO_WORK,
953 BTC_RSN_RFK_CHK_WORK,
954 BTC_RSN_UPDATE_BT_LEAUDINFO,
955 BTC_RSN_NUM,
956 BTC_ACT_NONE = 100,
957 BTC_ACT_WL_ONLY,
958 BTC_ACT_WL_5G,
959 BTC_ACT_WL_OTHER,
960 BTC_ACT_WL_IDLE,
961 BTC_ACT_WL_NC,
962 BTC_ACT_WL_RFK,
963 BTC_ACT_WL_INIT,
964 BTC_ACT_WL_OFF,
965 BTC_ACT_FREERUN,
966 BTC_ACT_BT_WHQL,
967 BTC_ACT_BT_RFK,
968 BTC_ACT_BT_OFF,
969 BTC_ACT_BT_IDLE,
970 BTC_ACT_BT_HFP,
971 BTC_ACT_BT_HID,
972 BTC_ACT_BT_A2DP,
973 BTC_ACT_BT_A2DPSINK,
974 BTC_ACT_BT_PAN,
975 BTC_ACT_BT_A2DP_HID,
976 BTC_ACT_BT_A2DP_PAN,
977 BTC_ACT_BT_PAN_HID,
978 BTC_ACT_BT_A2DP_PAN_HID,
979 BTC_ACT_BT_BIS,
980 BTC_ACT_BT_CIS,
981 BTC_ACT_WL_25G_MCC,
982 BTC_ACT_WL_2G_MCC,
983 BTC_ACT_WL_2G_SCC,
984 BTC_ACT_WL_2G_AP,
985 BTC_ACT_WL_2G_GO,
986 BTC_ACT_WL_2G_GC,
987 BTC_ACT_WL_2G_NAN,
988 BTC_ACT_LAST,
989 BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE,
990 BTC_ACT_EXT_BIT = BIT(14),
991 BTC_POLICY_EXT_BIT = BIT(15),
992 };
993
994 #define BTC_FREERUN_ANTISO_MIN 30
995 #define BTC_TDMA_BTHID_MAX 2
996 #define BTC_BLINK_NOCONNECT 0
997 #define BTC_B1_MAX 250 /* unit ms */
998
999 static void _run_coex(struct rtw89_dev *rtwdev,
1000 enum btc_reason_and_action reason);
1001 static void _write_scbd(struct rtw89_dev *rtwdev, u8 bid, u32 val, bool state);
1002 static u8 _sned_h2c_w2bscbd(struct rtw89_dev *rtwdev, bool force_exec, u8 bid);
1003 static void _update_bt_scbd(struct rtw89_dev *rtwdev, u8 bid);
1004 static const char *id_to_h2c(u32 id);
1005
_reset_h2c_macro(struct rtw89_btc * btc)1006 static void _reset_h2c_macro(struct rtw89_btc *btc)
1007 {
1008 btc->hbuf_len = 0;
1009 btc->hbuf_cnt = 0;
1010 memset(btc->hbuf, 0, BTC_H2C_MAXLEN);
1011 }
1012
_send_fw_cmd(struct rtw89_dev * rtwdev,u8 h2c_class,u8 h2c_func,void * param,u16 len)1013 static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func,
1014 void *param, u16 len)
1015 {
1016 struct rtw89_btc *btc = &rtwdev->btc;
1017 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
1018 struct rtw89_btc_cx *cx = &btc->cx;
1019 struct rtw89_btc_wl_info *wl = &cx->wl;
1020 struct rtw89_btc_dm *dm = &btc->dm;
1021 u8 h2c_func_mask, bid = BTC_BT_1ST;
1022 u8 *buf = param;
1023 int ret;
1024
1025 if (len > BTC_H2C_MAXLEN || len == 0) {
1026 btc->fwinfo.cnt_h2c_fail++;
1027 dm->error.map.h2c_buffer_over = true;
1028 return -EINVAL;
1029 } else if (!wl->status.map.init_ok) {
1030 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1031 "[BTC], %s(): return by btc not init!!\n", __func__);
1032 pfwinfo->cnt_h2c_fail++;
1033 return -EINVAL;
1034 } else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF &&
1035 wl->status.map.rf_off == BTC_LPS_RF_OFF) ||
1036 (wl->status.map.lps_pre == BTC_LPS_RF_OFF &&
1037 wl->status.map.lps == BTC_LPS_RF_OFF)) {
1038 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1039 "[BTC], %s(): return by wl off!!\n", __func__);
1040 pfwinfo->cnt_h2c_fail++;
1041 return -EINVAL;
1042 }
1043
1044 h2c_func_mask = h2c_func & (~BT_H2C_FUNC_BT2ND);
1045 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)
1046 bid = !!(h2c_func & BT_H2C_FUNC_BT2ND);
1047
1048 if (btc->io_oflld_type != BTC_IO_OFLD_BTC_H2C || btc->cli_h2c_cmd ||
1049 h2c_func_mask == SET_H2C_MACRO ||
1050 (h2c_func_mask == SET_DRV_INFO && buf[0] == CXDRVINFO_TRX) ||
1051 (h2c_func_mask == SET_IOFLD_SCBD && dm->scbd_write_instant) ||
1052 h2c_func_mask == SET_BT_LNA_CONSTRAIN) {
1053 h2c_class = BTFC_SET;
1054
1055 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func,
1056 buf, len, false, true);
1057
1058 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1059 "[BTC], %s():class=%d, bt%d-func=%s, len=%d\n",
1060 __func__, h2c_class, bid,
1061 id_to_h2c(h2c_func_mask), len);
1062
1063 if (h2c_func_mask == SET_H2C_MACRO) {
1064 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1065 "[BTC], %s():Send H2C-MACRO cnt=%d, len=%d\n",
1066 __func__, btc->hbuf_cnt, btc->hbuf_len);
1067 _reset_h2c_macro(btc); /* clear H2C MACRO buffer */
1068 }
1069
1070 if (ret != 0) { /* Send H2C fail */
1071 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1072 "[BTC], %s():return by rtw_hal_mac_send_h2c\n",
1073 __func__);
1074 btc->fwinfo.cnt_h2c_fail++;
1075 return 0;
1076 }
1077
1078 btc->fwinfo.cnt_h2c++;
1079 return 0;
1080 } else { /* Fill H2C MACRO buffer(TLV format) temporarily */
1081 if (btc->hbuf_cnt == 0)
1082 _reset_h2c_macro(btc);
1083
1084 /* Type:1 byte, Length:2 Bytes, Data:len bytes */
1085 if (btc->hbuf_len + len + 3 >= BTC_H2C_MAXLEN) {
1086 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1087 "[BTC], %s():return by MACRO buf full(%d)\n",
1088 __func__, btc->hbuf_len + len + 3);
1089 btc->fwinfo.cnt_h2c_fail++;
1090 return 0;
1091 }
1092
1093 btc->hbuf[btc->hbuf_len] = h2c_func;
1094 btc->hbuf[btc->hbuf_len + 1] = len & GENMASK(7, 0);
1095 btc->hbuf[btc->hbuf_len + 2] = (len & GENMASK(15, 8)) >> 8;
1096
1097 memcpy(&btc->hbuf[btc->hbuf_len + 3], buf, len);
1098 btc->hbuf_len = btc->hbuf_len + len + 3;
1099 btc->hbuf_cnt++;
1100
1101 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1102 "[BTC], %s():Buffer H2C-MACRO cnt=%d/bt%d-func=%s/len=%d\n",
1103 __func__, btc->hbuf_cnt, bid,
1104 id_to_h2c(h2c_func_mask), len);
1105 }
1106
1107 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, buf, len,
1108 false, true);
1109 if (ret)
1110 pfwinfo->cnt_h2c_fail++;
1111 else
1112 pfwinfo->cnt_h2c++;
1113
1114 return ret;
1115 }
1116
1117 #define BTC_DEFAULT_SIR_THRES 51 /* dB, BT Pin - This = TDD/FDD swtch thres */
1118 #define BTC_FDDR_TP_SETUP_TIME 1 /* in second */
1119 #define BTC_FDDR_TP_HOLD_TIME 3 /* in second */
1120 #define BTC_FDDR_RX_LOW_RATE_THRES 4 /* low rate for TDD swotch */
1121
_reset_btc_var(struct rtw89_dev * rtwdev,u8 type)1122 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
1123 {
1124 struct rtw89_btc *btc = &rtwdev->btc;
1125 struct rtw89_btc_cx *cx = &btc->cx;
1126 const struct rtw89_btc_ver *ver = btc->ver;
1127 struct rtw89_btc_bt_info *bt0 = &cx->bt0;
1128 struct rtw89_btc_bt_info *bt1 = &cx->bt1;
1129 u8 i;
1130
1131 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
1132
1133 if (type & BTC_RESET_CX) {
1134 memset(cx, 0, sizeof(*cx));
1135 cx->bt_ext.max_tx_pwr = RTW89_BTC_BT_DEF_LE_TX_PWR;
1136 cx->bt_ext.ant_iso_to_wl = RTW89_BTC_DEFAULT_ANISO;
1137 }
1138
1139 if (type & BTC_RESET_BTINFO) {/* only for BT enable */
1140 memset(bt0, 0, sizeof(*bt0));
1141 bt0->link_info.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR;
1142 bt0->link_info_56g.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR;
1143 bt0->link_info.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR;
1144 bt0->link_info_56g.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR;
1145 bt0->ant_iso_to_wl = RTW89_BTC_DEFAULT_ANISO;
1146 } else if (type & BTC_RESET_BTINFO2) {
1147 memset(bt1, 0, sizeof(*bt1));
1148 bt1->link_info.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR;
1149 bt1->link_info_56g.bt_txpwr_desc.br_dbm = RTW89_BTC_BT_DEF_BR_TX_PWR;
1150 bt1->link_info.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR;
1151 bt1->link_info_56g.bt_txpwr_desc.le_dbm = RTW89_BTC_BT_DEF_LE_TX_PWR;
1152 bt1->ant_iso_to_wl = RTW89_BTC_DEFAULT_ANISO;
1153 }
1154
1155 if (type & BTC_RESET_CTRL) {
1156 memset(&btc->ctrl, 0, sizeof(btc->ctrl));
1157 btc->ctrl.trace_step = FCXDEF_STEP;
1158 }
1159
1160 /* Init Coex variables that are not zero */
1161 if (type & BTC_RESET_DM) {
1162 memset(&btc->dm, 0, sizeof(btc->dm));
1163
1164 /* set the slot_now table to original */
1165 btc->dm.tdma_now = t_def[CXTD_OFF];
1166 btc->dm.tdma = t_def[CXTD_OFF];
1167 if (ver->fcxslots >= 2) {
1168 for (i = 0; i < ARRAY_SIZE(s_def); i++) {
1169 btc->dm.slot.v7[i].dur = s_def[i].dur;
1170 btc->dm.slot.v7[i].cxtype = s_def[i].cxtype;
1171 btc->dm.slot.v7[i].cxtbl = s_def[i].cxtbl;
1172 }
1173 memcpy(&btc->dm.slot_now.v7, &btc->dm.slot.v7,
1174 sizeof(btc->dm.slot_now.v7));
1175 } else {
1176 memcpy(&btc->dm.slot_now.v1, s_def,
1177 sizeof(btc->dm.slot_now.v1));
1178 memcpy(&btc->dm.slot.v1, s_def,
1179 sizeof(btc->dm.slot.v1));
1180 }
1181
1182 btc->policy_len = 0;
1183 btc->bt_req_len[RTW89_PHY_0] = 0;
1184 btc->bt_req_len[RTW89_PHY_1] = 0;
1185 btc->hubmsg_cnt = 0;
1186
1187 btc->dm.coex_info_map = BTC_COEX_INFO_ALL;
1188 btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF;
1189 btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF;
1190 btc->dm.bt_slot_flood = BTC_B1_MAX;
1191 btc->dm.sir_thres = BTC_DEFAULT_SIR_THRES;
1192 btc->dm.fddr_info.tp_setup_time = BTC_FDDR_TP_SETUP_TIME;
1193 btc->dm.fddr_info.tp_hold_time = BTC_FDDR_TP_HOLD_TIME;
1194 btc->dm.fddr_info.wl_rx_rate_thres = BTC_FDDR_RX_LOW_RATE_THRES;
1195 btc->dm.fddt_info.type = BTC_FDDT_TYPE_AUTO;
1196
1197 btc->dm.wl_pre_agc_rb = BTC_PREAGC_NOTFOUND;
1198 btc->dm.wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_NOTFOUND;
1199 }
1200
1201 if (type & BTC_RESET_MDINFO) {
1202 memset(&btc->mdinfo, 0, sizeof(btc->mdinfo));
1203 btc->mdinfo.ant.isolation = RTW89_BTC_DEFAULT_ANISO;
1204 }
1205 }
1206
_search_reg_index(struct rtw89_dev * rtwdev,u8 mreg_num,u16 reg_type,u32 target)1207 static u8 _search_reg_index(struct rtw89_dev *rtwdev, u8 mreg_num, u16 reg_type, u32 target)
1208 {
1209 const struct rtw89_chip_info *chip = rtwdev->chip;
1210 u8 i;
1211
1212 for (i = 0; i < mreg_num; i++)
1213 if (le16_to_cpu(chip->mon_reg[i].type) == reg_type &&
1214 le32_to_cpu(chip->mon_reg[i].offset) == target) {
1215 return i;
1216 }
1217 return BTC_REG_NOTFOUND;
1218 }
1219
_get_reg_status(struct rtw89_dev * rtwdev,u8 type,u8 * val)1220 static void _get_reg_status(struct rtw89_dev *rtwdev, u8 type, u8 *val)
1221 {
1222 struct rtw89_btc *btc = &rtwdev->btc;
1223 const struct rtw89_btc_ver *ver = btc->ver;
1224 struct rtw89_btc_module *md = &btc->mdinfo;
1225 union rtw89_btc_fbtc_mreg_val *pmreg;
1226 u32 pre_agc_addr = R_BTC_BB_PRE_AGC_S1;
1227 u32 reg_val;
1228 u8 idx;
1229
1230 if (btc->btg_pos == RF_PATH_A)
1231 pre_agc_addr = R_BTC_BB_PRE_AGC_S0;
1232
1233 switch (type) {
1234 case BTC_CSTATUS_TXDIV_POS:
1235 if (md->bt0_sw_type == BTC_SWITCH_INTERNAL)
1236 *val = BTC_ANT_DIV_MAIN;
1237 break;
1238 case BTC_CSTATUS_RXDIV_POS:
1239 if (md->bt0_sw_type == BTC_SWITCH_INTERNAL)
1240 *val = BTC_ANT_DIV_MAIN;
1241 break;
1242 case BTC_CSTATUS_BB_GNT_MUX:
1243 reg_val = rtw89_phy_read32(rtwdev, R_BTC_BB_BTG_RX);
1244 *val = !(reg_val & B_BTC_BB_GNT_MUX);
1245 break;
1246 case BTC_CSTATUS_BB_GNT_MUX_MON:
1247 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
1248 return;
1249
1250 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
1251 if (ver->fcxmreg == 1) {
1252 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
1253 REG_BB, R_BTC_BB_BTG_RX);
1254 if (idx == BTC_REG_NOTFOUND) {
1255 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
1256 } else {
1257 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]);
1258 *val = !(reg_val & B_BTC_BB_GNT_MUX);
1259 }
1260 } else if (ver->fcxmreg == 2) {
1261 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
1262 REG_BB, R_BTC_BB_BTG_RX);
1263 if (idx == BTC_REG_NOTFOUND) {
1264 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
1265 } else {
1266 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]);
1267 *val = !(reg_val & B_BTC_BB_GNT_MUX);
1268 }
1269 }
1270 break;
1271 case BTC_CSTATUS_BB_PRE_AGC:
1272 reg_val = rtw89_phy_read32(rtwdev, pre_agc_addr);
1273 reg_val &= B_BTC_BB_PRE_AGC_MASK;
1274 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1275 break;
1276 case BTC_CSTATUS_BB_PRE_AGC_MON:
1277 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
1278 return;
1279
1280 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
1281 if (ver->fcxmreg == 1) {
1282 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
1283 REG_BB, pre_agc_addr);
1284 if (idx == BTC_REG_NOTFOUND) {
1285 *val = BTC_PREAGC_NOTFOUND;
1286 } else {
1287 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]) &
1288 B_BTC_BB_PRE_AGC_MASK;
1289 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1290 }
1291 } else if (ver->fcxmreg == 2) {
1292 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
1293 REG_BB, pre_agc_addr);
1294 if (idx == BTC_REG_NOTFOUND) {
1295 *val = BTC_PREAGC_NOTFOUND;
1296 } else {
1297 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]) &
1298 B_BTC_BB_PRE_AGC_MASK;
1299 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1300 }
1301 }
1302 break;
1303 default:
1304 break;
1305 }
1306 }
1307
1308 #define BTC_RPT_HDR_SIZE 3
1309 #define BTC_CHK_WLSLOT_DRIFT_MAX 15
1310 #define BTC_CHK_BTSLOT_DRIFT_MAX 15
1311 #define BTC_CHK_HANG_MAX 3
1312
_chk_btc_err(struct rtw89_dev * rtwdev,u8 type,u32 cnt)1313 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt)
1314 {
1315 struct rtw89_btc *btc = &rtwdev->btc;
1316 struct rtw89_btc_cx *cx = &btc->cx;
1317 struct rtw89_btc_bt_info *bt = &cx->bt0;
1318 struct rtw89_btc_wl_info *wl = &cx->wl;
1319 struct rtw89_btc_dm *dm = &btc->dm;
1320
1321 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1322 "[BTC], %s(): type:%d cnt:%d\n",
1323 __func__, type, cnt);
1324
1325 switch (type) {
1326 case BTC_DCNT_WL_FW_VER_MATCH:
1327 if ((wl->ver_info.fw_coex & 0xffff0000) !=
1328 rtwdev->chip->wlcx_desired) {
1329 wl->fw_ver_mismatch = true;
1330 dm->error.map.wl_ver_mismatch = true;
1331 } else {
1332 wl->fw_ver_mismatch = false;
1333 dm->error.map.wl_ver_mismatch = false;
1334 }
1335 break;
1336 case BTC_DCNT_RPT_HANG:
1337 if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map)
1338 dm->cnt_dm[BTC_DCNT_RPT_HANG]++;
1339 else
1340 dm->cnt_dm[BTC_DCNT_RPT_HANG] = 0;
1341
1342 if (dm->cnt_dm[BTC_DCNT_RPT_HANG] >= BTC_CHK_HANG_MAX)
1343 dm->error.map.wl_fw_hang = true;
1344 else
1345 dm->error.map.wl_fw_hang = false;
1346
1347 dm->cnt_dm[BTC_DCNT_RPT] = cnt;
1348 break;
1349 case BTC_DCNT_CYCLE_HANG:
1350 if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt &&
1351 (dm->tdma_now.type != CXTDMA_OFF ||
1352 dm->tdma_now.ext_ctrl == CXECTL_EXT))
1353 dm->cnt_dm[BTC_DCNT_CYCLE_HANG]++;
1354 else
1355 dm->cnt_dm[BTC_DCNT_CYCLE_HANG] = 0;
1356
1357 if (dm->cnt_dm[BTC_DCNT_CYCLE_HANG] >= BTC_CHK_HANG_MAX)
1358 dm->error.map.cycle_hang = true;
1359 else
1360 dm->error.map.cycle_hang = false;
1361
1362 dm->cnt_dm[BTC_DCNT_CYCLE] = cnt;
1363 break;
1364 case BTC_DCNT_W1_HANG:
1365 if (dm->cnt_dm[BTC_DCNT_W1] == cnt &&
1366 dm->tdma_now.type != CXTDMA_OFF)
1367 dm->cnt_dm[BTC_DCNT_W1_HANG]++;
1368 else
1369 dm->cnt_dm[BTC_DCNT_W1_HANG] = 0;
1370
1371 if (dm->cnt_dm[BTC_DCNT_W1_HANG] >= BTC_CHK_HANG_MAX)
1372 dm->error.map.w1_hang = true;
1373 else
1374 dm->error.map.w1_hang = false;
1375
1376 dm->cnt_dm[BTC_DCNT_W1] = cnt;
1377 break;
1378 case BTC_DCNT_B1_HANG:
1379 if (dm->cnt_dm[BTC_DCNT_B1] == cnt &&
1380 dm->tdma_now.type != CXTDMA_OFF)
1381 dm->cnt_dm[BTC_DCNT_B1_HANG]++;
1382 else
1383 dm->cnt_dm[BTC_DCNT_B1_HANG] = 0;
1384
1385 if (dm->cnt_dm[BTC_DCNT_B1_HANG] >= BTC_CHK_HANG_MAX)
1386 dm->error.map.b1_hang = true;
1387 else
1388 dm->error.map.b1_hang = false;
1389
1390 dm->cnt_dm[BTC_DCNT_B1] = cnt;
1391 break;
1392 case BTC_DCNT_E2G_HANG:
1393 if (dm->cnt_dm[BTC_DCNT_E2G] == cnt &&
1394 dm->tdma_now.ext_ctrl == CXECTL_EXT)
1395 dm->cnt_dm[BTC_DCNT_E2G_HANG]++;
1396 else
1397 dm->cnt_dm[BTC_DCNT_E2G_HANG] = 0;
1398
1399 if (dm->cnt_dm[BTC_DCNT_E2G_HANG] >= BTC_CHK_HANG_MAX)
1400 dm->error.map.wl_e2g_hang = true;
1401 else
1402 dm->error.map.wl_e2g_hang = false;
1403
1404 dm->cnt_dm[BTC_DCNT_E2G] = cnt;
1405 break;
1406 case BTC_DCNT_TDMA_NONSYNC:
1407 if (cnt != 0) /* if tdma not sync between drv/fw */
1408 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++;
1409 else
1410 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0;
1411
1412 if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX)
1413 dm->error.map.tdma_no_sync = true;
1414 else
1415 dm->error.map.tdma_no_sync = false;
1416 break;
1417 case BTC_DCNT_SLOT_NONSYNC:
1418 if (cnt != 0) /* if slot not sync between drv/fw */
1419 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++;
1420 else
1421 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0;
1422
1423 if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX)
1424 dm->error.map.slot_no_sync = true;
1425 else
1426 dm->error.map.slot_no_sync = false;
1427 break;
1428 case BTC_DCNT_BTTX_HANG:
1429 cnt = bt->bcnt[BTC_BCNT_LOPRI_TX];
1430
1431 if (cnt == 0 && bt->link_info.slave_role)
1432 dm->cnt_dm[BTC_DCNT_BTTX_HANG]++;
1433 else
1434 dm->cnt_dm[BTC_DCNT_BTTX_HANG] = 0;
1435
1436 if (dm->cnt_dm[BTC_DCNT_BTTX_HANG] >= BTC_CHK_HANG_MAX)
1437 dm->error.map.bt_tx_hang = true;
1438 else
1439 dm->error.map.bt_tx_hang = false;
1440 break;
1441 case BTC_DCNT_BTCNT_HANG:
1442 cnt = bt->bcnt[BTC_BCNT_HIPRI_RX] +
1443 bt->bcnt[BTC_BCNT_HIPRI_TX] +
1444 bt->bcnt[BTC_BCNT_LOPRI_RX] +
1445 bt->bcnt[BTC_BCNT_LOPRI_TX];
1446
1447 if (cnt == 0)
1448 dm->cnt_dm[BTC_DCNT_BTCNT_HANG]++;
1449 else
1450 dm->cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
1451 break;
1452 case BTC_DCNT_WL_SLOT_DRIFT:
1453 if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX)
1454 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++;
1455 else
1456 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0;
1457
1458 if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1459 dm->error.map.wl_slot_drift = true;
1460 else
1461 dm->error.map.wl_slot_drift = false;
1462 break;
1463 case BTC_DCNT_BT_SLOT_DRIFT:
1464 if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX)
1465 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++;
1466 else
1467 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0;
1468
1469 if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1470 dm->error.map.bt_slot_drift = true;
1471 else
1472 dm->error.map.bt_slot_drift = false;
1473
1474 break;
1475 case BTC_DCNT_WL_STA_NTFY:
1476 cnt = dm->cnt_notify[BTC_NCNT_WL_STA] -
1477 dm->cnt_notify[BTC_NCNT_WL_STA_LAST];
1478
1479 dm->cnt_notify[BTC_NCNT_WL_STA_LAST] =
1480 dm->cnt_notify[BTC_NCNT_WL_STA];
1481
1482 if (cnt == 0 &&
1483 (dm->tdd_bind.wl_link_mode != BTC_WLINK_NOLINK ||
1484 dm->fdd_bind.wl_link_mode != BTC_WLINK_NOLINK))
1485 dm->cnt_dm[BTC_DCNT_WL_STA_NTFY]++;
1486 else
1487 dm->cnt_dm[BTC_DCNT_WL_STA_NTFY] = 0;
1488
1489 if (dm->cnt_dm[BTC_DCNT_WL_STA_NTFY] >= BTC_CHK_HANG_MAX)
1490 dm->error.map.wl_no_sta_ntfy = true;
1491 else
1492 dm->error.map.wl_no_sta_ntfy = false;
1493 break;
1494 case BTC_DCNT_W2B_SCBD_NOSYNC:
1495 if (!(rtwdev->chip->para_ver & BTC_FEAT_MULTI_PTA))
1496 return; /* return if no-support W2B scbd readback */
1497
1498 if (wl->scbd_rb[BTC_BT_1ST] != wl->scbd[BTC_BT_1ST] ||
1499 wl->scbd_rb[BTC_BT_2ND] != wl->scbd[BTC_BT_2ND])
1500 dm->cnt_dm[BTC_DCNT_W2B_SCBD_NOSYNC]++;
1501 else
1502 dm->cnt_dm[BTC_DCNT_W2B_SCBD_NOSYNC] = 0;
1503
1504 if (dm->cnt_dm[BTC_DCNT_W2B_SCBD_NOSYNC] >= BTC_CHK_HANG_MAX)
1505 dm->error.map.w2b_scbd_no_sync = true;
1506 else
1507 dm->error.map.w2b_scbd_no_sync = false;
1508 break;
1509 }
1510 }
1511
_update_bt_report(struct rtw89_dev * rtwdev,u8 rpt_type,u8 * pfinfo)1512 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo)
1513 {
1514 struct rtw89_btc *btc = &rtwdev->btc;
1515 const struct rtw89_btc_ver *ver = btc->ver;
1516 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
1517 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
1518 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc;
1519 union rtw89_btc_fbtc_btver *pver = &btc->fwinfo.rpt_fbtc_btver.finfo;
1520 struct rtw89_btc_fbtc_btafh_v2 *pafh_v2 = NULL;
1521 struct rtw89_btc_fbtc_btafh_v7 *pafh_v7 = NULL;
1522 struct rtw89_btc_fbtc_btdevinfo *pdev = NULL;
1523 struct rtw89_btc_fbtc_btafh *pafh_v1 = NULL;
1524 struct rtw89_btc_fbtc_btscan_v1 *pscan_v1;
1525 struct rtw89_btc_fbtc_btscan_v2 *pscan_v2;
1526 struct rtw89_btc_fbtc_btscan_v7 *pscan_v7;
1527 bool scan_update = true;
1528 int i;
1529
1530 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1531 "[BTC], %s(): rpt_type:%d\n",
1532 __func__, rpt_type);
1533
1534 switch (rpt_type) {
1535 case BTC_RPT_TYPE_BT_VER:
1536 if (ver->fcxbtver == 8) {
1537 pver->v8 = *(struct rtw89_btc_fbtc_btver_v8 *)pfinfo;
1538 bt = pver->v8.bt_id ? &btc->cx.bt1 : &btc->cx.bt0;
1539 bt->ver_info.fw = le32_to_cpu(pver->v8.fw_ver);
1540 bt->ver_info.fw_coex = le32_get_bits(pver->v8.coex_ver,
1541 GENMASK(7, 0));
1542 bt->feature = le32_to_cpu(pver->v8.feature);
1543 } else if (ver->fcxbtver == 7) {
1544 pver->v7 = *(struct rtw89_btc_fbtc_btver_v7 *)pfinfo;
1545 bt->ver_info.fw = le32_to_cpu(pver->v7.fw_ver);
1546 bt->ver_info.fw_coex = le32_get_bits(pver->v7.coex_ver,
1547 GENMASK(7, 0));
1548 bt->feature = le32_to_cpu(pver->v7.feature);
1549 } else {
1550 pver->v1 = *(struct rtw89_btc_fbtc_btver_v1 *)pfinfo;
1551 bt->ver_info.fw = le32_to_cpu(pver->v1.fw_ver);
1552 bt->ver_info.fw_coex = le32_get_bits(pver->v1.coex_ver,
1553 GENMASK(7, 0));
1554 bt->feature = le32_to_cpu(pver->v1.feature);
1555 }
1556 break;
1557 case BTC_RPT_TYPE_BT_SCAN:
1558 if (ver->fcxbtscan == 1) {
1559 pscan_v1 = (struct rtw89_btc_fbtc_btscan_v1 *)pfinfo;
1560 for (i = 0; i < BTC_SCAN_MAX1; i++) {
1561 bt->scan_info_v1[i] = pscan_v1->scan[i];
1562 if (bt->scan_info_v1[i].win == 0 &&
1563 bt->scan_info_v1[i].intvl == 0)
1564 scan_update = false;
1565 }
1566 } else if (ver->fcxbtscan == 2) {
1567 pscan_v2 = (struct rtw89_btc_fbtc_btscan_v2 *)pfinfo;
1568 for (i = 0; i < CXSCAN_MAX; i++) {
1569 bt->scan_info_v2[i] = pscan_v2->para[i];
1570 if ((pscan_v2->type & BIT(i)) &&
1571 pscan_v2->para[i].win == 0 &&
1572 pscan_v2->para[i].intvl == 0)
1573 scan_update = false;
1574 }
1575 } else if (ver->fcxbtscan == 7) {
1576 pscan_v7 = (struct rtw89_btc_fbtc_btscan_v7 *)pfinfo;
1577 for (i = 0; i < CXSCAN_MAX; i++) {
1578 bt->scan_info_v2[i] = pscan_v7->para[i];
1579 if ((pscan_v7->type & BIT(i)) &&
1580 pscan_v7->para[i].win == 0 &&
1581 pscan_v7->para[i].intvl == 0)
1582 scan_update = false;
1583 }
1584 } else if (ver->fcxbtscan == 8) {
1585 struct rtw89_btc_fbtc_btscan_v8 *pscan_v8 =
1586 (struct rtw89_btc_fbtc_btscan_v8 *)pfinfo;
1587 struct rtw89_btc_bt_info *tbt =
1588 pscan_v8->bt_id ? &btc->cx.bt1 : &btc->cx.bt0;
1589
1590 for (i = 0; i < CXSCAN_MAX; i++) {
1591 tbt->scan_info_v2[i] = pscan_v8->para[i];
1592 if ((pscan_v8->type & BIT(i)) &&
1593 pscan_v8->para[i].win == 0 &&
1594 pscan_v8->para[i].intvl == 0)
1595 scan_update = false;
1596 }
1597 }
1598 if (scan_update)
1599 bt->scan_info_update = 1;
1600 break;
1601 case BTC_RPT_TYPE_BT_AFH:
1602 if (ver->fcxbtafh == 2) {
1603 pafh_v2 = (struct rtw89_btc_fbtc_btafh_v2 *)pfinfo;
1604 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1605 memcpy(&bt_linfo->afh_map[0], pafh_v2->afh_l, 4);
1606 memcpy(&bt_linfo->afh_map[4], pafh_v2->afh_m, 4);
1607 memcpy(&bt_linfo->afh_map[8], pafh_v2->afh_h, 2);
1608 }
1609 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LE) {
1610 memcpy(&bt_linfo->afh_map_le[0], pafh_v2->afh_le_a, 4);
1611 memcpy(&bt_linfo->afh_map_le[4], pafh_v2->afh_le_b, 1);
1612 }
1613 } else if (ver->fcxbtafh == 7) {
1614 pafh_v7 = (struct rtw89_btc_fbtc_btafh_v7 *)pfinfo;
1615 if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1616 memcpy(&bt_linfo->afh_map[0], pafh_v7->afh_l, 4);
1617 memcpy(&bt_linfo->afh_map[4], pafh_v7->afh_m, 4);
1618 memcpy(&bt_linfo->afh_map[8], pafh_v7->afh_h, 2);
1619 }
1620 if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LE) {
1621 memcpy(&bt_linfo->afh_map_le[0], pafh_v7->afh_le_a, 4);
1622 memcpy(&bt_linfo->afh_map_le[4], pafh_v7->afh_le_b, 1);
1623 }
1624 } else if (ver->fcxbtafh == 8) {
1625 struct rtw89_btc_fbtc_btafh_v8 *pafh_v8 =
1626 (struct rtw89_btc_fbtc_btafh_v8 *)pfinfo;
1627 struct rtw89_btc_bt_info *tbt =
1628 pafh_v8->bt_id ? &btc->cx.bt1 : &btc->cx.bt0;
1629 struct rtw89_btc_bt_link_info *tbt_linfo = &tbt->link_info;
1630
1631 if (pafh_v8->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1632 memcpy(&tbt_linfo->afh_map[0], pafh_v8->afh_l, 4);
1633 memcpy(&tbt_linfo->afh_map[4], pafh_v8->afh_m, 4);
1634 memcpy(&tbt_linfo->afh_map[8], pafh_v8->afh_h, 2);
1635 }
1636 if (pafh_v8->map_type & RPT_BT_AFH_SEQ_LE) {
1637 memcpy(&tbt_linfo->afh_map_le[0], pafh_v8->afh_le_a, 4);
1638 memcpy(&tbt_linfo->afh_map_le[4], pafh_v8->afh_le_b, 1);
1639 }
1640 } else if (ver->fcxbtafh == 1) {
1641 pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo;
1642 memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4);
1643 memcpy(&bt_linfo->afh_map[4], pafh_v1->afh_m, 4);
1644 memcpy(&bt_linfo->afh_map[8], pafh_v1->afh_h, 2);
1645 }
1646 break;
1647 case BTC_RPT_TYPE_BT_DEVICE:
1648 pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo;
1649 a2dp->device_name = le32_to_cpu(pdev->dev_name);
1650 a2dp->vendor_id = le16_to_cpu(pdev->vendor_id);
1651 a2dp->flush_time = le32_to_cpu(pdev->flush_time);
1652 break;
1653 default:
1654 break;
1655 }
1656 }
1657
rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev * rtwdev,u8 * index)1658 static void rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev *rtwdev, u8 *index)
1659 {
1660 struct rtw89_btc *btc = &rtwdev->btc;
1661 const struct rtw89_btc_ver *ver = btc->ver;
1662
1663 if (ver->fwevntrptl == 1)
1664 return;
1665
1666 if (*index <= __BTC_RPT_TYPE_V0_SAME)
1667 return;
1668 else if (*index <= __BTC_RPT_TYPE_V0_MAX)
1669 (*index)++;
1670 else
1671 *index = BTC_RPT_TYPE_MAX;
1672 }
1673
1674 #define BTC_LEAK_AP_TH 10
1675 #define BTC_CYSTA_CHK_PERIOD 100
1676
1677 struct rtw89_btc_prpt {
1678 u8 type;
1679 __le16 len;
1680 u8 content[];
1681 } __packed;
1682
_chk_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * prptbuf,u32 index)1683 static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
1684 struct rtw89_btc_btf_fwinfo *pfwinfo,
1685 u8 *prptbuf, u32 index)
1686 {
1687 struct rtw89_btc *btc = &rtwdev->btc;
1688 struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver;
1689 const struct rtw89_btc_ver *ver = btc->ver;
1690 struct rtw89_btc_dm *dm = &btc->dm;
1691 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
1692 struct rtw89_btc_cx *cx = &btc->cx;
1693 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1694 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
1695 union rtw89_btc_fbtc_rpt_ctrl_ver_info *prpt = NULL;
1696 union rtw89_btc_fbtc_cysta_info *pcysta = NULL;
1697 struct rtw89_btc_prpt *btc_prpt = NULL;
1698 void *rpt_content = NULL, *pfinfo = NULL;
1699 u8 rpt_type = 0;
1700 u16 wl_slot_set = 0, wl_slot_real = 0, val16;
1701 u32 trace_step = 0, rpt_len = 0, diff_t = 0;
1702 u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr;
1703 u8 i, j, val = 0, val1, val2;
1704 u32 *bt_cnt, start_idx;
1705
1706 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1707 "[BTC], %s(): index:%d\n",
1708 __func__, index);
1709
1710 if (!prptbuf) {
1711 pfwinfo->err[BTFRE_INVALID_INPUT]++;
1712 return 0;
1713 }
1714
1715 btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index];
1716 rpt_type = btc_prpt->type;
1717 rpt_len = le16_to_cpu(btc_prpt->len);
1718 rpt_content = btc_prpt->content;
1719
1720 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1721 "[BTC], %s(): rpt_type:%d\n",
1722 __func__, rpt_type);
1723
1724 rtw89_btc_fw_rpt_evnt_ver(rtwdev, &rpt_type);
1725
1726 switch (rpt_type) {
1727 case BTC_RPT_TYPE_CTRL:
1728 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
1729 prpt = &pfwinfo->rpt_ctrl.finfo;
1730 if (ver->fcxbtcrpt == 1) {
1731 pfinfo = &pfwinfo->rpt_ctrl.finfo.v1;
1732 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v1);
1733 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v1.fver;
1734 } else if (ver->fcxbtcrpt == 4) {
1735 pfinfo = &pfwinfo->rpt_ctrl.finfo.v4;
1736 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v4);
1737 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v4.fver;
1738 } else if (ver->fcxbtcrpt == 5) {
1739 pfinfo = &pfwinfo->rpt_ctrl.finfo.v5;
1740 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v5);
1741 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v5.fver;
1742 } else if (ver->fcxbtcrpt == 105) {
1743 pfinfo = &pfwinfo->rpt_ctrl.finfo.v105;
1744 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v105);
1745 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v105.fver;
1746 pcinfo->req_fver = 5;
1747 break;
1748 } else if (ver->fcxbtcrpt == 8) {
1749 pfinfo = &pfwinfo->rpt_ctrl.finfo.v8;
1750 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8);
1751 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v8.fver;
1752 } else if (ver->fcxbtcrpt == 7) {
1753 pfinfo = &pfwinfo->rpt_ctrl.finfo.v7;
1754 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v7);
1755 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v7.fver;
1756 } else if (ver->fcxbtcrpt == 9) {
1757 pfinfo = &pfwinfo->rpt_ctrl.finfo.v9;
1758 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v9);
1759 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v9.fver;
1760 } else if (ver->fcxbtcrpt == 11) {
1761 pfinfo = &pfwinfo->rpt_ctrl.finfo.v11;
1762 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v11);
1763 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v11.fver;
1764 } else {
1765 goto err;
1766 }
1767 pcinfo->req_fver = ver->fcxbtcrpt;
1768 break;
1769 case BTC_RPT_TYPE_TDMA:
1770 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
1771 if (ver->fcxtdma == 1) {
1772 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
1773 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1);
1774 fwsubver->fcxtdma = 0;
1775 } else if (ver->fcxtdma == 3 || ver->fcxtdma == 4 ||
1776 ver->fcxtdma == 7 || ver->fcxtdma == 8) {
1777 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3;
1778 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3);
1779 fwsubver->fcxtdma = pfwinfo->rpt_fbtc_tdma.finfo.v3.fver;
1780 } else {
1781 goto err;
1782 }
1783 pcinfo->req_fver = ver->fcxtdma;
1784 break;
1785 case BTC_RPT_TYPE_SLOT:
1786 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
1787 if (ver->fcxslots == 1) {
1788 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1;
1789 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v1);
1790 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v1.fver;
1791 } else if (ver->fcxslots == 2) {
1792 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v2;
1793 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v2);
1794 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v2.fver;
1795 } else if (ver->fcxslots == 7) {
1796 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7;
1797 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v7);
1798 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v7.fver;
1799 } else {
1800 goto err;
1801 }
1802 pcinfo->req_fver = ver->fcxslots;
1803 break;
1804 case BTC_RPT_TYPE_CYSTA:
1805 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
1806 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
1807 if (ver->fcxcysta == 2) {
1808 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
1809 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
1810 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v2);
1811 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v2.fver;
1812 } else if (ver->fcxcysta == 3) {
1813 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
1814 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
1815 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v3);
1816 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v3.fver;
1817 } else if (ver->fcxcysta == 4) {
1818 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
1819 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
1820 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v4);
1821 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v4.fver;
1822 } else if (ver->fcxcysta == 5) {
1823 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
1824 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
1825 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v5);
1826 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v5.fver;
1827 } else if (ver->fcxcysta == 105) {
1828 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v105;
1829 pcysta->v105 = pfwinfo->rpt_fbtc_cysta.finfo.v105;
1830 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v105);
1831 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v105.fver;
1832 } else if (ver->fcxcysta == 7) {
1833 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
1834 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
1835 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v7);
1836 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v7.fver;
1837 } else {
1838 goto err;
1839 }
1840 pcinfo->req_fver = ver->fcxcysta;
1841 break;
1842 case BTC_RPT_TYPE_STEP:
1843 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
1844 if (ver->fcxctrl != 7)
1845 trace_step = btc->ctrl.trace_step;
1846
1847 if (ver->fcxstep == 2) {
1848 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v2;
1849 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) *
1850 trace_step +
1851 offsetof(struct rtw89_btc_fbtc_steps_v2, step);
1852 fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v2.fver;
1853 } else if (ver->fcxstep == 3) {
1854 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3;
1855 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) *
1856 trace_step +
1857 offsetof(struct rtw89_btc_fbtc_steps_v3, step);
1858 fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v3.fver;
1859 } else {
1860 goto err;
1861 }
1862 pcinfo->req_fver = ver->fcxstep;
1863 break;
1864 case BTC_RPT_TYPE_NULLSTA:
1865 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
1866 if (ver->fcxnullsta == 1) {
1867 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1;
1868 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v1);
1869 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v1.fver;
1870 } else if (ver->fcxnullsta == 2) {
1871 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2;
1872 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v2);
1873 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v2.fver;
1874 } else if (ver->fcxnullsta == 7) {
1875 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v7;
1876 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v7);
1877 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v7.fver;
1878 } else {
1879 goto err;
1880 }
1881 pcinfo->req_fver = ver->fcxnullsta;
1882 break;
1883 case BTC_RPT_TYPE_MREG:
1884 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
1885 if (ver->fcxmreg == 1) {
1886 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
1887 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v1);
1888 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v1.fver;
1889 } else if (ver->fcxmreg == 2) {
1890 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
1891 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v2);
1892 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v2.fver;
1893 } else if (ver->fcxmreg == 7) {
1894 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
1895 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v7);
1896 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v7.fver;
1897 } else {
1898 goto err;
1899 }
1900 pcinfo->req_fver = ver->fcxmreg;
1901 break;
1902 case BTC_RPT_TYPE_GPIO_DBG:
1903 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
1904 if (ver->fcxgpiodbg == 7) {
1905 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7;
1906 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7);
1907 fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7.fver;
1908 } else {
1909 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1;
1910 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1);
1911 fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1.fver;
1912 }
1913 pcinfo->req_fver = ver->fcxgpiodbg;
1914 break;
1915 case BTC_RPT_TYPE_BT_VER:
1916 pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
1917 if (ver->fcxbtver == 1) {
1918 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v1;
1919 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v1);
1920 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v1.fver;
1921 } else if (ver->fcxbtver == 7) {
1922 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v7;
1923 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v7);
1924 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v7.fver;
1925 } else if (ver->fcxbtver == 8) {
1926 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v8;
1927 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v8);
1928 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v8.fver;
1929 } else {
1930 goto err;
1931 }
1932 pcinfo->req_fver = ver->fcxbtver;
1933 break;
1934 case BTC_RPT_TYPE_BT_SCAN:
1935 pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
1936 if (ver->fcxbtscan == 1) {
1937 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1;
1938 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v1);
1939 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v1.fver;
1940 } else if (ver->fcxbtscan == 2) {
1941 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2;
1942 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v2);
1943 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v2.fver;
1944 } else if (ver->fcxbtscan == 7) {
1945 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v7;
1946 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v7);
1947 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v7.fver;
1948 } else if (ver->fcxbtscan == 8) {
1949 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v8;
1950 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v8);
1951 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v8.fver;
1952 } else {
1953 goto err;
1954 }
1955 pcinfo->req_fver = ver->fcxbtscan;
1956 break;
1957 case BTC_RPT_TYPE_BT_AFH:
1958 pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
1959 if (ver->fcxbtafh == 1) {
1960 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1;
1961 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v1);
1962 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v1.fver;
1963 } else if (ver->fcxbtafh == 2) {
1964 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2;
1965 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2);
1966 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v2.fver;
1967 } else if (ver->fcxbtafh == 7) {
1968 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v7;
1969 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v7);
1970 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v7.fver;
1971 } else if (ver->fcxbtafh == 8) {
1972 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v8;
1973 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v8);
1974 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v8.fver;
1975 } else {
1976 goto err;
1977 }
1978 pcinfo->req_fver = ver->fcxbtafh;
1979 break;
1980 case BTC_RPT_TYPE_BT_DEVICE:
1981 pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
1982 pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo;
1983 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo);
1984 fwsubver->fcxbtdevinfo = pfwinfo->rpt_fbtc_btdev.finfo.fver;
1985 pcinfo->req_fver = ver->fcxbtdevinfo;
1986 break;
1987 default:
1988 pfwinfo->err[BTFRE_UNDEF_TYPE]++;
1989 return 0;
1990 }
1991
1992 pcinfo->rx_len = rpt_len;
1993 pcinfo->rx_cnt++;
1994
1995 if (rpt_len != pcinfo->req_len) {
1996 if (rpt_type < BTC_RPT_TYPE_MAX)
1997 pfwinfo->len_mismch |= (0x1 << rpt_type);
1998 else
1999 pfwinfo->len_mismch |= BIT(31);
2000 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2001 "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n",
2002 __func__, rpt_type, rpt_len, pcinfo->req_len);
2003
2004 pcinfo->valid = 0;
2005 return 0;
2006 } else if (!pfinfo || !rpt_content || !pcinfo->req_len) {
2007 pfwinfo->err[BTFRE_EXCEPTION]++;
2008 pcinfo->valid = 0;
2009 return 0;
2010 }
2011
2012 memcpy(pfinfo, rpt_content, pcinfo->req_len);
2013 pcinfo->valid = 1;
2014
2015 switch (rpt_type) {
2016 case BTC_RPT_TYPE_CTRL:
2017 if (ver->fcxbtcrpt == 1) {
2018 prpt->v1 = pfwinfo->rpt_ctrl.finfo.v1;
2019 btc->fwinfo.rpt_en_map = prpt->v1.rpt_enable;
2020 wl->ver_info.fw_coex = prpt->v1.wl_fw_coex_ver;
2021 wl->ver_info.fw = prpt->v1.wl_fw_ver;
2022 dm->wl_fw_cx_offload = !!prpt->v1.wl_fw_cx_offload;
2023
2024 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
2025 pfwinfo->event[BTF_EVNT_RPT]);
2026
2027 /* To avoid I/O if WL LPS or power-off */
2028 if (wl->status.map.lps != BTC_LPS_RF_OFF &&
2029 !wl->status.map.rf_off) {
2030 rtwdev->chip->ops->btc_update_bt_cnt(rtwdev);
2031 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2032
2033 bt->bcnt[BTC_BCNT_POLLUTED] =
2034 rtw89_mac_get_plt_cnt(rtwdev,
2035 RTW89_MAC_0);
2036 }
2037 } else if (ver->fcxbtcrpt == 4) {
2038 prpt->v4 = pfwinfo->rpt_ctrl.finfo.v4;
2039 btc->fwinfo.rpt_en_map = le32_to_cpu(prpt->v4.rpt_info.en);
2040 wl->ver_info.fw_coex = le32_to_cpu(prpt->v4.wl_fw_info.cx_ver);
2041 wl->ver_info.fw = le32_to_cpu(prpt->v4.wl_fw_info.fw_ver);
2042 dm->wl_fw_cx_offload = !!le32_to_cpu(prpt->v4.wl_fw_info.cx_offload);
2043
2044 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
2045 memcpy(&dm->gnt_val[i], &prpt->v4.gnt_val[i],
2046 sizeof(dm->gnt_val[i]));
2047
2048 bt->bcnt[BTC_BCNT_HIPRI_TX] =
2049 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_TX]);
2050 bt->bcnt[BTC_BCNT_HIPRI_RX] =
2051 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_RX]);
2052 bt->bcnt[BTC_BCNT_LOPRI_TX] =
2053 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_TX]);
2054 bt->bcnt[BTC_BCNT_LOPRI_RX] =
2055 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_RX]);
2056 bt->bcnt[BTC_BCNT_POLLUTED] =
2057 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_POLLUTED]);
2058
2059 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2060 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
2061 pfwinfo->event[BTF_EVNT_RPT]);
2062
2063 if (le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
2064 bt->rfk_info.map.timeout = 1;
2065 else
2066 bt->rfk_info.map.timeout = 0;
2067
2068 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
2069 } else if (ver->fcxbtcrpt == 5) {
2070 prpt->v5 = pfwinfo->rpt_ctrl.finfo.v5;
2071 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v5.rpt_info.en);
2072 wl->ver_info.fw_coex = le32_to_cpu(prpt->v5.rpt_info.cx_ver);
2073 wl->ver_info.fw = le32_to_cpu(prpt->v5.rpt_info.fw_ver);
2074 dm->wl_fw_cx_offload = 0;
2075
2076 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
2077 memcpy(&dm->gnt_val[i], &prpt->v5.gnt_val[i],
2078 sizeof(dm->gnt_val[i]));
2079
2080 bt->bcnt[BTC_BCNT_HIPRI_TX] =
2081 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_TX]);
2082 bt->bcnt[BTC_BCNT_HIPRI_RX] =
2083 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_RX]);
2084 bt->bcnt[BTC_BCNT_LOPRI_TX] =
2085 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_TX]);
2086 bt->bcnt[BTC_BCNT_LOPRI_RX] =
2087 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_RX]);
2088 bt->bcnt[BTC_BCNT_POLLUTED] =
2089 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_POLLUTED]);
2090
2091 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2092 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
2093 pfwinfo->event[BTF_EVNT_RPT]);
2094
2095 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
2096 } else if (ver->fcxbtcrpt == 105) {
2097 prpt->v105 = pfwinfo->rpt_ctrl.finfo.v105;
2098 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v105.rpt_info.en);
2099 wl->ver_info.fw_coex = le32_to_cpu(prpt->v105.rpt_info.cx_ver);
2100 wl->ver_info.fw = le32_to_cpu(prpt->v105.rpt_info.fw_ver);
2101 dm->wl_fw_cx_offload = 0;
2102
2103 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
2104 memcpy(&dm->gnt_val[i], &prpt->v105.gnt_val[i],
2105 sizeof(dm->gnt_val[i]));
2106
2107 bt->bcnt[BTC_BCNT_HIPRI_TX] =
2108 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_TX_V105]);
2109 bt->bcnt[BTC_BCNT_HIPRI_RX] =
2110 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_RX_V105]);
2111 bt->bcnt[BTC_BCNT_LOPRI_TX] =
2112 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_TX_V105]);
2113 bt->bcnt[BTC_BCNT_LOPRI_RX] =
2114 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_RX_V105]);
2115 bt->bcnt[BTC_BCNT_POLLUTED] =
2116 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_POLLUTED_V105]);
2117
2118 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2119 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
2120 pfwinfo->event[BTF_EVNT_RPT]);
2121
2122 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
2123 } else if (ver->fcxbtcrpt == 7) {
2124 prpt->v7 = pfwinfo->rpt_ctrl.finfo.v7;
2125 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v7.rpt_info.en);
2126 wl->ver_info.fw_coex = le32_to_cpu(prpt->v7.rpt_info.cx_ver);
2127 wl->ver_info.fw = le32_to_cpu(prpt->v7.rpt_info.fw_ver);
2128
2129 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
2130 memcpy(&dm->gnt_val[i], &prpt->v7.gnt_val[i],
2131 sizeof(dm->gnt_val[i]));
2132
2133 bt->bcnt[BTC_BCNT_HIPRI_TX] =
2134 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_TX_V105]);
2135 bt->bcnt[BTC_BCNT_HIPRI_RX] =
2136 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_RX_V105]);
2137 bt->bcnt[BTC_BCNT_LOPRI_TX] =
2138 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_TX_V105]);
2139 bt->bcnt[BTC_BCNT_LOPRI_RX] =
2140 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_RX_V105]);
2141
2142 val1 = le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]);
2143 if (val1 > bt->bcnt[BTC_BCNT_POLUT_NOW])
2144 val1 -= bt->bcnt[BTC_BCNT_POLUT_NOW]; /* diff */
2145
2146 bt->bcnt[BTC_BCNT_POLUT_DIFF] = val1;
2147 bt->bcnt[BTC_BCNT_POLUT_NOW] =
2148 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]);
2149
2150 val1 = pfwinfo->event[BTF_EVNT_RPT];
2151 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2152 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
2153 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
2154 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
2155 } else if (ver->fcxbtcrpt == 8) {
2156 prpt->v8 = pfwinfo->rpt_ctrl.finfo.v8;
2157 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v8.rpt_info.en);
2158 wl->ver_info.fw_coex = le32_to_cpu(prpt->v8.rpt_info.cx_ver);
2159 wl->ver_info.fw = le32_to_cpu(prpt->v8.rpt_info.fw_ver);
2160
2161 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
2162 memcpy(&dm->gnt_val[i], &prpt->v8.gnt_val[i],
2163 sizeof(dm->gnt_val[i]));
2164
2165 bt->bcnt[BTC_BCNT_HIPRI_TX] =
2166 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_TX_V105]);
2167 bt->bcnt[BTC_BCNT_HIPRI_RX] =
2168 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_RX_V105]);
2169 bt->bcnt[BTC_BCNT_LOPRI_TX] =
2170 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_TX_V105]);
2171 bt->bcnt[BTC_BCNT_LOPRI_RX] =
2172 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_RX_V105]);
2173
2174 val1 = le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
2175 if (val1 > bt->bcnt[BTC_BCNT_POLUT_NOW])
2176 val1 -= bt->bcnt[BTC_BCNT_POLUT_NOW]; /* diff */
2177
2178 bt->bcnt[BTC_BCNT_POLUT_DIFF] = val1;
2179 bt->bcnt[BTC_BCNT_POLUT_NOW] =
2180 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
2181
2182 val1 = pfwinfo->event[BTF_EVNT_RPT];
2183 if (((prpt->v8.rpt_len_max_h << 8) +
2184 prpt->v8.rpt_len_max_l) != ver->info_buf)
2185 dm->error.map.h2c_c2h_buffer_mismatch = true;
2186 else
2187 dm->error.map.h2c_c2h_buffer_mismatch = false;
2188
2189 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2190 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
2191 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
2192 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
2193 } else if (ver->fcxbtcrpt == 9) {
2194 prpt->v9 = pfwinfo->rpt_ctrl.finfo.v9;
2195 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v9.rpt_info.en);
2196 wl->ver_info.fw_coex = le32_to_cpu(prpt->v9.rpt_info.cx_ver);
2197 wl->ver_info.fw = le32_to_cpu(prpt->v9.rpt_info.fw_ver);
2198
2199 memcpy(wl->ver_info.build_time,
2200 prpt->v9.build_time,
2201 sizeof(wl->ver_info.build_time));
2202 memcpy(wl->ver_info.build_date,
2203 prpt->v9.build_date,
2204 sizeof(wl->ver_info.build_date));
2205
2206 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
2207 memcpy(&dm->gnt_val[i], &prpt->v9.gnt_val[i],
2208 sizeof(dm->gnt_val[i]));
2209
2210 bt->bcnt[BTC_BCNT_HIPRI_TX] =
2211 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_HI_TX_V105]);
2212 bt->bcnt[BTC_BCNT_HIPRI_RX] =
2213 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_HI_RX_V105]);
2214 bt->bcnt[BTC_BCNT_LOPRI_TX] =
2215 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_LO_TX_V105]);
2216 bt->bcnt[BTC_BCNT_LOPRI_RX] =
2217 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_LO_RX_V105]);
2218
2219 val1 = le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_POLLUTED_V105]);
2220 if (val1 > bt->bcnt[BTC_BCNT_POLUT_NOW])
2221 val1 -= bt->bcnt[BTC_BCNT_POLUT_NOW]; /* diff */
2222
2223 bt->bcnt[BTC_BCNT_POLUT_DIFF] = val1;
2224 bt->bcnt[BTC_BCNT_POLUT_NOW] =
2225 le16_to_cpu(prpt->v9.bt_cnt[BTC_BCNT_POLLUTED_V105]);
2226
2227 dm->pta_owner = prpt->v9.pta_owner;
2228
2229 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2230 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
2231 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
2232 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
2233 } else if (ver->fcxbtcrpt == 11) {
2234 prpt->v11 = pfwinfo->rpt_ctrl.finfo.v11;
2235 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v11.rpt_info.en);
2236 wl->ver_info.fw_coex = le32_to_cpu(prpt->v11.rpt_info.cx_ver);
2237 wl->ver_info.fw = le32_to_cpu(prpt->v11.rpt_info.fw_ver);
2238
2239 memcpy(wl->ver_info.build_time,
2240 prpt->v11.build_time,
2241 sizeof(wl->ver_info.build_time));
2242 memcpy(wl->ver_info.build_date,
2243 prpt->v11.build_date,
2244 sizeof(wl->ver_info.build_date));
2245
2246 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
2247 memcpy(&dm->gnt_val[i], &prpt->v11.gnt_val[i][0],
2248 sizeof(dm->gnt_val[i]));
2249
2250 for (i = BTC_BT_1ST; i <= BTC_BT_EXT; i++) {
2251 if (i == BTC_BT_EXT) {
2252 if (cx->bt_ext.func_type == BTC_BTF_NONE)
2253 continue;
2254 bt_cnt = cx->bt_ext.bcnt;
2255 } else if (i == BTC_BT_2ND) {
2256 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))
2257 continue;
2258 bt_cnt = cx->bt1.bcnt;
2259 wl->scbd_rb[i] = le32_to_cpu(prpt->v11.scbd_w2b[i]);
2260 cx->bt1.scbd_rb = le32_to_cpu(prpt->v11.scbd_b2w[i]);
2261 } else {
2262 bt_cnt = cx->bt0.bcnt;
2263 wl->scbd_rb[i] = le32_to_cpu(prpt->v11.scbd_w2b[i]);
2264 cx->bt0.scbd_rb = le32_to_cpu(prpt->v11.scbd_b2w[i]);
2265 }
2266
2267 start_idx = BTC_BCNT_HIPRI_TX;
2268 for (j = BTC_BCNT_HI_TX_V105; j <= BTC_BCNT_LO_RX_V105 ; j++)
2269 bt_cnt[start_idx++] = le16_to_cpu(prpt->v11.bt_cnt[i][j]);
2270
2271 /* check if polut counter increase */
2272 val1 = le16_to_cpu(prpt->v11.bt_cnt[i][BTC_BCNT_POLLUTED_V105]);
2273 if (val1 > bt_cnt[BTC_BCNT_POLUT_NOW]) /* cnt increase*/
2274 val2 = val1 - bt_cnt[BTC_BCNT_POLUT_NOW];
2275 else
2276 val2 = val1; /* overflow */
2277
2278 bt_cnt[BTC_BCNT_POLUT_DIFF] = val2;
2279 bt_cnt[BTC_BCNT_POLUT_NOW] = val1;
2280
2281 if (i <= BTC_BT_2ND)
2282 bt_cnt[BTC_BCNT_SCBDREAD]++;
2283 }
2284 dm->scbd_w2b_update = true;
2285 dm->scbd_b2w_update = true;
2286
2287 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
2288 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
2289 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
2290 _chk_btc_err(rtwdev, BTC_DCNT_WL_STA_NTFY, 0);
2291 _chk_btc_err(rtwdev, BTC_DCNT_W2B_SCBD_NOSYNC, 0);
2292 } else {
2293 goto err;
2294 }
2295 break;
2296 case BTC_RPT_TYPE_TDMA:
2297 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2298 "[BTC], %s(): check %d %zu\n", __func__,
2299 BTC_DCNT_TDMA_NONSYNC,
2300 sizeof(dm->tdma_now));
2301 if (ver->fcxtdma == 1)
2302 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
2303 memcmp(&dm->tdma_now,
2304 &pfwinfo->rpt_fbtc_tdma.finfo.v1,
2305 sizeof(dm->tdma_now)));
2306 else if (ver->fcxtdma == 3 || ver->fcxtdma == 4 ||
2307 ver->fcxtdma == 7 || ver->fcxtdma == 8)
2308 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
2309 memcmp(&dm->tdma_now,
2310 &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma,
2311 sizeof(dm->tdma_now)));
2312 else
2313 goto err;
2314 break;
2315 case BTC_RPT_TYPE_SLOT:
2316 if (ver->fcxslots == 7) {
2317 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2318 "[BTC], %s(): check %d %zu\n",
2319 __func__, BTC_DCNT_SLOT_NONSYNC,
2320 sizeof(dm->slot_now.v7));
2321 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
2322 memcmp(dm->slot_now.v7,
2323 pfwinfo->rpt_fbtc_slots.finfo.v7.slot,
2324 sizeof(dm->slot_now.v7)));
2325 } else if (ver->fcxslots == 2) {
2326 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2327 "[BTC], %s(): check %d %zu\n",
2328 __func__, BTC_DCNT_SLOT_NONSYNC,
2329 sizeof(dm->slot_now.v7));
2330 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
2331 memcmp(dm->slot_now.v7,
2332 pfwinfo->rpt_fbtc_slots.finfo.v2.slot,
2333 sizeof(dm->slot_now.v7)));
2334 } else if (ver->fcxslots == 1) {
2335 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2336 "[BTC], %s(): check %d %zu\n",
2337 __func__, BTC_DCNT_SLOT_NONSYNC,
2338 sizeof(dm->slot_now.v1));
2339 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
2340 memcmp(dm->slot_now.v1,
2341 pfwinfo->rpt_fbtc_slots.finfo.v1.slot,
2342 sizeof(dm->slot_now.v1)));
2343 }
2344 break;
2345 case BTC_RPT_TYPE_CYSTA:
2346 if (ver->fcxcysta == 2) {
2347 if (le16_to_cpu(pcysta->v2.cycles) < BTC_CYSTA_CHK_PERIOD)
2348 break;
2349 /* Check Leak-AP */
2350 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) != 0 &&
2351 le32_to_cpu(pcysta->v2.leakrx_cnt) != 0 && dm->tdma_now.rxflctrl) {
2352 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) <
2353 BTC_LEAK_AP_TH * le32_to_cpu(pcysta->v2.leakrx_cnt))
2354 dm->leak_ap = 1;
2355 }
2356
2357 /* Check diff time between WL slot and W1/E2G slot */
2358 if (dm->tdma_now.type == CXTDMA_OFF &&
2359 dm->tdma_now.ext_ctrl == CXECTL_EXT) {
2360 if (ver->fcxslots == 1)
2361 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_E2G].dur);
2362 else if (ver->fcxslots == 7)
2363 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_E2G].dur);
2364 } else {
2365 if (ver->fcxslots == 1)
2366 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2367 else if (ver->fcxslots == 7)
2368 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2369 }
2370
2371 if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) {
2372 diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set;
2373 _chk_btc_err(rtwdev,
2374 BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2375 }
2376
2377 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2378 le32_to_cpu(pcysta->v2.slot_cnt[CXST_W1]));
2379 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2380 le32_to_cpu(pcysta->v2.slot_cnt[CXST_B1]));
2381 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2382 le16_to_cpu(pcysta->v2.cycles));
2383 } else if (ver->fcxcysta == 3) {
2384 if (le16_to_cpu(pcysta->v3.cycles) < BTC_CYSTA_CHK_PERIOD)
2385 break;
2386
2387 cnt_leak_slot = le32_to_cpu(pcysta->v3.slot_cnt[CXST_LK]);
2388 cnt_rx_imr = le32_to_cpu(pcysta->v3.leak_slot.cnt_rximr);
2389
2390 /* Check Leak-AP */
2391 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
2392 dm->tdma_now.rxflctrl) {
2393 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
2394 dm->leak_ap = 1;
2395 }
2396
2397 /* Check diff time between real WL slot and W1 slot */
2398 if (dm->tdma_now.type == CXTDMA_OFF) {
2399 if (ver->fcxslots == 1)
2400 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2401 else if (ver->fcxslots == 7)
2402 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2403 wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]);
2404 if (wl_slot_real > wl_slot_set) {
2405 diff_t = wl_slot_real - wl_slot_set;
2406 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2407 }
2408 }
2409
2410 /* Check diff time between real BT slot and EBT/E5G slot */
2411 if (dm->tdma_now.type == CXTDMA_OFF &&
2412 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
2413 btc->bt_req_len[RTW89_PHY_0] != 0) {
2414 bt_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_BT]);
2415 if (btc->bt_req_len[RTW89_PHY_0] > bt_slot_real) {
2416 diff_t = btc->bt_req_len[RTW89_PHY_0] - bt_slot_real;
2417 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2418 }
2419 }
2420
2421 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2422 le32_to_cpu(pcysta->v3.slot_cnt[CXST_W1]));
2423 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2424 le32_to_cpu(pcysta->v3.slot_cnt[CXST_B1]));
2425 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2426 le16_to_cpu(pcysta->v3.cycles));
2427 } else if (ver->fcxcysta == 4) {
2428 if (le16_to_cpu(pcysta->v4.cycles) < BTC_CYSTA_CHK_PERIOD)
2429 break;
2430
2431 cnt_leak_slot = le16_to_cpu(pcysta->v4.slot_cnt[CXST_LK]);
2432 cnt_rx_imr = le32_to_cpu(pcysta->v4.leak_slot.cnt_rximr);
2433
2434 /* Check Leak-AP */
2435 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
2436 dm->tdma_now.rxflctrl) {
2437 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
2438 dm->leak_ap = 1;
2439 }
2440
2441 /* Check diff time between real WL slot and W1 slot */
2442 if (dm->tdma_now.type == CXTDMA_OFF) {
2443 if (ver->fcxslots == 1)
2444 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2445 else if (ver->fcxslots == 7)
2446 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2447 wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]);
2448 if (wl_slot_real > wl_slot_set) {
2449 diff_t = wl_slot_real - wl_slot_set;
2450 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2451 }
2452 }
2453
2454 /* Check diff time between real BT slot and EBT/E5G slot */
2455 if (dm->tdma_now.type == CXTDMA_OFF &&
2456 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
2457 btc->bt_req_len[RTW89_PHY_0] != 0) {
2458 bt_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_BT]);
2459
2460 if (btc->bt_req_len[RTW89_PHY_0] > bt_slot_real) {
2461 diff_t = btc->bt_req_len[RTW89_PHY_0] - bt_slot_real;
2462 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2463 }
2464 }
2465
2466 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2467 le16_to_cpu(pcysta->v4.slot_cnt[CXST_W1]));
2468 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2469 le16_to_cpu(pcysta->v4.slot_cnt[CXST_B1]));
2470 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2471 le16_to_cpu(pcysta->v4.cycles));
2472 } else if (ver->fcxcysta == 5) {
2473 if (dm->fddt_train == BTC_FDDT_ENABLE)
2474 break;
2475 cnt_leak_slot = le16_to_cpu(pcysta->v5.slot_cnt[CXST_LK]);
2476 cnt_rx_imr = le32_to_cpu(pcysta->v5.leak_slot.cnt_rximr);
2477
2478 /* Check Leak-AP */
2479 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
2480 dm->tdma_now.rxflctrl) {
2481 if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD &&
2482 cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
2483 dm->leak_ap = 1;
2484 }
2485
2486 /* Check diff time between real WL slot and W1 slot */
2487 if (dm->tdma_now.type == CXTDMA_OFF) {
2488 if (ver->fcxslots == 1)
2489 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2490 else if (ver->fcxslots == 7)
2491 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2492 wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]);
2493
2494 if (wl_slot_real > wl_slot_set)
2495 diff_t = wl_slot_real - wl_slot_set;
2496 else
2497 diff_t = wl_slot_set - wl_slot_real;
2498 }
2499 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2500
2501 /* Check diff time between real BT slot and EBT/E5G slot */
2502 bt_slot_set = btc->bt_req_len[RTW89_PHY_0];
2503 bt_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_BT]);
2504 diff_t = 0;
2505 if (dm->tdma_now.type == CXTDMA_OFF &&
2506 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
2507 bt_slot_set != 0) {
2508 if (bt_slot_set > bt_slot_real)
2509 diff_t = bt_slot_set - bt_slot_real;
2510 else
2511 diff_t = bt_slot_real - bt_slot_set;
2512 }
2513
2514 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2515 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
2516 le16_to_cpu(pcysta->v5.slot_cnt[CXST_E2G]));
2517 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2518 le16_to_cpu(pcysta->v5.slot_cnt[CXST_W1]));
2519 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2520 le16_to_cpu(pcysta->v5.slot_cnt[CXST_B1]));
2521 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2522 le16_to_cpu(pcysta->v5.cycles));
2523 } else if (ver->fcxcysta == 105) {
2524 if (dm->fddt_train == BTC_FDDT_ENABLE)
2525 break;
2526
2527 cnt_leak_slot = le16_to_cpu(pcysta->v105.slot_cnt[CXST_LK]);
2528 cnt_rx_imr = le32_to_cpu(pcysta->v105.leak_slot.cnt_rximr);
2529
2530 /* Check Leak-AP */
2531 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
2532 dm->tdma_now.rxflctrl) {
2533 if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD &&
2534 cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
2535 dm->leak_ap = 1;
2536 }
2537
2538 /* Check diff time between real WL slot and W1 slot */
2539 if (dm->tdma_now.type == CXTDMA_OFF) {
2540 if (ver->fcxslots == 1)
2541 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2542 else if (ver->fcxslots == 7)
2543 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2544 wl_slot_real = le16_to_cpu(pcysta->v105.cycle_time.tavg[CXT_WL]);
2545
2546 if (wl_slot_real > wl_slot_set)
2547 diff_t = wl_slot_real - wl_slot_set;
2548 else
2549 diff_t = wl_slot_set - wl_slot_real;
2550 }
2551 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2552
2553 /* Check diff time between real BT slot and EBT/E5G slot */
2554 bt_slot_set = btc->bt_req_len[RTW89_PHY_0];
2555 bt_slot_real = le16_to_cpu(pcysta->v105.cycle_time.tavg[CXT_BT]);
2556 diff_t = 0;
2557 if (dm->tdma_now.type == CXTDMA_OFF &&
2558 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
2559 bt_slot_set != 0) {
2560 if (bt_slot_set > bt_slot_real)
2561 diff_t = bt_slot_set - bt_slot_real;
2562 else
2563 diff_t = bt_slot_real - bt_slot_set;
2564 }
2565
2566 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2567 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
2568 le16_to_cpu(pcysta->v105.slot_cnt[CXST_E2G]));
2569 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2570 le16_to_cpu(pcysta->v105.slot_cnt[CXST_W1]));
2571 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2572 le16_to_cpu(pcysta->v105.slot_cnt[CXST_B1]));
2573 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2574 le16_to_cpu(pcysta->v105.cycles));
2575 } else if (ver->fcxcysta == 7) {
2576 if (dm->fddt_train == BTC_FDDT_ENABLE)
2577 break;
2578
2579 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
2580
2581 if (dm->tdma_now.type != CXTDMA_OFF) {
2582 /* Check diff time between real WL slot and W1 slot */
2583 val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_WL]);
2584 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, val16);
2585
2586 /* Check Leak-AP */
2587 val1 = le32_to_cpu(pcysta->v7.leak_slot.cnt_rximr) *
2588 BTC_LEAK_AP_TH;
2589 val2 = le16_to_cpu(pcysta->v7.slot_cnt[CXST_LK]);
2590
2591 val16 = le16_to_cpu(pcysta->v7.cycles);
2592 if (dm->tdma_now.rxflctrl &&
2593 val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
2594 dm->leak_ap = 1;
2595 } else if (dm->tdma_now.ext_ctrl == CXECTL_EXT) {
2596 val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_BT]);
2597 /* Check diff between real BT slot and EBT/E5G slot */
2598 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, val16);
2599
2600 /* Check bt slot length for P2P mode*/
2601 val1 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt_timeout) *
2602 BTC_SLOT_REQ_TH;
2603 val2 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt);
2604
2605 val16 = le16_to_cpu(pcysta->v7.cycles);
2606 if (val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
2607 dm->slot_req_more = 1;
2608 else if (bt->link_info.status.map.connect == 0)
2609 dm->slot_req_more = 0;
2610 }
2611
2612 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
2613 le16_to_cpu(pcysta->v7.slot_cnt[CXST_E2G]));
2614 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2615 le16_to_cpu(pcysta->v7.slot_cnt[CXST_W1]));
2616 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2617 le16_to_cpu(pcysta->v7.slot_cnt[CXST_B1]));
2618
2619 /* "BT_SLOT_FLOOD" error-check MUST before "CYCLE_HANG" */
2620 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_FLOOD,
2621 le16_to_cpu(pcysta->v7.cycles));
2622 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2623 le16_to_cpu(pcysta->v7.cycles));
2624 } else {
2625 goto err;
2626 }
2627 break;
2628 case BTC_RPT_TYPE_MREG:
2629 if (ver->fcxmreg == 7)
2630 break;
2631 _get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX_MON, &val);
2632 if (dm->wl_btg_rx == BTC_BTGCTRL_BB_GNT_FWCTRL)
2633 dm->wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_FWCTRL;
2634 else
2635 dm->wl_btg_rx_rb = val;
2636
2637 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC_MON, &val);
2638 if (dm->wl_pre_agc == BTC_PREAGC_BB_FWCTRL)
2639 dm->wl_pre_agc_rb = BTC_PREAGC_BB_FWCTRL;
2640 else
2641 dm->wl_pre_agc_rb = val;
2642 break;
2643 case BTC_RPT_TYPE_BT_VER:
2644 case BTC_RPT_TYPE_BT_SCAN:
2645 case BTC_RPT_TYPE_BT_AFH:
2646 case BTC_RPT_TYPE_BT_DEVICE:
2647 _update_bt_report(rtwdev, rpt_type, pfinfo);
2648 break;
2649 }
2650 return (rpt_len + BTC_RPT_HDR_SIZE);
2651
2652 err:
2653 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2654 "[BTC], %s(): Undefined version for type=%d\n", __func__, rpt_type);
2655 return 0;
2656 }
2657
_parse_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * pbuf,u32 buf_len)2658 static void _parse_btc_report(struct rtw89_dev *rtwdev,
2659 struct rtw89_btc_btf_fwinfo *pfwinfo,
2660 u8 *pbuf, u32 buf_len)
2661 {
2662 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
2663 struct rtw89_btc_prpt *btc_prpt = NULL;
2664 u32 index = 0, rpt_len = 0;
2665
2666 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2667 "[BTC], %s(): buf_len:%d\n",
2668 __func__, buf_len);
2669
2670 while (pbuf) {
2671 btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index];
2672 if (index + 2 >= ver->info_buf)
2673 break;
2674 /* At least 3 bytes: type(1) & len(2) */
2675 rpt_len = le16_to_cpu(btc_prpt->len);
2676 if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len)
2677 break;
2678
2679 rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index);
2680 if (!rpt_len)
2681 break;
2682 index += rpt_len;
2683 }
2684 }
2685
2686 #define BTC_TLV_HDR_LEN 2
2687 #define BTC_TLV_HDR_LEN_V7 3
2688
_append_tdma(struct rtw89_dev * rtwdev)2689 static void _append_tdma(struct rtw89_dev *rtwdev)
2690 {
2691 struct rtw89_btc *btc = &rtwdev->btc;
2692 const struct rtw89_btc_ver *ver = btc->ver;
2693 struct rtw89_btc_dm *dm = &btc->dm;
2694 struct rtw89_btc_btf_tlv *tlv;
2695 struct rtw89_btc_btf_tlv_v7 *tlv_v7;
2696 struct rtw89_btc_fbtc_tdma *v;
2697 struct rtw89_btc_fbtc_tdma_v3 *v3;
2698 u16 len = btc->policy_len;
2699
2700 if (!btc->update_policy_force &&
2701 !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) {
2702 rtw89_debug(rtwdev,
2703 RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n",
2704 __func__);
2705 return;
2706 }
2707
2708 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
2709 tlv->type = CXPOLICY_TDMA;
2710 if (ver->fcxtdma == 1) {
2711 v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0];
2712 tlv->len = sizeof(*v);
2713 *v = dm->tdma;
2714 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
2715 } else if (ver->fcxtdma == 7 || ver->fcxtdma == 4) {
2716 tlv_v7 = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2717 tlv_v7->len = sizeof(dm->tdma);
2718 tlv_v7->ver = ver->fcxtdma;
2719 tlv_v7->type = CXPOLICY_TDMA;
2720 memcpy(tlv_v7->val, &dm->tdma, tlv_v7->len);
2721 btc->policy_len += BTC_TLV_HDR_LEN_V7 + tlv_v7->len;
2722 } else {
2723 tlv->len = sizeof(*v3);
2724 v3 = (struct rtw89_btc_fbtc_tdma_v3 *)&tlv->val[0];
2725 v3->fver = ver->fcxtdma;
2726 v3->tdma = dm->tdma;
2727 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v3);
2728 }
2729
2730 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2731 "[BTC], %s(): type:%d, rxflctrl=%d, txflctrl=%d, bind=%d, leak_n=%d, ext_ctrl=%d\n",
2732 __func__, dm->tdma.type, dm->tdma.rxflctrl,
2733 dm->tdma.txflctrl, dm->tdma.bind, dm->tdma.leak_n,
2734 dm->tdma.ext_ctrl);
2735 }
2736
_append_slot_v1(struct rtw89_dev * rtwdev)2737 static void _append_slot_v1(struct rtw89_dev *rtwdev)
2738 {
2739 struct rtw89_btc *btc = &rtwdev->btc;
2740 struct rtw89_btc_dm *dm = &btc->dm;
2741 struct rtw89_btc_btf_tlv *tlv = NULL;
2742 struct btc_fbtc_1slot *v = NULL;
2743 u16 len = 0;
2744 u8 i, cnt = 0;
2745
2746 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2747 "[BTC], %s(): A:btc->policy_len = %d\n",
2748 __func__, btc->policy_len);
2749
2750 for (i = 0; i < CXST_MAX; i++) {
2751 if (!btc->update_policy_force &&
2752 !memcmp(&dm->slot.v1[i], &dm->slot_now.v1[i],
2753 sizeof(dm->slot.v1[i])))
2754 continue;
2755
2756 len = btc->policy_len;
2757
2758 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
2759 v = (struct btc_fbtc_1slot *)&tlv->val[0];
2760 tlv->type = CXPOLICY_SLOT;
2761 tlv->len = sizeof(*v);
2762
2763 v->fver = btc->ver->fcxslots;
2764 v->sid = i;
2765 v->slot = dm->slot.v1[i];
2766
2767 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2768 "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n",
2769 __func__, i, dm->slot.v1[i].dur, dm->slot.v1[i].cxtbl,
2770 dm->slot.v1[i].cxtype);
2771 cnt++;
2772
2773 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
2774 }
2775
2776 if (cnt > 0)
2777 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2778 "[BTC], %s(): slot update (cnt=%d)!!\n",
2779 __func__, cnt);
2780 }
2781
_append_slot_v7(struct rtw89_dev * rtwdev)2782 static void _append_slot_v7(struct rtw89_dev *rtwdev)
2783 {
2784 struct rtw89_btc_btf_tlv_v7 *tlv = NULL;
2785 struct rtw89_btc *btc = &rtwdev->btc;
2786 struct rtw89_btc_dm *dm = &btc->dm;
2787 u8 i, cnt = 0;
2788 u16 len;
2789
2790 for (i = 0; i < CXST_MAX; i++) {
2791 if (!btc->update_policy_force &&
2792 !memcmp(&dm->slot.v7[i], &dm->slot_now.v7[i],
2793 sizeof(dm->slot.v7[i])))
2794 continue;
2795
2796 len = btc->policy_len;
2797
2798 if (!tlv) {
2799 if ((len + BTC_TLV_HDR_LEN_V7) > RTW89_BTC_POLICY_MAXLEN) {
2800 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2801 "[BTC], %s(): buff overflow!\n", __func__);
2802 break;
2803 }
2804
2805 tlv = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2806 tlv->type = CXPOLICY_SLOT;
2807 tlv->ver = btc->ver->fcxslots;
2808 tlv->len = sizeof(dm->slot.v7[0]) + BTC_TLV_SLOT_ID_LEN_V7;
2809 len += BTC_TLV_HDR_LEN_V7;
2810 }
2811
2812 if ((len + (u16)tlv->len) > RTW89_BTC_POLICY_MAXLEN) {
2813 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2814 "[BTC], %s(): buff overflow!\n", __func__);
2815 break;
2816 }
2817
2818 btc->policy[len] = i; /* slot-id */
2819 memcpy(&btc->policy[len + 1], &dm->slot.v7[i],
2820 sizeof(dm->slot.v7[0]));
2821 len += tlv->len;
2822
2823 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2824 "[BTC], %s: policy_len=%d, slot-%d: dur=%d, type=%d, table=0x%08x\n",
2825 __func__, btc->policy_len, i, dm->slot.v7[i].dur,
2826 dm->slot.v7[i].cxtype, dm->slot.v7[i].cxtbl);
2827 cnt++;
2828 btc->policy_len = len; /* update total length */
2829 }
2830
2831 if (cnt > 0)
2832 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2833 "[BTC], %s: slot update (cnt=%d, len=%d)!!\n",
2834 __func__, cnt, btc->policy_len);
2835 }
2836
_append_slot(struct rtw89_dev * rtwdev)2837 static void _append_slot(struct rtw89_dev *rtwdev)
2838 {
2839 struct rtw89_btc *btc = &rtwdev->btc;
2840
2841 if (btc->ver->fcxslots == 2 || btc->ver->fcxslots == 7)
2842 _append_slot_v7(rtwdev);
2843 else
2844 _append_slot_v1(rtwdev);
2845 }
2846
rtw89_btc_fw_rpt_ver(struct rtw89_dev * rtwdev,u32 rpt_map)2847 static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map)
2848 {
2849 struct rtw89_btc *btc = &rtwdev->btc;
2850 const struct rtw89_btc_ver *ver = btc->ver;
2851 u32 bit_map = 0;
2852
2853 switch (rpt_map) {
2854 case RPT_EN_TDMA:
2855 bit_map = BIT(0);
2856 break;
2857 case RPT_EN_CYCLE:
2858 bit_map = BIT(1);
2859 break;
2860 case RPT_EN_MREG:
2861 bit_map = BIT(2);
2862 break;
2863 case RPT_EN_BT_VER_INFO:
2864 bit_map = BIT(3);
2865 break;
2866 case RPT_EN_BT_SCAN_INFO:
2867 bit_map = BIT(4);
2868 break;
2869 case RPT_EN_BT_DEVICE_INFO:
2870 switch (ver->frptmap) {
2871 case 0:
2872 case 1:
2873 case 2:
2874 bit_map = BIT(6);
2875 break;
2876 case 3:
2877 case 4:
2878 case 5:
2879 case 105:
2880 bit_map = BIT(5);
2881 break;
2882 default:
2883 break;
2884 }
2885 break;
2886 case RPT_EN_BT_AFH_MAP:
2887 switch (ver->frptmap) {
2888 case 0:
2889 case 1:
2890 case 2:
2891 bit_map = BIT(5);
2892 break;
2893 case 3:
2894 case 4:
2895 case 5:
2896 case 105:
2897 bit_map = BIT(6);
2898 break;
2899 default:
2900 break;
2901 }
2902 break;
2903 case RPT_EN_BT_AFH_MAP_LE:
2904 switch (ver->frptmap) {
2905 case 2:
2906 bit_map = BIT(8);
2907 break;
2908 case 3:
2909 case 4:
2910 case 5:
2911 case 105:
2912 bit_map = BIT(7);
2913 break;
2914 default:
2915 break;
2916 }
2917 break;
2918 case RPT_EN_BT_TX_PWR_LVL:
2919 switch (ver->frptmap) {
2920 case 0:
2921 case 1:
2922 case 2:
2923 case 3:
2924 case 105:
2925 break;
2926 case 4:
2927 case 5:
2928 bit_map = BIT(8);
2929 break;
2930 default:
2931 break;
2932 }
2933 break;
2934 case RPT_EN_FW_STEP_INFO:
2935 switch (ver->frptmap) {
2936 case 1:
2937 case 2:
2938 bit_map = BIT(7);
2939 break;
2940 case 3:
2941 case 105:
2942 bit_map = BIT(8);
2943 break;
2944 case 4:
2945 case 5:
2946 bit_map = BIT(9);
2947 break;
2948 default:
2949 break;
2950 }
2951 break;
2952 case RPT_EN_TEST:
2953 if (ver->frptmap == 5)
2954 bit_map = BIT(10);
2955 else if (ver->frptmap == 105)
2956 bit_map = BIT(9);
2957 else
2958 bit_map = BIT(31);
2959 break;
2960 case RPT_EN_WL_ALL:
2961 switch (ver->frptmap) {
2962 case 0:
2963 case 1:
2964 case 2:
2965 bit_map = GENMASK(2, 0);
2966 break;
2967 case 3:
2968 case 105:
2969 bit_map = GENMASK(2, 0) | BIT(8);
2970 break;
2971 case 4:
2972 case 5:
2973 bit_map = GENMASK(2, 0) | BIT(9);
2974 break;
2975 default:
2976 break;
2977 }
2978 break;
2979 case RPT_EN_BT_ALL:
2980 switch (ver->frptmap) {
2981 case 0:
2982 case 1:
2983 bit_map = GENMASK(6, 3);
2984 break;
2985 case 2:
2986 bit_map = GENMASK(6, 3) | BIT(8);
2987 break;
2988 case 3:
2989 case 105:
2990 bit_map = GENMASK(7, 3);
2991 break;
2992 case 4:
2993 case 5:
2994 bit_map = GENMASK(8, 3);
2995 break;
2996 default:
2997 break;
2998 }
2999 break;
3000 case RPT_EN_ALL:
3001 switch (ver->frptmap) {
3002 case 0:
3003 bit_map = GENMASK(6, 0);
3004 break;
3005 case 1:
3006 bit_map = GENMASK(7, 0);
3007 break;
3008 case 2:
3009 case 3:
3010 bit_map = GENMASK(8, 0);
3011 break;
3012 case 4:
3013 case 5:
3014 case 105:
3015 bit_map = GENMASK(9, 0);
3016 break;
3017 default:
3018 break;
3019 }
3020 break;
3021 case RPT_EN_MONITER:
3022 switch (ver->frptmap) {
3023 case 0:
3024 case 1:
3025 bit_map = GENMASK(6, 2);
3026 break;
3027 case 2:
3028 bit_map = GENMASK(6, 2) | BIT(8);
3029 break;
3030 case 3:
3031 case 105:
3032 bit_map = GENMASK(8, 2);
3033 break;
3034 case 4:
3035 case 5:
3036 bit_map = GENMASK(9, 2);
3037 break;
3038 default:
3039 break;
3040 }
3041 break;
3042 }
3043
3044 return bit_map;
3045 }
3046
rtw89_btc_fw_set_slots(struct rtw89_dev * rtwdev)3047 static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev)
3048 {
3049 struct rtw89_btc *btc = &rtwdev->btc;
3050 const struct rtw89_btc_ver *ver = btc->ver;
3051 struct rtw89_btc_btf_tlv_v7 *tlv_v7 = NULL;
3052 struct rtw89_btc_btf_set_slot_table *tbl;
3053 struct rtw89_btc_dm *dm = &btc->dm;
3054 u16 n, len;
3055
3056 if (ver->fcxslots == 2 || ver->fcxslots == 7) {
3057 len = sizeof(*tlv_v7) + sizeof(dm->slot.v7);
3058 tlv_v7 = kmalloc(len, GFP_KERNEL);
3059 if (!tlv_v7)
3060 return;
3061
3062 tlv_v7->type = SET_SLOT_TABLE;
3063 tlv_v7->ver = ver->fcxslots;
3064 tlv_v7->len = ARRAY_SIZE(dm->slot.v7);
3065 memcpy(tlv_v7->val, dm->slot.v7, sizeof(dm->slot.v7));
3066
3067 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, (u8 *)tlv_v7, len);
3068
3069 kfree(tlv_v7);
3070 } else {
3071 n = struct_size(tbl, tbls, CXST_MAX);
3072 tbl = kmalloc(n, GFP_KERNEL);
3073 if (!tbl)
3074 return;
3075
3076 tbl->fver = BTF_SET_SLOT_TABLE_VER;
3077 tbl->tbl_num = CXST_MAX;
3078 memcpy(tbl->tbls, dm->slot.v1, flex_array_size(tbl, tbls, CXST_MAX));
3079
3080 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
3081
3082 kfree(tbl);
3083 }
3084 }
3085
rtw89_btc_fw_en_rpt(struct rtw89_dev * rtwdev,bool force_exec,u32 rpt_map)3086 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
3087 bool force_exec, u32 rpt_map)
3088 {
3089 struct rtw89_btc *btc = &rtwdev->btc;
3090 struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo;
3091 union rtw89_fbtc_rtp_ctrl r;
3092 int ret;
3093 u32 i;
3094
3095 if (!force_exec && rpt_map == fwinfo->rpt_en_map)
3096 return;
3097
3098 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rpt_map=%x\n",
3099 __func__, fwinfo->rpt_en_map);
3100
3101 if (btc->ver->fcxbtcrpt == 7 ||
3102 btc->ver->fcxbtcrpt == 8 ||
3103 btc->ver->fcxbtcrpt == 9 ||
3104 btc->ver->fcxbtcrpt == 11) {
3105 r.v8.type = SET_REPORT_EN;
3106 r.v8.fver = btc->ver->fcxbtcrpt;
3107 r.v8.len = sizeof(r.v8.map);
3108 r.v8.map = cpu_to_le32(rpt_map);
3109 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v8,
3110 sizeof(r.v8));
3111 } else {
3112 if (btc->ver->fcxbtcrpt == 105)
3113 r.v1.fver = 5;
3114 else
3115 r.v1.fver = btc->ver->fcxbtcrpt;
3116
3117 for (i = 0; i < RPT_EN_MONITER; i++) {
3118 r.v1.enable = cpu_to_le32(i);
3119 if (rpt_map & BIT(i))
3120 r.v1.para = cpu_to_le32(1);
3121 else
3122 r.v1.para = 0;
3123
3124 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN,
3125 &r.v1, sizeof(r.v1));
3126 }
3127 }
3128
3129 if (!ret)
3130 fwinfo->rpt_en_map = rpt_map;
3131 }
3132
btc_fw_set_monreg(struct rtw89_dev * rtwdev)3133 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
3134 {
3135 const struct rtw89_chip_info *chip = rtwdev->chip;
3136 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
3137 struct rtw89_btc_btf_set_mon_reg_v1 *v1 = NULL;
3138 struct rtw89_btc_btf_set_mon_reg_v7 *v7 = NULL;
3139 u8 i, n, ulen, cxmreg_max;
3140 u16 sz = 0;
3141
3142 n = chip->mon_reg_num;
3143 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3144 "[BTC], %s(): mon_reg_num=%d\n", __func__, n);
3145
3146 if (ver->fcxmreg == 1)
3147 cxmreg_max = CXMREG_MAX;
3148 else
3149 cxmreg_max = CXMREG_MAX_V2;
3150
3151 if (n > cxmreg_max) {
3152 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3153 "[BTC], %s(): mon reg count %d > %d\n",
3154 __func__, n, cxmreg_max);
3155 return;
3156 }
3157
3158 ulen = sizeof(struct rtw89_btc_fbtc_mreg);
3159
3160 if (ver->fcxmreg == 7) {
3161 sz = struct_size(v7, regs, n);
3162 v7 = kmalloc(sz, GFP_KERNEL);
3163 if (!v7)
3164 return;
3165 v7->type = RPT_EN_MREG;
3166 v7->fver = ver->fcxmreg;
3167 v7->len = n;
3168 for (i = 0; i < n; i++) {
3169 v7->regs[i].type = chip->mon_reg[i].type;
3170 v7->regs[i].bytes = chip->mon_reg[i].bytes;
3171 v7->regs[i].offset = chip->mon_reg[i].offset;
3172 }
3173
3174 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v7, sz);
3175 kfree(v7);
3176 } else {
3177 sz = struct_size(v1, regs, n);
3178 v1 = kmalloc(sz, GFP_KERNEL);
3179 if (!v1)
3180 return;
3181 v1->fver = ver->fcxmreg;
3182 v1->reg_num = n;
3183 memcpy(v1->regs, chip->mon_reg, flex_array_size(v1, regs, n));
3184
3185 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v1, sz);
3186 kfree(v1);
3187 }
3188
3189 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3190 "[BTC], %s(): sz=%d ulen=%d n=%d\n",
3191 __func__, sz, ulen, n);
3192 }
3193
_update_dm_step(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason_or_action)3194 static void _update_dm_step(struct rtw89_dev *rtwdev,
3195 enum btc_reason_and_action reason_or_action)
3196 {
3197 struct rtw89_btc *btc = &rtwdev->btc;
3198 struct rtw89_btc_dm *dm = &btc->dm;
3199
3200 /* use ring-structure to store dm step */
3201 dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action;
3202 dm->dm_step.step_pos++;
3203
3204 if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) {
3205 dm->dm_step.step_pos = 0;
3206 dm->dm_step.step_ov = true;
3207 }
3208 }
3209
_fw_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)3210 static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
3211 enum btc_reason_and_action action)
3212 {
3213 struct rtw89_btc *btc = &rtwdev->btc;
3214 struct rtw89_btc_dm *dm = &btc->dm;
3215 int ret;
3216
3217 dm->run_action = action;
3218
3219 _update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT);
3220 _update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT);
3221
3222 btc->policy_len = 0;
3223 btc->policy_type = policy_type;
3224
3225 _append_tdma(rtwdev);
3226 _append_slot(rtwdev);
3227
3228 if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN)
3229 return;
3230
3231 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3232 "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n",
3233 __func__, action, policy_type, btc->policy_len);
3234
3235 if (dm->tdma.rxflctrl == CXFLC_NULLP ||
3236 dm->tdma.rxflctrl == CXFLC_QOSNULL)
3237 btc->btc_ctrl_lps = 1;
3238 else
3239 btc->btc_ctrl_lps = dm->lps_ctrl_scbd;
3240
3241 if (btc->btc_ctrl_lps == 1)
3242 rtw89_set_coex_ctrl_lps(rtwdev, btc->btc_ctrl_lps);
3243
3244 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY,
3245 btc->policy, btc->policy_len);
3246 if (!ret) {
3247 memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now));
3248 if (btc->ver->fcxslots == 2 || btc->ver->fcxslots == 7)
3249 memcpy(&dm->slot_now.v7, &dm->slot.v7, sizeof(dm->slot_now.v7));
3250 else
3251 memcpy(&dm->slot_now.v1, &dm->slot.v1, sizeof(dm->slot_now.v1));
3252 }
3253
3254 if (btc->update_policy_force)
3255 btc->update_policy_force = false;
3256
3257 if (btc->btc_ctrl_lps == 0)
3258 rtw89_set_coex_ctrl_lps(rtwdev, btc->btc_ctrl_lps);
3259 }
3260
_get_gpiosig_for_ver(struct rtw89_dev * rtwdev,u8 sig_v8)3261 static u8 _get_gpiosig_for_ver(struct rtw89_dev *rtwdev, u8 sig_v8)
3262 {
3263 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
3264
3265 /* v8: gpio_ver >= 8, directly use v8 signal ID */
3266 if (ver->fcxgpiodbg >= 8)
3267 return sig_v8;
3268
3269 /* v7: gpio_ver < 8, convert v8 signal ID to v7 signal ID */
3270 if (sig_v8 <= BTC_DBG_GNT_WL) {
3271 return sig_v8;
3272 } else if (sig_v8 <= BTC_DBG_GNT_WL1) {
3273 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3274 "[BTC], %s(): sig %d not supported in v7\n",
3275 __func__, sig_v8);
3276 return BTC_DBG_NUM;
3277 } else if (sig_v8 >= BTC_DBG_NUM) {
3278 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3279 "[BTC], %s(): sig %d not available\n",
3280 __func__, sig_v8);
3281 return BTC_DBG_NUM;
3282 } else {
3283 return sig_v8 - 2;
3284 }
3285 }
3286
_convert_gpio_enmap_to_ver(struct rtw89_dev * rtwdev,u32 en_map_v8)3287 static u32 _convert_gpio_enmap_to_ver(struct rtw89_dev *rtwdev, u32 en_map_v8)
3288 {
3289 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
3290 u32 en_map_v7 = 0;
3291 u32 bit;
3292
3293 /* v8: gpio_ver >= 8, directly use v8 en_map */
3294 if (ver->fcxgpiodbg >= 8)
3295 return en_map_v8;
3296
3297 /* v7: gpio_ver < 8, convert v8 en_map bitmap to v7 en_map bitmap */
3298 /* bit 0-1: GNT_BT, GNT_WL - same position in both versions */
3299 en_map_v7 |= en_map_v8 & GENMASK(1, 0);
3300
3301 /* bit 2-3: GNT_BT1, GNT_WL1 - not supported in v7, skip these bits */
3302
3303 /* bit 4-31: shift right by 2 positions (become bit 2-29 in v7) */
3304 for (bit = BTC_DBG_BCN_EARLY; bit < BTC_DBG_NUM; bit++) {
3305 if (en_map_v8 & BIT(bit))
3306 en_map_v7 |= BIT(bit - 2);
3307 }
3308
3309 return en_map_v7;
3310 }
3311
_convert_gpio_enmap_from_ver(struct rtw89_dev * rtwdev,u32 en_map)3312 static u32 _convert_gpio_enmap_from_ver(struct rtw89_dev *rtwdev, u32 en_map)
3313 {
3314 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
3315 u32 en_map_v8 = 0;
3316 u32 bit;
3317
3318 if (ver->fcxgpiodbg >= 8)
3319 return en_map;
3320
3321 /* bit 0-1: GNT_BT, GNT_WL - same position in both versions */
3322 en_map_v8 |= en_map & GENMASK(1, 0);
3323
3324 /* bit 2-29: shift left by 2 positions (become bit 4-31 in v8) */
3325 for (bit = BTC_DBG_GNT_BT1; bit < BTC_DBG_NUM - 2; bit++) {
3326 if (en_map & BIT(bit))
3327 en_map_v8 |= BIT(bit + 2);
3328 }
3329
3330 return en_map_v8;
3331 }
3332
_fw_set_gpio(struct rtw89_dev * rtwdev,u8 type,u32 val)3333 static void _fw_set_gpio(struct rtw89_dev *rtwdev, u8 type, u32 val)
3334 {
3335 struct rtw89_btc *btc = &rtwdev->btc;
3336 struct rtw89_fbtc_h2c_set_gpio *gpio = &btc->gpio;
3337 const struct rtw89_btc_ver *ver = btc->ver;
3338 struct rtw89_fbtc_h2c_set_gpio_2b l2_h2c;
3339 struct rtw89_fbtc_h2c_set_gpio_4b l4_h2c;
3340 u8 gpio_ver = ver->fcxgpiodbg;
3341 u8 buf[sizeof(l4_h2c)];
3342 u8 len;
3343
3344 if (gpio_ver < 8 && type > CXDGPIO_MUX_MAP)
3345 return;
3346
3347 if (type >= CXDGPIO_MAX)
3348 return;
3349
3350 switch (type) {
3351 case CXDGPIO_EN_MAP: /* GPIO debug signal en-map 0~31 */
3352 val = _convert_gpio_enmap_to_ver(rtwdev, val);
3353 gpio->en_map.data.type = CXDGPIO_EN_MAP;
3354 gpio->en_map.data.fver = gpio_ver;
3355 gpio->en_map.data.dlen = CXDGPIO_SET_L4;
3356 gpio->en_map.data.en_map = val;
3357 l4_h2c = gpio->en_map.fmt;
3358 put_unaligned_le32(val, (u32 *)l4_h2c.data);
3359 memcpy(buf, &l4_h2c, sizeof(l4_h2c));
3360 len = sizeof(l4_h2c);
3361 break;
3362 case CXDGPIO_MUX_MAP: /* GPIO dbg: Signal to GPIO Mux */
3363 gpio->mux.data.type = CXDGPIO_MUX_MAP;
3364 gpio->mux.data.fver = gpio_ver;
3365 gpio->mux.data.dlen = CXDGPIO_SET_L2;
3366 gpio->mux.data.sig = _get_gpiosig_for_ver(rtwdev,
3367 FIELD_GET(GENMASK(7, 0), val));
3368 if (gpio->mux.data.sig == 0xff)
3369 return;
3370 gpio->mux.data.gpio = FIELD_GET(GENMASK(15, 8), val);
3371 l2_h2c = gpio->mux.fmt;
3372 memcpy(buf, &l2_h2c, sizeof(l2_h2c));
3373 len = sizeof(l2_h2c);
3374 break;
3375 case CXDGPIO_EXT_HPTA: /* GPIO config for Ext HW-PTA */
3376 gpio->ext_pta.data.type = CXDGPIO_EXT_HPTA;
3377 gpio->ext_pta.data.fver = gpio_ver;
3378 gpio->ext_pta.data.dlen = CXDGPIO_SET_L2;
3379 gpio->ext_pta.data.map_low = FIELD_GET(GENMASK(7, 0), val);
3380 gpio->ext_pta.data.map_high = FIELD_GET(GENMASK(15, 8), val);
3381 l2_h2c = gpio->ext_pta.fmt;
3382 memcpy(buf, &l2_h2c, sizeof(l2_h2c));
3383 len = sizeof(l2_h2c);
3384 break;
3385 case CXDGPIO_EXT_HMBX: /* GPIO config for Ext HW-mailbox */
3386 gpio->ext_mb.data.type = CXDGPIO_EXT_HMBX;
3387 gpio->ext_mb.data.fver = gpio_ver;
3388 gpio->ext_mb.data.dlen = CXDGPIO_SET_L2;
3389 gpio->ext_mb.data.map_low = FIELD_GET(GENMASK(7, 0), val);
3390 gpio->ext_mb.data.map_high = FIELD_GET(GENMASK(15, 8), val);
3391 l2_h2c = gpio->ext_mb.fmt;
3392 memcpy(buf, &l2_h2c, sizeof(l2_h2c));
3393 len = sizeof(l2_h2c);
3394 break;
3395 case CXDGPIO_EXT_SWOUT: /* GPIO config for Ext SW output (wlan_act) */
3396 gpio->ext_swout.data.type = CXDGPIO_EXT_SWOUT;
3397 gpio->ext_swout.data.fver = gpio_ver;
3398 gpio->ext_swout.data.dlen = CXDGPIO_SET_L2;
3399 gpio->ext_swout.data.map_low = FIELD_GET(GENMASK(7, 0), val);
3400 gpio->ext_swout.data.map_high = FIELD_GET(GENMASK(15, 8), val);
3401 l2_h2c = gpio->ext_swout.fmt;
3402 memcpy(buf, &l2_h2c, sizeof(l2_h2c));
3403 len = sizeof(l2_h2c);
3404 break;
3405 case CXDGPIO_EXT_SWIN: /* GPIO config for Ext SW input control */
3406 gpio->ext_swin.data.type = CXDGPIO_EXT_SWIN;
3407 gpio->ext_swin.data.fver = gpio_ver;
3408 gpio->ext_swin.data.dlen = CXDGPIO_SET_L4;
3409 gpio->ext_swin.data.in_map_low = FIELD_GET(GENMASK(7, 0), val);
3410 gpio->ext_swin.data.in_map_high = FIELD_GET(GENMASK(15, 8), val);
3411 gpio->ext_swin.data.int_map_low = FIELD_GET(GENMASK(23, 16), val);
3412 gpio->ext_swin.data.int_map_high = FIELD_GET(GENMASK(31, 24), val);
3413 l4_h2c = gpio->ext_swin.fmt;
3414 put_unaligned_le32(val, (u32 *)l4_h2c.data);
3415 memcpy(buf, &l4_h2c, sizeof(l4_h2c));
3416 len = sizeof(l4_h2c);
3417 break;
3418 default:
3419 return;
3420 }
3421
3422 _send_fw_cmd(rtwdev, BTFC_SET, SET_GPIO_DBG, buf, len);
3423 }
3424
_set_ext_interface(struct rtw89_dev * rtwdev)3425 static void _set_ext_interface(struct rtw89_dev *rtwdev)
3426 {
3427 struct rtw89_btc *btc = &rtwdev->btc;
3428 struct rtw89_btc_cx *cx = &btc->cx;
3429 u8 bt1_sw_type = BTC_SWITCH_INTERNAL;
3430 u32 val;
3431
3432 if (btc->ver->fcxgpiodbg < 7)
3433 return;
3434
3435 /* if BT1+WL-S0, route DBG_GNT_BT1 to control SPDT */
3436 if ((rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) &&
3437 btc->ver->fcxinit >= 10) {
3438 if (btc->ver->fcxinit >= 10)
3439 bt1_sw_type = btc->mdinfo.bt1_sw_type;
3440 else
3441 return;
3442
3443 if (bt1_sw_type > BTC_SWITCH_INTERNAL) {
3444 _fw_set_gpio(rtwdev, CXDGPIO_EN_MAP,
3445 BIT(BTC_DBG_GNT_BT1));
3446
3447 val = (bt1_sw_type << 8) + BTC_DBG_GNT_BT1;
3448 _fw_set_gpio(rtwdev, CXDGPIO_MUX_MAP, val);
3449 }
3450 }
3451
3452 /* set GPIO as Ext-PTA interface wire */
3453 if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_PTA)
3454 _fw_set_gpio(rtwdev, CXDGPIO_EXT_HPTA, cx->bt_ext.hpta_cfg);
3455
3456 /* set GPIO as Ext-mailbox interface wire */
3457 if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_MBX)
3458 _fw_set_gpio(rtwdev, CXDGPIO_EXT_HMBX, cx->bt_ext.hmbx_cfg);
3459
3460 /* set GPIO as Ext-SWIO interface wire */
3461 if (cx->bt_ext.hw_coex & BTC_EXTSOC_INTF_SWIO) {
3462 _fw_set_gpio(rtwdev, CXDGPIO_EXT_SWOUT, cx->bt_ext.swout_cfg);
3463 _fw_set_gpio(rtwdev, CXDGPIO_EXT_SWIN, cx->bt_ext.swin_cfg);
3464 }
3465 }
3466
_fw_set_drv_info(struct rtw89_dev * rtwdev,u8 index)3467 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 index)
3468 {
3469 struct rtw89_btc *btc = &rtwdev->btc;
3470 const struct rtw89_btc_ver *ver = btc->ver;
3471
3472 switch (index) {
3473 case CXDRVINFO_INIT:
3474 if (ver->fcxinit == 7 || ver->fcxinit == 107)
3475 rtw89_fw_h2c_cxdrv_init_v7(rtwdev, index);
3476 else if (ver->fcxinit == 10)
3477 rtw89_fw_h2c_cxdrv_init_v10(rtwdev, index);
3478 else if (ver->fcxinit == 11)
3479 rtw89_fw_h2c_cxdrv_init_v11(rtwdev, index);
3480 else
3481 rtw89_fw_h2c_cxdrv_init(rtwdev, index);
3482 break;
3483 case CXDRVINFO_ROLE:
3484 if (ver->fwlrole == 0)
3485 rtw89_fw_h2c_cxdrv_role(rtwdev, index);
3486 else if (ver->fwlrole == 1)
3487 rtw89_fw_h2c_cxdrv_role_v1(rtwdev, index);
3488 else if (ver->fwlrole == 101)
3489 rtw89_fw_h2c_cxdrv_role_v101(rtwdev, index);
3490 else if (ver->fwlrole == 2)
3491 rtw89_fw_h2c_cxdrv_role_v2(rtwdev, index);
3492 else if (ver->fwlrole == 7)
3493 rtw89_fw_h2c_cxdrv_role_v7(rtwdev, index);
3494 else if (ver->fwlrole == 8)
3495 rtw89_fw_h2c_cxdrv_role_v8(rtwdev, index);
3496 else if (ver->fwlrole == 10)
3497 rtw89_fw_h2c_cxdrv_role_v10(rtwdev, index);
3498 break;
3499 case CXDRVINFO_CTRL:
3500 if (ver->drvinfo_ver != 0)
3501 index = 2;
3502
3503 if (ver->fcxctrl == 7)
3504 rtw89_fw_h2c_cxdrv_ctrl_v7(rtwdev, index);
3505 else if (ver->fcxctrl == 9)
3506 rtw89_fw_h2c_cxdrv_ctrl_v9(rtwdev, index);
3507 else
3508 rtw89_fw_h2c_cxdrv_ctrl(rtwdev, index);
3509 break;
3510 case CXDRVINFO_TRX:
3511 if (ver->drvinfo_ver > 1)
3512 index = 3;
3513
3514 if (ver->fcxtrx == 0)
3515 return;
3516
3517 if (ver->fcxtrx == 7)
3518 rtw89_fw_h2c_cxdrv_trx_v7(rtwdev, index);
3519 else if (ver->fcxtrx == 9)
3520 rtw89_fw_h2c_cxdrv_trx_v9(rtwdev, index);
3521 else if (ver->fcxtrx == 107)
3522 rtw89_fw_h2c_cxdrv_trx_v107(rtwdev, index);
3523 break;
3524 case CXDRVINFO_RFK:
3525 if (ver->drvinfo_ver != 0)
3526 return;
3527
3528 rtw89_fw_h2c_cxdrv_rfk(rtwdev, index);
3529 break;
3530 case CXDRVINFO_TXPWR:
3531 if (ver->drvinfo_ver == 3 || ver->drvinfo_ver == 103)
3532 index = 4;
3533
3534 if (ver->fcxtrx == 7 || ver->fcxtrx == 107)
3535 rtw89_fw_h2c_cxtxpwr_v7(rtwdev, index);
3536 else if (ver->fcxtrx == 9)
3537 rtw89_fw_h2c_cxtxpwr_v9(rtwdev, index);
3538 break;
3539 case CXDRVINFO_FDDT:
3540 if (ver->drvinfo_ver == 3 || ver->drvinfo_ver == 103)
3541 index = 5;
3542 else
3543 return;
3544
3545 break;
3546 case CXDRVINFO_MLO:
3547 if (!ver->fcxmlo || ver->drvinfo_ver == 103)
3548 return;
3549
3550 if (ver->drvinfo_ver == 3)
3551 index = 6;
3552 else
3553 return;
3554
3555 if (ver->fcxmlo == 2)
3556 rtw89_fw_h2c_cxdrv_mlo_v2(rtwdev, index);
3557
3558 break;
3559 case CXDRVINFO_OSI:
3560 if (!ver->fcxosi || ver->drvinfo_ver == 103)
3561 return;
3562
3563 if (ver->drvinfo_ver == 3)
3564 index = 7;
3565 else
3566 return;
3567
3568 if (ver->fcxosi == 1)
3569 rtw89_fw_h2c_cxdrv_osi_info(rtwdev, index);
3570 else if (ver->fcxosi == 6)
3571 rtw89_fw_h2c_cxdrv_osi_info_v6(rtwdev, index);
3572 else
3573 return;
3574 break;
3575 default:
3576 break;
3577 }
3578 }
3579
3580 static
btc_fw_event(struct rtw89_dev * rtwdev,u8 evt_id,void * data,u32 len)3581 void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len)
3582 {
3583 struct rtw89_btc *btc = &rtwdev->btc;
3584 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
3585 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
3586 u8 i;
3587
3588 _parse_btc_report(rtwdev, pfwinfo, data, len);
3589
3590 if (!rtwdev->chip->scbd)
3591 return;
3592
3593 if (!btc->dm.scbd_b2w_update)
3594 return; /* skip if init or no-update */
3595
3596 for (i = BTC_BT_1ST; i <= BTC_BT_2ND; i++) {
3597 bt = (i == BTC_BT_1ST) ? &btc->cx.bt0 : &btc->cx.bt1;
3598
3599 if (bt->scbd_c2h != bt->scbd_rb) {
3600 /* if btx b2w scbd non-sync */
3601 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3602 "[BTC], %s() bt%d:c2h->0x%08x, rb->0x%08x\n",
3603 __func__, i, bt->scbd_c2h, bt->scbd_rb);
3604 bt->scbd_c2h = bt->scbd_rb;
3605 _update_bt_scbd(rtwdev, i);
3606 btc->dm.scbd_b2w_update = false;
3607 }
3608 }
3609
3610 if (!btc->dm.scbd_b2w_update)
3611 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
3612 else
3613 btc->dm.scbd_b2w_update = 0;
3614 }
3615
_set_gnt(struct rtw89_dev * rtwdev,u8 phy_map,u8 wl_state,u8 bt_state,u8 wlact_state)3616 static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map,
3617 u8 wl_state, u8 bt_state, u8 wlact_state)
3618 {
3619 struct rtw89_btc *btc = &rtwdev->btc;
3620 struct rtw89_btc_dm *dm = &btc->dm;
3621 struct rtw89_btc_fbtc_outsrc_set_info *o = &dm->ost_info;
3622 struct rtw89_mac_ax_wl_act *wlact_set;
3623 struct rtw89_mac_ax_coex_gnt mg;
3624 u8 i;
3625
3626 if (phy_map > BTC_PHY_ALL)
3627 return;
3628
3629 for (i = 0; i < RTW89_PHY_NUM; i++) {
3630 if (!(phy_map & BIT(i)))
3631 continue;
3632
3633 switch (wl_state) {
3634 case BTC_GNT_HW:
3635 dm->gnt_set[i].gnt_wl_sw_en = 0;
3636 dm->gnt_set[i].gnt_wl = 0;
3637 break;
3638 case BTC_GNT_SW_LO:
3639 dm->gnt_set[i].gnt_wl_sw_en = 1;
3640 dm->gnt_set[i].gnt_wl = 0;
3641 break;
3642 case BTC_GNT_SW_HI:
3643 dm->gnt_set[i].gnt_wl_sw_en = 1;
3644 dm->gnt_set[i].gnt_wl = 1;
3645 break;
3646 case BTC_GNT_SET_SKIP:
3647 default:
3648 break;
3649 }
3650
3651 switch (bt_state) {
3652 case BTC_GNT_HW:
3653 dm->gnt_set[i].gnt_bt0_sw_en = 0;
3654 dm->gnt_set[i].gnt_bt0 = 0;
3655 dm->gnt_set[i].gnt_bt1_sw_en = 0;
3656 dm->gnt_set[i].gnt_bt1 = 0;
3657 dm->gnt_set[i].gnt_zb_sw_en = 0;
3658 dm->gnt_set[i].gnt_zb = 0;
3659 break;
3660 case BTC_GNT_SW_LO:
3661 dm->gnt_set[i].gnt_bt0_sw_en = 1;
3662 dm->gnt_set[i].gnt_bt0 = 0;
3663 dm->gnt_set[i].gnt_bt1_sw_en = 1;
3664 dm->gnt_set[i].gnt_bt1 = 0;
3665 dm->gnt_set[i].gnt_zb_sw_en = 1;
3666 dm->gnt_set[i].gnt_zb = 0;
3667 break;
3668 case BTC_GNT_SW_HI:
3669 dm->gnt_set[i].gnt_bt0_sw_en = 1;
3670 dm->gnt_set[i].gnt_bt0 = 1;
3671 dm->gnt_set[i].gnt_bt1_sw_en = 1;
3672 dm->gnt_set[i].gnt_bt1 = 1;
3673 dm->gnt_set[i].gnt_zb_sw_en = 1;
3674 dm->gnt_set[i].gnt_zb = 1;
3675 break;
3676 case BTC_GNT_SET_SKIP:
3677 default:
3678 break;
3679 }
3680 }
3681
3682 for (i = 0; i < BTC_ALL_BT_EZL; i++) {
3683 if (!(rtwdev->chip->para_ver & BTC_FEAT_WLAN_ACT_MUX))
3684 break;
3685
3686 switch (wlact_state) {
3687 case BTC_WLACT_HW:
3688 dm->wlact_set[i].wlan_act_en = 0;
3689 dm->wlact_set[i].wlan_act = 0;
3690 break;
3691 case BTC_WLACT_SW_LO:
3692 dm->wlact_set[i].wlan_act_en = 1;
3693 dm->wlact_set[i].wlan_act = 0;
3694 break;
3695 case BTC_WLACT_SW_HI:
3696 dm->wlact_set[i].wlan_act_en = 1;
3697 dm->wlact_set[i].wlan_act = 1;
3698 break;
3699 default:
3700 break;
3701 }
3702
3703 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))
3704 break;
3705 }
3706
3707 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3708 "[BTC], %s(): phy_map=0x%x, gnt_wl:%d, gnt_bt:%d, wl_act:%d\n",
3709 __func__, phy_map, wl_state, bt_state, wlact_state);
3710
3711 if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO) {
3712 if (o->rf_band[BTC_RF_S0] == 1 && o->rf_band[BTC_RF_S1] == 0)
3713 o->rf_gbt_source = BTC_RF_S1;
3714 else
3715 o->rf_gbt_source = BTC_RF_S0;
3716
3717 memcpy(o->wlact_set, dm->wlact_set, sizeof(o->wlact_set));
3718
3719 if (btc->ver->fcxosi == 6) {
3720 memcpy(o->gnt_set_be, dm->gnt_set, sizeof(o->gnt_set_be));
3721 return;
3722 } else if (btc->ver->fcxosi == 1) {
3723 for (i = 0; i < RTW89_PHY_NUM; i++) { /* gnt[MAC0/MAC1] */
3724 mg.band[i].gnt_bt_sw_en = dm->gnt_set[i].gnt_bt0_sw_en;
3725 mg.band[i].gnt_bt = dm->gnt_set[i].gnt_bt0;
3726 mg.band[i].gnt_wl_sw_en = dm->gnt_set[i].gnt_wl_sw_en;
3727 mg.band[i].gnt_wl = dm->gnt_set[i].gnt_wl;
3728 memcpy(o->gnt_set, mg.band, sizeof(o->gnt_set));
3729 }
3730 return;
3731 }
3732 }
3733
3734 for (i = 0; i < RTW89_PHY_NUM; i++) { /* gnt[MAC0/MAC1] */
3735 mg.band[i].gnt_bt_sw_en = dm->gnt_set[i].gnt_bt0_sw_en;
3736 mg.band[i].gnt_bt = dm->gnt_set[i].gnt_bt0;
3737 mg.band[i].gnt_wl_sw_en = dm->gnt_set[i].gnt_wl_sw_en;
3738 mg.band[i].gnt_wl = dm->gnt_set[i].gnt_wl;
3739 }
3740 for (i = 0; i < BTC_ALL_BT; i++) { /* wlact[BT0/BT1] */
3741 wlact_set = &dm->wlact_set[i];
3742 mg.bt[i].wlan_act_en = wlact_set->wlan_act_en;
3743 mg.bt[i].wlan_act = wlact_set->wlan_act;
3744 }
3745
3746 rtw89_chip_mac_cfg_gnt(rtwdev, &mg);
3747 }
3748
3749 #define BTC_TDMA_WLROLE_MAX 3
3750
_set_bt_ignore_wlan_act(struct rtw89_dev * rtwdev,u8 enable)3751 static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable)
3752 {
3753 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3754 "[BTC], %s(): set bt %s wlan_act\n", __func__,
3755 enable ? "ignore" : "do not ignore");
3756
3757 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1);
3758 }
3759
3760 #define WL_TX_POWER_NO_BTC_CTRL GENMASK(31, 0)
3761 #define WL_TX_POWER_ALL_TIME GENMASK(15, 0)
3762 #define WL_TX_POWER_WITH_BT GENMASK(31, 16)
3763 #define WL_TX_POWER_INT_PART GENMASK(8, 2)
3764 #define WL_TX_POWER_FRA_PART GENMASK(1, 0)
3765 #define B_BTC_WL_TX_POWER_SIGN BIT(7)
3766 #define B_TSSI_WL_TX_POWER_SIGN BIT(8)
3767 #define SET_RF_PARA_AX_LEN 1
3768
_set_wl_tx_power(struct rtw89_dev * rtwdev,u32 level,u8 phy_map)3769 static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level, u8 phy_map)
3770 {
3771 const struct rtw89_chip_info *chip = rtwdev->chip;
3772 struct rtw89_btc *btc = &rtwdev->btc;
3773 const struct rtw89_btc_ver *ver = btc->ver;
3774 struct rtw89_btc_dm *dm = &btc->dm;
3775 bool level_chg = false;
3776 u32 pwr_val;
3777
3778 if (phy_map & BIT(RTW89_PHY_0))
3779 level_chg = !(dm->rf_trx_para.wl_tx_power[RTW89_PHY_0] == level);
3780
3781 if (phy_map & BIT(RTW89_PHY_1))
3782 level_chg |= !(dm->rf_trx_para.wl_tx_power[RTW89_PHY_1] == level);
3783
3784 if (!level_chg && !btc->cli_h2c_cmd)
3785 return;
3786
3787 if (phy_map & BIT(RTW89_PHY_0))
3788 dm->rf_trx_para.wl_tx_power[RTW89_PHY_0] = level;
3789
3790 if (phy_map & BIT(RTW89_PHY_1))
3791 dm->rf_trx_para.wl_tx_power[RTW89_PHY_1] = level;
3792
3793 dm->wl_tx_pwr_phy_map = phy_map;
3794 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3795 "[BTC], %s(): phy_map=0x%x, wl_tx_pwr-> phy0=%d, phy1=%d\n",
3796 __func__, phy_map,
3797 dm->rf_trx_para.wl_tx_power[RTW89_PHY_0],
3798 dm->rf_trx_para.wl_tx_power[RTW89_PHY_1]);
3799
3800 if ((ver->fcxtrx == 7 && chip->chip_id == RTL8922A) ||
3801 ver->fcxtrx == 107) {
3802 _fw_set_drv_info(rtwdev, CXDRVINFO_TXPWR);
3803 } else if (ver->fcxtrx == 9) {
3804 _fw_set_drv_info(rtwdev, CXDRVINFO_TXPWR);
3805 } else {
3806 if (level == RTW89_BTC_WL_DEF_TX_PWR) {
3807 pwr_val = WL_TX_POWER_NO_BTC_CTRL;
3808 } else { /* only apply "force tx power" */
3809 pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level);
3810 if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR)
3811 pwr_val = RTW89_BTC_WL_DEF_TX_PWR;
3812
3813 if (level & B_BTC_WL_TX_POWER_SIGN)
3814 pwr_val |= B_TSSI_WL_TX_POWER_SIGN;
3815 pwr_val |= WL_TX_POWER_WITH_BT;
3816 }
3817 chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val);
3818 }
3819 }
3820
_set_wl_rx_gain(struct rtw89_dev * rtwdev,u32 level,u8 phy_map)3821 static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level, u8 phy_map)
3822 {
3823 const struct rtw89_chip_info *chip = rtwdev->chip;
3824 struct rtw89_btc *btc = &rtwdev->btc;
3825 struct rtw89_btc_dm *dm = &btc->dm;
3826 bool level_chg = false;
3827
3828 if (phy_map & BIT(RTW89_PHY_0))
3829 level_chg = !(dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0] == level);
3830
3831 if (phy_map & BIT(RTW89_PHY_1))
3832 level_chg |= !(dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1] == level);
3833
3834 if (!level_chg && !btc->cli_h2c_cmd)
3835 return;
3836
3837 if (phy_map & BIT(RTW89_PHY_0))
3838 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0] = level;
3839
3840 if (phy_map & BIT(RTW89_PHY_1))
3841 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1] = level;
3842
3843 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3844 "[BTC], %s(): phy_map=0x%x, wl_rx_gain-> phy0=%d, phy1=%d\n",
3845 __func__, phy_map,
3846 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0],
3847 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1]);
3848
3849 chip->ops->btc_set_wl_rx_gain(rtwdev, level);
3850 }
3851
_set_bt_tx_power(struct rtw89_dev * rtwdev,bool force_exec,u8 bid,u8 rf_band,u8 level)3852 static void _set_bt_tx_power(struct rtw89_dev *rtwdev, bool force_exec, u8 bid,
3853 u8 rf_band, u8 level)
3854 {
3855 struct rtw89_btc *btc = &rtwdev->btc;
3856 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
3857 u8 h2c_func = SET_BT_TX_PWR;
3858 u8 i, id_start, id_stop;
3859 u8 buf[2] = {};
3860 u8 len = sizeof(*buf);
3861
3862 if (bt->bcnt[BTC_BCNT_INFOUPDATE] == 0 || !rf_band)
3863 return;
3864
3865 if (bt->rf_para.tx_pwr_freerun == level)
3866 return;
3867
3868 if (bid == BTC_ALL_BT) {
3869 id_start = BTC_BT_1ST;
3870 id_stop = BTC_BT_2ND;
3871 } else {
3872 id_start = bid;
3873 id_stop = bid;
3874 }
3875
3876 for (i = id_start; i <= id_stop; i++) {
3877 if (i == BTC_BT_2ND) {
3878 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))
3879 continue;
3880
3881 bt = &btc->cx.bt1;
3882 h2c_func |= BT_H2C_FUNC_BT2ND;
3883 }
3884
3885 buf[0] = (s8)(-level);
3886 buf[1] = rf_band; /* bit-map: bit1->5GHz/6Ghz, bit0->2.4GHz */
3887
3888 if (!force_exec && !btc->cli_h2c_cmd) {
3889 if (rf_band == RTW89_BAND_2G &&
3890 bt->tx_power_now == level)
3891 continue;
3892 else if (rf_band != RTW89_BAND_2G &&
3893 bt->tx_power_now_6g == level)
3894 continue;
3895 }
3896
3897 if (rtwdev->chip->chip_gen == RTW89_CHIP_AX)
3898 len = SET_RF_PARA_AX_LEN;
3899
3900 if (!_send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, len)) {
3901 btc->dm.rf_trx_para.bt_tx_power[i] = level;
3902 if (rf_band == RTW89_BAND_2G)
3903 bt->tx_power_now = level;
3904 else
3905 bt->tx_power_now_6g = level;
3906 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3907 "[BTC], %s(): bt%d_tx_power_level = %d\n",
3908 __func__, i, level);
3909 }
3910 }
3911 }
3912
3913 #define BTC_BT_RX_NORMAL_LVL 7
_set_bt_rx_gain(struct rtw89_dev * rtwdev,bool force_exec,u8 bid,u8 rf_band,u8 level)3914 static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, bool force_exec, u8 bid,
3915 u8 rf_band, u8 level)
3916 {
3917 struct rtw89_btc *btc = &rtwdev->btc;
3918 struct rtw89_btc_cx *cx = &btc->cx;
3919 struct rtw89_btc_bt_info *bt = &cx->bt0;
3920 u8 h2c_func = SET_BT_LNA_CONSTRAIN;
3921 u8 i, id_start, id_stop;
3922 bool state = false;
3923 u32 scbd_bit = 0;
3924 u8 buf[2] = {};
3925 u8 len = sizeof(*buf);
3926
3927 if (bt->bcnt[BTC_BCNT_INFOUPDATE] == 0 || !rf_band)
3928 return;
3929
3930 if (bt->rf_para.rx_gain_freerun == level ||
3931 level > BTC_BT_RX_NORMAL_LVL || !rtwdev->chip->scbd ||
3932 bid > BTC_ALL_BT)
3933 return;
3934
3935 if (bid == BTC_ALL_BT) {
3936 id_start = BTC_BT_1ST;
3937 id_stop = BTC_BT_2ND;
3938 } else {
3939 id_start = bid;
3940 id_stop = bid;
3941 }
3942
3943 if (rf_band == RTW89_BAND_2G)
3944 scbd_bit |= BTC_WSCB_RXGAIN;
3945 else
3946 scbd_bit |= BTC_WSCB_RXGAIN_56G;
3947
3948 for (i = id_start; i <= id_stop; i++) {
3949 if (i == BTC_BT_2ND) {
3950 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))
3951 continue;
3952
3953 bt = &cx->bt1;
3954 h2c_func |= BT_H2C_FUNC_BT2ND;
3955 }
3956
3957 /* return if same setup */
3958 if (!force_exec && !btc->cli_h2c_cmd) {
3959 if (rf_band == RTW89_BAND_2G &&
3960 bt->lna_constrain == level)
3961 continue;
3962 else if (rf_band != RTW89_BAND_2G &&
3963 bt->lna_constrain_6g == level)
3964 continue;
3965 }
3966
3967 buf[0] = level;
3968 buf[1] = rf_band;
3969
3970 if (rtwdev->chip->chip_gen == RTW89_CHIP_AX)
3971 len = SET_RF_PARA_AX_LEN;
3972
3973 if (_send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, len)) {
3974 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3975 "[BTC], %s(): bt%d_rx_gain_level = %d\n",
3976 __func__, i, level);
3977 }
3978
3979 btc->dm.rf_trx_para.bt_rx_gain[i] = level;
3980
3981 if (buf[0] != BTC_BT_RX_NORMAL_LVL)
3982 state = true;
3983
3984 _write_scbd(rtwdev, bid, scbd_bit, state);
3985 }
3986 }
3987
_set_bt_corx_table(struct rtw89_dev * rtwdev,bool en)3988 static void _set_bt_corx_table(struct rtw89_dev *rtwdev, bool en)
3989 {
3990 struct rtw89_btc *btc = &rtwdev->btc;
3991 struct rtw89_btc_cx *cx = &btc->cx;
3992 struct rtw89_btc_bt_info *bt = &cx->bt0;
3993 struct rtw89_btc_dm *dm = &btc->dm;
3994 u8 is_24g, is_56g, i;
3995 u32 scbd_bit;
3996
3997 /*
3998 * true: bt use Hi-LNA rx gain table (f/e/3/2) in -3x~-9xdBm for co-rx
3999 * false: bt use original rx gain table (f/b/7/3/2)
4000 */
4001
4002 if (btc->dm.fdd_bind.bt_sel == BIT(BTC_BT_EXT))
4003 return;
4004
4005 for (i = BTC_BT_1ST; i <= BTC_BT_2ND; i++) {
4006 scbd_bit = 0;
4007 if (i == BTC_BT_2ND) {
4008 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))
4009 continue;
4010 bt = &cx->bt1;
4011 }
4012
4013 is_24g = (dm->corx_map[BTC_RF_S0][i] ||
4014 dm->corx_map[BTC_RF_S1][i]) & BIT(RTW89_BAND_2G);
4015 is_56g = (dm->corx_map[BTC_RF_S0][i] ||
4016 dm->corx_map[BTC_RF_S1][i]) & BIT(RTW89_BAND_5G);
4017 if (is_24g)
4018 scbd_bit |= BTC_WSCB_BT_HILNA;
4019 if (is_56g)
4020 scbd_bit |= BTC_WSCB_BT_HILNA_56G;
4021
4022 if ((is_24g && (en != (!!bt->hi_lna_rx))) ||
4023 (is_56g && (en != (!!bt->hi_lna_rx_6g))))
4024 _write_scbd(rtwdev, i, scbd_bit, en);
4025 }
4026 }
4027
_set_rf_trx_para_v9(struct rtw89_dev * rtwdev)4028 static void _set_rf_trx_para_v9(struct rtw89_dev *rtwdev)
4029 {
4030 struct rtw89_btc *btc = &rtwdev->btc;
4031 struct rtw89_btc_cx *cx = &btc->cx;
4032 struct rtw89_btc_wl_smap *wl_smap = &cx->wl.status.map;
4033 struct rtw89_btc_dm *dm = &btc->dm;
4034 bool bt_2r = false;
4035 u8 wl_stb_chg = 0;
4036
4037 if (wl_smap->rf_off || wl_smap->lps == BTC_LPS_RF_OFF)
4038 return;
4039
4040 /* must call after _set_halbb_btg_ctrl() */
4041 if (dm->tdd_bind.wl_link_mode != BTC_WLINK_NOLINK) {
4042 wl_stb_chg = 1;
4043 if (dm->wl_btg_rx)
4044 bt_2r = true;
4045 }
4046
4047 _set_bt_corx_table(rtwdev, bt_2r);
4048
4049 if (wl_stb_chg != dm->wl_stb_chg) {
4050 dm->wl_stb_chg = wl_stb_chg;
4051 dm->ost_info.wl_btg_standby_chg = wl_stb_chg;
4052 rtwdev->chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg);
4053 }
4054 }
4055
_set_rf_trx_para(struct rtw89_dev * rtwdev)4056 static void _set_rf_trx_para(struct rtw89_dev *rtwdev)
4057 {
4058 const struct rtw89_chip_info *chip = rtwdev->chip;
4059 struct rtw89_btc *btc = &rtwdev->btc;
4060 const struct rtw89_btc_ver *ver = btc->ver;
4061 struct rtw89_btc_dm *dm = &btc->dm;
4062 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4063 struct rtw89_btc_wl_role_info *r = &wl->role_info;
4064 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
4065 struct rtw89_btc_bt_link_info *b = &bt->link_info;
4066 struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
4067 struct rtw89_btc_rf_trx_para_v9 para;
4068 u8 bmode = dm->tdd_bind.wl_link_mode;
4069 u8 rf_band = dm->tdd_bind.rf_band;
4070 u8 i, ul_para_num, dl_para_num;
4071 u8 mode = BTC_WLINK_NOLINK;
4072 u8 bid = BTC_BT_1ST, lv;
4073 u32 wl_stb_chg;
4074
4075 if (ver->fcxtrx == 9) {
4076 /* Early v9 need to assign UL/DL RF para at driver */
4077 if (chip->rf_para_ulink_v9) {
4078 ul_para_num = chip->rf_para_ulink_num_v9;
4079 dl_para_num = chip->rf_para_dlink_num_v9;
4080 } else {
4081 _set_rf_trx_para_v9(rtwdev);
4082 return;
4083 }
4084 } else if ((ver->fcxtrx == 0 || ver->fcxtrx == 7 || ver->fcxtrx == 107) &&
4085 chip->rf_para_ulink_v0) {
4086 ul_para_num = chip->rf_para_ulink_num_v0;
4087 dl_para_num = chip->rf_para_dlink_num_v0;
4088 } else {
4089 rtw89_warn(rtwdev, "[BTC]%s(), No rf_para for verseion %d\n",
4090 __func__, ver->fcxtrx);
4091 goto next;
4092 }
4093
4094 if (bmode == BTC_WLINK_NOLINK) {
4095 return;
4096 } else if (rf_band == RTW89_BAND_5G) {
4097 mode = BTC_WLINK_V0_5G;
4098 } else if (rf_band == RTW89_BAND_2G && bmode == BTC_WLINK_STA) {
4099 mode = BTC_WLINK_V0_2G_STA;
4100 }
4101
4102 /* decide trx_para_level */
4103 if (btc->ant_type == BTC_ANT_SHARED) {
4104 /* fix LNA2 + TIA gain not change by GNT_BT */
4105 if ((btc->dm.wl_btg_rx && b->link_cnt.now != 0) ||
4106 dm->bt_only == 1)
4107 dm->trx_para_level = 1; /* for better BT ACI issue */
4108 else
4109 dm->trx_para_level = 0;
4110 } else { /* non-shared antenna */
4111 dm->trx_para_level = 5;
4112 /* modify trx_para if WK 2.4G-STA-DL + bt link */
4113 if (b->link_cnt.now != 0 &&
4114 mode == BTC_WLINK_V0_2G_STA &&
4115 wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { /* uplink */
4116 if (wl->rssi_level == 4 && bt->rssi_level > 2)
4117 dm->trx_para_level = 6;
4118 else if (wl->rssi_level == 3 && bt->rssi_level > 3)
4119 dm->trx_para_level = 7;
4120 }
4121 }
4122
4123 lv = dm->trx_para_level;
4124 if (lv >= ul_para_num ||
4125 lv >= dl_para_num) {
4126 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4127 "[BTC], %s(): invalid level_id: %d\n",
4128 __func__, lv);
4129 return;
4130 }
4131
4132 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4133 if (ver->fcxtrx == 9) {
4134 para = chip->rf_para_ulink_v9[lv];
4135 } else {
4136 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) {
4137 para.wl_tx_power[i] = chip->rf_para_ulink_v0[lv].wl_tx_power;
4138 para.wl_rx_gain[i] = chip->rf_para_ulink_v0[lv].wl_rx_gain;
4139 }
4140 for (i = BTC_BT_1ST; i < BTC_ALL_BT; i++) {
4141 para.bt_tx_power[i] = chip->rf_para_ulink_v0[lv].bt_tx_power;
4142 para.bt_rx_gain[i] = chip->rf_para_ulink_v0[lv].bt_rx_gain;
4143 }
4144 }
4145 } else {
4146 if (ver->fcxtrx == 9) {
4147 para = chip->rf_para_dlink_v9[lv];
4148 } else {
4149 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) {
4150 para.wl_tx_power[i] = chip->rf_para_dlink_v0[lv].wl_tx_power;
4151 para.wl_rx_gain[i] = chip->rf_para_dlink_v0[lv].wl_rx_gain;
4152 }
4153 for (i = BTC_BT_1ST; i < BTC_ALL_BT; i++) {
4154 para.bt_tx_power[i] = chip->rf_para_dlink_v0[lv].bt_tx_power;
4155 para.bt_rx_gain[i] = chip->rf_para_dlink_v0[lv].bt_rx_gain;
4156 }
4157 }
4158 }
4159
4160 if (dm->fddt_train) {
4161 _set_wl_rx_gain(rtwdev, 1, RTW89_PHY_0);
4162 _write_scbd(rtwdev, bid, BTC_WSCB_RXGAIN, true);
4163 } else {
4164 _set_wl_tx_power(rtwdev, para.wl_tx_power[RTW89_PHY_0], RTW89_PHY_0);
4165 _set_wl_rx_gain(rtwdev, para.wl_rx_gain[RTW89_PHY_0], RTW89_PHY_0);
4166 _set_bt_tx_power(rtwdev, true, bid, rf_band, para.bt_tx_power[BTC_BT_1ST]);
4167 _set_bt_rx_gain(rtwdev, true, bid, rf_band, para.bt_rx_gain[BTC_BT_1ST]);
4168 }
4169
4170 next:
4171 if (!bt->enable.now || dm->wl_only || wl_smap->rf_off ||
4172 wl_smap->lps == BTC_LPS_RF_OFF || mode == BTC_WLINK_V0_5G ||
4173 (rtwdev->dbcc_en && r->dbcc_2g_phy != RTW89_PHY_1))
4174 wl_stb_chg = 0;
4175 else
4176 wl_stb_chg = 1;
4177
4178 if (wl_stb_chg != dm->wl_stb_chg) {
4179 dm->wl_stb_chg = wl_stb_chg;
4180 chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg);
4181 }
4182 }
4183
_update_btc_state_map(struct rtw89_dev * rtwdev)4184 static void _update_btc_state_map(struct rtw89_dev *rtwdev)
4185 {
4186 struct rtw89_btc *btc = &rtwdev->btc;
4187 struct rtw89_btc_cx *cx = &btc->cx;
4188 struct rtw89_btc_wl_info *wl = &cx->wl;
4189 struct rtw89_btc_bt_info *bt = &cx->bt0;
4190 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
4191
4192 if (wl->status.map.dhcp || wl->status.map._4way ||
4193 wl->status.map.roaming || wl->status.map.transacting ||
4194 wl->status.map.handshake) {
4195 cx->state_map = BTC_WLINKING;
4196 } else if (wl->status.map.scan) { /* wl scan */
4197 if (bt_linfo->status.map.inq_pag)
4198 cx->state_map = BTC_WSCAN_BSCAN;
4199 else
4200 cx->state_map = BTC_WSCAN_BNOSCAN;
4201 } else if (wl->status.map.busy) { /* only busy */
4202 if (bt_linfo->status.map.inq_pag)
4203 cx->state_map = BTC_WBUSY_BSCAN;
4204 else
4205 cx->state_map = BTC_WBUSY_BNOSCAN;
4206 } else { /* wl idle */
4207 cx->state_map = BTC_WIDLE;
4208 }
4209 }
4210
_get_wl_guard_bw(struct rtw89_dev * rtwdev,u8 index)4211 static u8 _get_wl_guard_bw(struct rtw89_dev *rtwdev, u8 index)
4212 {
4213 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4214 u8 guard_ch = rtwdev->chip->afh_guard_ch;
4215 u8 bw = 0;
4216
4217 /* default AFH channel sapn = center-ch +- 6MHz */
4218 switch (index) {
4219 case RTW89_CHANNEL_WIDTH_20:
4220 if (dm->freerun || dm->fddt_train)
4221 bw = 48;
4222 else
4223 bw = 20 + guard_ch * 2;
4224 break;
4225 case RTW89_CHANNEL_WIDTH_40:
4226 bw = 40 + guard_ch * 2;
4227 break;
4228 case RTW89_CHANNEL_WIDTH_80:
4229 bw = 80 + guard_ch * 2;
4230 break;
4231 case RTW89_CHANNEL_WIDTH_160:
4232 case RTW89_CHANNEL_WIDTH_80_80:
4233 bw = 160 + guard_ch * 2;
4234 break;
4235 case RTW89_CHANNEL_WIDTH_320:
4236 bw = 320 + guard_ch * 2;
4237 break;
4238 case RTW89_CHANNEL_WIDTH_5:
4239 bw = 5 + guard_ch * 2;
4240 break;
4241 case RTW89_CHANNEL_WIDTH_10:
4242 bw = 10 + guard_ch * 2;
4243 break;
4244 default:
4245 bw = 0;
4246 break;
4247 }
4248
4249 return bw;
4250 }
4251
_set_wl_ch_map(struct rtw89_dev * rtwdev)4252 static void _set_wl_ch_map(struct rtw89_dev *rtwdev)
4253 {
4254 struct rtw89_btc *btc = &rtwdev->btc;
4255 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4256 struct rtw89_btc_wl_afh_info *afh;
4257 u16 ch_start, ch_end, i;
4258 u8 b_group, b_pos; /* byte-group, bit-position */
4259 u8 hwb;
4260
4261 if (wl->afh_info[RTW89_MAC_0][RTW89_BAND_2G].en &&
4262 wl->afh_info[RTW89_MAC_1][RTW89_BAND_2G].en) {
4263 /* select wilder bw if 1+1 */
4264 if (wl->afh_info[RTW89_MAC_1][RTW89_BAND_2G].bw >
4265 wl->afh_info[RTW89_MAC_0][RTW89_BAND_2G].bw)
4266 hwb = RTW89_MAC_1;
4267 else
4268 hwb = RTW89_MAC_0;
4269 } else if (wl->afh_info[RTW89_MAC_1][RTW89_BAND_2G].en) {
4270 hwb = RTW89_MAC_1;
4271 } else {
4272 hwb = RTW89_MAC_0;
4273 }
4274
4275 afh = &wl->afh_info[hwb][RTW89_BAND_2G];
4276
4277 /* focus on WL 2.4GHz link */
4278 if (!afh->en || afh->band != RTW89_BAND_2G)
4279 return;
4280
4281 memset(wl->ch_map, 0x0, sizeof(wl->ch_map));
4282 memset(wl->ch_map_le, 0x0, sizeof(wl->ch_map_le));
4283
4284 ch_start = afh->ch * 5 + 2407 - afh->bw / 2;
4285 ch_end = ch_start + afh->bw;
4286
4287 for (i = ch_start; i < ch_end; i++) {
4288 if (i < 2402 || i > 2480)
4289 continue;
4290 b_group = (i - 2402) / 8;
4291 b_pos = 7 - ((i - 2402) % 8);
4292 wl->ch_map[b_group] |= BIT(b_pos);
4293
4294 if (i % 2) /* BLE ch = even-freq (ex:2402,2404) */
4295 continue;
4296
4297 b_group = (i - 2402) / 16;
4298 b_pos = 7 - (((i - 2402) / 2) % 8);
4299 wl->ch_map_le[b_group] |= BIT(b_pos);
4300 }
4301 }
4302
_get_w2b_fbd_ch(struct rtw89_dev * rtwdev,u8 bt_fb_band,u32 wl_vco_freq,u32 * ch_lo_bound,u32 * ch_up_bound)4303 static u8 _get_w2b_fbd_ch(struct rtw89_dev *rtwdev,
4304 u8 bt_fb_band, u32 wl_vco_freq,
4305 u32 *ch_lo_bound, u32 *ch_up_bound)
4306 {
4307 u32 ch_lo, ch_pup, ch_min, ch_max;
4308 u8 out_of_range = 0;
4309 s32 val_lo, val_up;
4310 u32 vco_lo_in_KHz; /* VCO pulling lower bound */
4311 u32 vco_up_in_KHz; /* VCO pulling Upper bound */
4312 u32 freq_start;
4313
4314 vco_lo_in_KHz = wl_vco_freq - BTC_VCO_GUARD_W2B * 1000; /* KHz */
4315 vco_up_in_KHz = wl_vco_freq + BTC_VCO_GUARD_W2B * 1000;
4316
4317 switch (bt_fb_band) {
4318 default:
4319 case BTC_BT_B2G: /* BT 2GHz forbiddened Channel */
4320 val_lo = vco_lo_in_KHz * BTC_LO_2G_DNM / BTC_LO_2G_NMR;
4321 val_up = vco_up_in_KHz * BTC_LO_2G_DNM / BTC_LO_2G_NMR;
4322 freq_start = BTC_FREQ_B2G * 1000; /* KHz */
4323 ch_min = BTC_CH_B2G_MIN;
4324 ch_max = BTC_CH_B2G_MAX;
4325 break;
4326 case BTC_BT_B5G: /* BT 5/6GHz forbiddened Channel */
4327 val_lo = vco_lo_in_KHz * BTC_LO_6G_DNM / BTC_LO_6G_NMR;
4328 val_up = vco_up_in_KHz * BTC_LO_6G_DNM / BTC_LO_6G_NMR;
4329 freq_start = BTC_FREQ_B6G * 1000; /* KHz */
4330 ch_min = BTC_CH_B5G_MIN;
4331 ch_max = BTC_CH_B5G_MAX;
4332 break;
4333 }
4334
4335 /* Search forbiddened Channel (un-process range)*/
4336 ch_lo = (val_lo - freq_start) / 1000;
4337 if ((val_lo - freq_start) % 1000 != 0) /* Round-UP */
4338 ch_lo++;
4339
4340 ch_pup = (val_up - freq_start) / 1000; /* Round-down */
4341
4342 /* Search forbiddened Channel */
4343 if (ch_lo > ch_max || ch_pup < ch_min) { /* out-of-range -> NA */
4344 out_of_range = 1;
4345 *ch_lo_bound = 0;
4346 *ch_up_bound = 0;
4347 }
4348
4349 if (ch_lo < ch_min)
4350 *ch_lo_bound = ch_min;
4351 else if (ch_lo <= ch_max)
4352 *ch_lo_bound = ch_lo;
4353
4354 if (ch_pup > ch_max)
4355 *ch_up_bound = ch_max;
4356 else if (ch_pup >= ch_min)
4357 *ch_up_bound = ch_pup;
4358
4359 if (bt_fb_band == BTC_BT_B5G) { /* BT ch is 8MHz-spacing for 5/6GHz */
4360 *ch_lo_bound = *ch_lo_bound / 8; /* low-bound -> Round-down */
4361
4362 if (*ch_up_bound % 8 != 0) /* Up-bound -> cover wider range */
4363 *ch_up_bound = *ch_up_bound / 8 + 1;
4364 else
4365 *ch_up_bound = *ch_up_bound / 8;
4366 }
4367
4368 return out_of_range;
4369 }
4370
_set_wl_ch_info(struct rtw89_dev * rtwdev)4371 static void _set_wl_ch_info(struct rtw89_dev *rtwdev)
4372 {
4373 static const u8 path_hwb[BTC_RF_NUM] = {RTW89_PHY_0, RTW89_PHY_1};
4374 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4375 struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
4376 struct rtw89_btc_wl_info *wl = &cx->wl;
4377 u32 vco_freq, ch_lo = 0, ch_up = 0;
4378 u16 rf_band, freq, f_diff;
4379 u8 i, j, ch;
4380
4381 if (!(rtwdev->chip->para_ver & BTC_FEAT_MULTI_PTA)) /* only new-PTA require setup */
4382 return;
4383
4384 for (i = RTW89_PHY_0; i <= RTW89_PHY_1; i++) {
4385 if (wl->mlo_info.wmode[i] == RTW89_MR_WMODE_NONE) { /* no-connect */
4386 dm->ost_info.rf_center_freq[i] = 0;
4387 dm->ost_info.fbd_group_en[i][0] = 0;
4388 dm->ost_info.fbd_group_en[i][1] = 0;
4389 dm->ost_info.fbd_group_bound[i][0] = 0;
4390 dm->ost_info.fbd_group_bound[i][1] = 0;
4391 continue;
4392 }
4393
4394 ch = wl->rf_ch_info[i].center_ch;
4395 switch (wl->rf_ch_info[i].band) {
4396 case RTW89_BAND_2G:
4397 default:
4398 rf_band = 0;
4399 if (ch == 14)
4400 freq = BTC_FREQ_W2G_CH14;
4401 else
4402 freq = BTC_FREQ_W2G + (ch - 1) * 5;
4403 vco_freq = freq * 1000 * BTC_LO_2G_NMR / BTC_LO_2G_DNM;
4404 break;
4405 case RTW89_BAND_5G:
4406 rf_band = BIT(15);
4407 freq = BTC_FREQ_W5G + (ch - 1) * 5;
4408 vco_freq = freq * 1000 * BTC_LO_5G_NMR / BTC_LO_5G_DNM;
4409 break;
4410 case RTW89_BAND_6G:
4411 rf_band = BIT(15);
4412 freq = BTC_FREQ_W6G + (ch - 1) * 5;
4413 vco_freq = freq * 1000 * BTC_LO_6G_NMR / BTC_LO_6G_DNM;
4414 break;
4415 }
4416
4417 dm->ost_info.rf_center_freq[i] = rf_band + freq;
4418
4419 for (j = BTC_BT_B2G; j <= BTC_BT_B5G; j++) {
4420 /* no WL->BT forbidden channel */
4421 if (_get_w2b_fbd_ch(rtwdev, j, vco_freq, &ch_lo, &ch_up)) {
4422 dm->ost_info.fbd_group_en[i][j] = j << 1;
4423 dm->ost_info.fbd_group_bound[i][j] = 0;
4424 continue;
4425 }
4426
4427 dm->ost_info.fbd_group_en[i][j] = (j << 1) + 0x1;
4428 dm->ost_info.fbd_group_bound[i][j] = (ch_up << 8) + ch_lo;
4429 }
4430 }
4431
4432 for (i = BTC_RF_S0; i <= BTC_RF_S1; i++) {
4433 for (j = BTC_BT_1ST; j <= BTC_BT_EXT; j++) {
4434 /*
4435 * If WL & BT share same ANT/Path, set freq-diff > 2GHz,
4436 * because TDD will always run in 5/6GHz band.
4437 * Otherwise, the frq-diff thres is decided by the RF
4438 * out-of-channel rejection capability.
4439 */
4440 if (dm->ant_xmap[i][j])
4441 f_diff = 0x7ff; /* 2047MHz */
4442 else
4443 f_diff = rtwdev->chip->fdd_iso_freq;
4444
4445 dm->ost_info.freq_diff_thres[path_hwb[i]][j] = f_diff;
4446 }
4447 }
4448 }
4449
_set_bt_afh_info(struct rtw89_dev * rtwdev)4450 static void _set_bt_afh_info(struct rtw89_dev *rtwdev)
4451 {
4452 struct rtw89_btc *btc = &rtwdev->btc;
4453 struct rtw89_btc_cx *cx = &btc->cx;
4454 struct rtw89_btc_wl_info *wl = &cx->wl;
4455 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
4456 struct rtw89_btc_wl_rlink *rlink;
4457 u8 h2c_func, hwb, bt_link_chg;
4458 u8 i, j, sz, bw;
4459 u8 buf[4];
4460
4461 if (btc->manual_ctrl || wl->status.map.rf_off ||
4462 (wl->status.val & btc_scanning_map.val))
4463 return;
4464
4465 memset(wl->afh_info, 0, sizeof(wl->afh_info));
4466
4467 for (j = RTW89_MAC_0; j < RTW89_MAC_NUM; j++) {
4468 /* skip HW-Band if no fdd/fdd bind */
4469 if ((!(btc->dm.tdd_bind.wl_hwb_sel & BIT(j))) &&
4470 (!(btc->dm.fdd_bind.wl_hwb_sel & BIT(j))))
4471 continue;
4472
4473 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
4474 rlink = &wl_rinfo->rlink[i][j];
4475
4476 /* Skip no-active case */
4477 if (!rlink->connected || !rlink->active ||
4478 rlink->rf_band >= RTW89_BAND_NUM)
4479 continue;
4480
4481 /* In addition to AP/P2P, skip if same-rf-band*/
4482 if (wl->afh_info[j][rlink->rf_band].en &&
4483 (rlink->role != RTW89_WIFI_ROLE_AP &&
4484 rlink->role != RTW89_WIFI_ROLE_P2P_GO &&
4485 rlink->role != RTW89_WIFI_ROLE_P2P_CLIENT))
4486 continue;
4487
4488 bw = _get_wl_guard_bw(rtwdev, rlink->bw);
4489 wl->afh_info[j][rlink->rf_band].en = 1;
4490 wl->afh_info[j][rlink->rf_band].ch = rlink->ch;
4491 wl->afh_info[j][rlink->rf_band].bw = bw;
4492 wl->afh_info[j][rlink->rf_band].band = rlink->rf_band;
4493 }
4494 }
4495
4496 for (j = RTW89_BAND_2G; j < RTW89_BAND_NUM; j++) {
4497 /* skip non-2.4GHz if BT is 2.4GHz only*/
4498 if (!(rtwdev->chip->para_ver & BTC_FEAT_BT_6G)) {
4499 if (j != RTW89_BAND_2G)
4500 continue;
4501 sz = 3;
4502 } else {
4503 sz = 4;
4504 }
4505
4506 if (wl->afh_info[RTW89_MAC_0][j].en &&
4507 wl->afh_info[RTW89_MAC_1][j].en) {
4508 /* select wilder bw if 1+1 */
4509 if (wl->afh_info[RTW89_MAC_1][j].bw >
4510 wl->afh_info[RTW89_MAC_0][j].bw)
4511 hwb = RTW89_MAC_1;
4512 else
4513 hwb = RTW89_MAC_0;
4514 } else if (wl->afh_info[RTW89_MAC_1][j].en) {
4515 hwb = RTW89_MAC_1;
4516 } else {
4517 hwb = RTW89_MAC_0;
4518 }
4519
4520 if (j == RTW89_BAND_2G) {
4521 if (cx->bt0.link_info.link_cnt.chg ||
4522 cx->bt1.link_info.link_cnt.chg)
4523 bt_link_chg = 1;
4524 else
4525 bt_link_chg = 0;
4526 } else {
4527 if (cx->bt0.link_info_56g.link_cnt.chg ||
4528 cx->bt1.link_info_56g.link_cnt.chg)
4529 bt_link_chg = 1;
4530 else
4531 bt_link_chg = 0;
4532 }
4533
4534 /* return if no-afh-info-change/no wl-bt link change */
4535 if (!memcmp(&wl->afh_info_last[hwb][j],
4536 &wl->afh_info[hwb][j],
4537 sizeof(struct rtw89_btc_wl_afh_info)) &&
4538 !bt_link_chg &&
4539 !wl->link_mode_chg)
4540 continue;
4541
4542 memcpy(&wl->afh_info_last[hwb][j],
4543 &wl->afh_info[hwb][j],
4544 sizeof(struct rtw89_btc_wl_afh_info));
4545
4546 buf[0] = wl->afh_info[hwb][j].en;
4547 buf[1] = wl->afh_info[hwb][j].ch;
4548 buf[2] = wl->afh_info[hwb][j].bw;
4549 buf[3] = wl->afh_info[hwb][j].band;
4550
4551 h2c_func = SET_BT_WL_CH_INFO;
4552 if (cx->bt0.enable.now)
4553 _send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, sz);
4554
4555 /* send mailbox to 2nd-BT if exist */
4556 if (cx->bt1.enable.now) {
4557 h2c_func |= BT_H2C_FUNC_BT2ND;
4558 _send_fw_cmd(rtwdev, BTFC_SET, h2c_func, buf, sz);
4559 }
4560
4561 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4562 "[BTC], %s(): en=%d, ch=%d, bw=%d, rf_band=%d\n",
4563 __func__, buf[0], buf[1], buf[2], buf[3]);
4564
4565 wl->wcnt[BTC_WCNT_CH_UPDATE]++;
4566
4567 /* ToDo: Remove if BT update new-define to support 6GHz */
4568 if (j == RTW89_BAND_2G)
4569 break;
4570 }
4571
4572 /* for AFH map display in coex log */
4573 _set_wl_ch_map(rtwdev);
4574
4575 /* set HWB center-ch/forbidden group to ost_info for CR setup in FW */
4576 _set_wl_ch_info(rtwdev);
4577 }
4578
_check_freerun(struct rtw89_dev * rtwdev)4579 static bool _check_freerun(struct rtw89_dev *rtwdev)
4580 {
4581 struct rtw89_btc *btc = &rtwdev->btc;
4582 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4583 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
4584 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
4585 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
4586 struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc;
4587 struct rtw89_btc_module *md = &btc->mdinfo;
4588
4589 if (btc->ant_type == BTC_ANT_SHARED) {
4590 btc->dm.trx_para_level = 0;
4591 return false;
4592 }
4593
4594 /* The below is dedicated antenna case */
4595 if (wl_rinfo->connect_cnt > BTC_TDMA_WLROLE_MAX) {
4596 btc->dm.trx_para_level = 5;
4597 return true;
4598 }
4599
4600 if (bt_linfo->link_cnt.now == 0) {
4601 btc->dm.trx_para_level = 5;
4602 return true;
4603 }
4604
4605 if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) {
4606 btc->dm.trx_para_level = 5;
4607 return true;
4608 }
4609
4610 /* TODO get isolation by BT psd */
4611 if (md->ant.isolation >= BTC_FREERUN_ANTISO_MIN) {
4612 btc->dm.trx_para_level = 5;
4613 return true;
4614 }
4615
4616 if (!wl->status.map.busy) {/* wl idle -> freerun */
4617 btc->dm.trx_para_level = 5;
4618 return true;
4619 } else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */
4620 btc->dm.trx_para_level = 0;
4621 return false;
4622 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4623 if (wl->rssi_level == 0 && bt_linfo->rssi > 31) {
4624 btc->dm.trx_para_level = 6;
4625 return true;
4626 } else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) {
4627 btc->dm.trx_para_level = 7;
4628 return true;
4629 }
4630 btc->dm.trx_para_level = 0;
4631 return false;
4632 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) {
4633 if (bt_linfo->rssi > 28) {
4634 btc->dm.trx_para_level = 6;
4635 return true;
4636 }
4637 }
4638
4639 btc->dm.trx_para_level = 0;
4640 return false;
4641 }
4642
4643 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; })
4644 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; })
4645 #define _tdma_set_rxflctrl(btc, rxflc) ({(btc)->dm.tdma.rxflctrl = rxflc; })
4646 #define _tdma_set_txflctrl(btc, txflc) ({(btc)->dm.tdma.txflctrl = txflc; })
4647 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; })
4648
4649 struct btc_btinfo_lb2 {
4650 u8 connect: 1;
4651 u8 sco_busy: 1;
4652 u8 inq_pag: 1;
4653 u8 acl_busy: 1;
4654 u8 hfp: 1;
4655 u8 hid: 1;
4656 u8 a2dp: 1;
4657 u8 pan: 1;
4658 };
4659
4660 struct btc_btinfo_lb3 {
4661 u8 retry: 4;
4662 u8 cqddr: 1;
4663 u8 inq: 1;
4664 u8 mesh_busy: 1;
4665 u8 pag: 1;
4666 };
4667
4668 struct btc_btinfo_hb0 {
4669 s8 rssi;
4670 };
4671
4672 struct btc_btinfo_hb1 {
4673 u8 ble_connect: 1;
4674 u8 reinit: 1;
4675 u8 relink: 1;
4676 u8 igno_wl: 1;
4677 u8 voice: 1;
4678 u8 ble_scan: 1;
4679 u8 role_sw: 1;
4680 u8 multi_link: 1;
4681 };
4682
4683 struct btc_btinfo_hb2 {
4684 u8 pan_active: 1;
4685 u8 afh_update: 1;
4686 u8 a2dp_active: 1;
4687 u8 slave: 1;
4688 u8 hid_slot: 2;
4689 u8 hid_cnt: 2;
4690 };
4691
4692 struct btc_btinfo_hb3 {
4693 u8 a2dp_bitpool: 6;
4694 u8 tx_3m: 1;
4695 u8 a2dp_sink: 1;
4696 };
4697
4698 union btc_btinfo {
4699 u8 val;
4700 struct btc_btinfo_lb2 lb2;
4701 struct btc_btinfo_lb3 lb3;
4702 struct btc_btinfo_hb0 hb0;
4703 struct btc_btinfo_hb1 hb1;
4704 struct btc_btinfo_hb2 hb2;
4705 struct btc_btinfo_hb3 hb3;
4706 };
4707
_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)4708 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
4709 enum btc_reason_and_action action)
4710 {
4711 const struct rtw89_chip_info *chip = rtwdev->chip;
4712
4713 chip->ops->btc_set_policy(rtwdev, policy_type);
4714 _fw_set_policy(rtwdev, policy_type, action);
4715 }
4716
_set_tdma_bind(struct rtw89_dev * rtwdev,bool tdma_on)4717 static void _set_tdma_bind(struct rtw89_dev *rtwdev, bool tdma_on)
4718 {
4719 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
4720 struct rtw89_btc_bind_info *bind;
4721 u8 null_role = RTW89_WIFI_ROLE_STATION;
4722 u8 bt_sel;
4723
4724 if (dm->tdd_en)
4725 bind = &dm->tdd_bind; /* tdd = 1 && fdd = 0 or 1 */
4726 else
4727 bind = &dm->fdd_bind; /* tdd = 0 && fdd = 1 */
4728
4729 if (bind->bt_sel >= (BIT(BTC_BT_1ST) | BIT(BTC_BT_2ND)))
4730 bt_sel = BTC_ALL_BT;
4731 else if (bind->bt_sel == BIT(BTC_BT_2ND))
4732 bt_sel = BTC_BT_2ND;
4733 else
4734 bt_sel = BTC_BT_1ST;
4735
4736 /* notify BT TDMA on/off by scoreboard for ACL/Scan schedule */
4737 _write_scbd(rtwdev, bt_sel, BTC_WSCB_TDMA, tdma_on);
4738
4739 /*
4740 * set hwb/bt bind to TDMA policy parameter
4741 * FW-BTC will setup related hwbx vs. BTx coex tables by slot toggle
4742 * ex: HWb0 + BT0 + BT1, HWB0-BT0/HWB0-BT1 coex by WL/BT slot toggle
4743 */
4744 dm->tdma.bind = ((bind->bt_sel & 0xf) << 4) + (bind->wl_hwb_sel & 0x3);
4745 if (dm->tdd_en)
4746 dm->tdma.bind |= BIT(2);
4747 if (dm->fdd_en)
4748 dm->tdma.bind |= BIT(3);
4749 if (rtwdev->btc.ver->fcxtdma != 8)
4750 dm->tdma.bind |= 0;
4751
4752 /* set Null-tx role for 2 HW-BAND TDMA (MLMR) */
4753 if (!dm->eslot_ctrl.en && dm->tdma.rxflctrl &&
4754 (bind->wl_hwb_sel == (BIT(RTW89_PHY_1) | BIT(RTW89_PHY_0)))) {
4755 null_role = (null_role << 4) + null_role;
4756 _tdma_set_flctrl_role(&rtwdev->btc, null_role);
4757 }
4758 }
4759
4760 #define BTC_B1_MAX 250 /* unit ms */
rtw89_btc_set_policy(struct rtw89_dev * rtwdev,u16 policy_type)4761 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type)
4762 {
4763 struct rtw89_btc *btc = &rtwdev->btc;
4764 struct rtw89_btc_dm *dm = &btc->dm;
4765 struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
4766 u8 type;
4767 u32 tbl_w1, tbl_b1, tbl_b4;
4768 bool tdma_on = false;
4769
4770 if (btc->ant_type == BTC_ANT_SHARED) {
4771 if (btc->cx.wl.status.map._4way)
4772 tbl_w1 = cxtbl[1];
4773 else
4774 tbl_w1 = cxtbl[8];
4775 tbl_b1 = cxtbl[3];
4776 tbl_b4 = cxtbl[3];
4777 } else {
4778 tbl_w1 = cxtbl[16];
4779 tbl_b1 = cxtbl[17];
4780 tbl_b4 = cxtbl[17];
4781 }
4782
4783 type = (u8)((policy_type & BTC_CXP_MASK) >> 8);
4784 btc->bt_req_en = false;
4785
4786 switch (type) {
4787 case BTC_CXP_USERDEF0:
4788 *t = t_def[CXTD_OFF];
4789 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4790 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4791 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
4792 btc->update_policy_force = true;
4793 break;
4794 case BTC_CXP_OFF: /* TDMA off */
4795 tdma_on = false;
4796 *t = t_def[CXTD_OFF];
4797 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4798 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4799
4800 switch (policy_type) {
4801 case BTC_CXP_OFF_BT:
4802 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
4803 break;
4804 case BTC_CXP_OFF_WL:
4805 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
4806 break;
4807 case BTC_CXP_OFF_EQ0:
4808 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
4809 break;
4810 case BTC_CXP_OFF_EQ1:
4811 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
4812 break;
4813 case BTC_CXP_OFF_EQ2:
4814 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
4815 break;
4816 case BTC_CXP_OFF_EQ3:
4817 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
4818 break;
4819 case BTC_CXP_OFF_BWB0:
4820 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
4821 break;
4822 case BTC_CXP_OFF_BWB1:
4823 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
4824 break;
4825 case BTC_CXP_OFF_BWB3:
4826 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
4827 break;
4828 }
4829 break;
4830 case BTC_CXP_OFFB: /* TDMA off + beacon protect */
4831 tdma_on = false;
4832 *t = t_def[CXTD_OFF_B2];
4833 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4834 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4835 _slot_set(btc, CXST_B2, 10, cxtbl[1], SLOT_ISO);
4836
4837 switch (policy_type) {
4838 case BTC_CXP_OFFB_BWB0:
4839 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
4840 break;
4841 case BTC_CXP_OFFB_BWB1:
4842 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
4843 break;
4844 case BTC_CXP_OFFB_BWB2:
4845 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
4846 break;
4847 case BTC_CXP_OFFB_BWB3:
4848 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
4849 break;
4850 case BTC_CXP_OFFB_BWB4:
4851 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
4852 break;
4853 }
4854 break;
4855 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
4856 btc->bt_req_en = true;
4857 tdma_on = true;
4858 *t = t_def[CXTD_OFF_EXT];
4859 switch (policy_type) {
4860 case BTC_CXP_OFFE_DEF:
4861 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
4862 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
4863 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4864 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4865 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4866 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4867 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
4868 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
4869 break;
4870 case BTC_CXP_OFFE_DEF2:
4871 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
4872 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4873 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4874 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4875 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4876 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
4877 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
4878 break;
4879 }
4880 break;
4881 case BTC_CXP_FIX: /* TDMA Fix-Slot */
4882 tdma_on = true;
4883 *t = t_def[CXTD_FIX];
4884 switch (policy_type) {
4885 case BTC_CXP_FIX_TD3030:
4886 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4887 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4888 break;
4889 case BTC_CXP_FIX_TD5050:
4890 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4891 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
4892 break;
4893 case BTC_CXP_FIX_TD2030:
4894 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4895 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4896 break;
4897 case BTC_CXP_FIX_TD4010:
4898 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
4899 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4900 break;
4901 case BTC_CXP_FIX_TD4010ISO:
4902 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
4903 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4904 break;
4905 case BTC_CXP_FIX_TD4010ISO_DL:
4906 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
4907 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
4908 break;
4909 case BTC_CXP_FIX_TD4010ISO_UL:
4910 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
4911 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
4912 break;
4913 case BTC_CXP_FIX_TD7010:
4914 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
4915 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4916 break;
4917 case BTC_CXP_FIX_TD2060:
4918 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4919 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4920 break;
4921 case BTC_CXP_FIX_TD3060:
4922 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4923 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4924 break;
4925 case BTC_CXP_FIX_TD2080:
4926 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4927 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
4928 break;
4929 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
4930 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4931 tbl_w1, SLOT_ISO);
4932 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4933 tbl_b1, SLOT_MIX);
4934 break;
4935 }
4936 break;
4937 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
4938 tdma_on = true;
4939 *t = t_def[CXTD_PFIX];
4940 if (btc->cx.wl.role_info.role_map & BIT(RTW89_WIFI_ROLE_AP))
4941 _tdma_set_flctrl(btc, CXFLC_QOSNULL);
4942
4943 switch (policy_type) {
4944 case BTC_CXP_PFIX_TD3030:
4945 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4946 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4947 break;
4948 case BTC_CXP_PFIX_TD5050:
4949 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4950 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
4951 break;
4952 case BTC_CXP_PFIX_TD2030:
4953 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4954 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4955 break;
4956 case BTC_CXP_PFIX_TD2060:
4957 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4958 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4959 break;
4960 case BTC_CXP_PFIX_TD3070:
4961 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4962 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4963 break;
4964 case BTC_CXP_PFIX_TD2080:
4965 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4966 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
4967 break;
4968 }
4969 break;
4970 case BTC_CXP_AUTO: /* TDMA Auto-Slot */
4971 tdma_on = true;
4972 *t = t_def[CXTD_AUTO];
4973 switch (policy_type) {
4974 case BTC_CXP_AUTO_TD50B1:
4975 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4976 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4977 break;
4978 case BTC_CXP_AUTO_TD60B1:
4979 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4980 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4981 break;
4982 case BTC_CXP_AUTO_TD20B1:
4983 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4984 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4985 break;
4986 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
4987 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4988 tbl_w1, SLOT_ISO);
4989 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4990 tbl_b1, SLOT_MIX);
4991 break;
4992 }
4993 break;
4994 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
4995 tdma_on = true;
4996 *t = t_def[CXTD_PAUTO];
4997 switch (policy_type) {
4998 case BTC_CXP_PAUTO_TD50B1:
4999 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
5000 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5001 break;
5002 case BTC_CXP_PAUTO_TD60B1:
5003 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
5004 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5005 break;
5006 case BTC_CXP_PAUTO_TD20B1:
5007 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5008 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5009 break;
5010 case BTC_CXP_PAUTO_TDW1B1:
5011 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5012 tbl_w1, SLOT_ISO);
5013 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
5014 tbl_b1, SLOT_MIX);
5015 break;
5016 }
5017 break;
5018 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
5019 tdma_on = true;
5020 *t = t_def[CXTD_AUTO2];
5021 switch (policy_type) {
5022 case BTC_CXP_AUTO2_TD3050:
5023 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5024 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
5025 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5026 break;
5027 case BTC_CXP_AUTO2_TD3070:
5028 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5029 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
5030 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5031 break;
5032 case BTC_CXP_AUTO2_TD5050:
5033 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
5034 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
5035 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5036 break;
5037 case BTC_CXP_AUTO2_TD6060:
5038 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
5039 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
5040 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5041 break;
5042 case BTC_CXP_AUTO2_TD2080:
5043 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5044 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
5045 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5046 break;
5047 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
5048 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5049 tbl_w1, SLOT_ISO);
5050 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
5051 tbl_b4, SLOT_MIX);
5052 break;
5053 }
5054 break;
5055 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
5056 tdma_on = true;
5057 *t = t_def[CXTD_PAUTO2];
5058 switch (policy_type) {
5059 case BTC_CXP_PAUTO2_TD3050:
5060 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5061 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
5062 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5063 break;
5064 case BTC_CXP_PAUTO2_TD3070:
5065 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5066 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
5067 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5068 break;
5069 case BTC_CXP_PAUTO2_TD5050:
5070 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
5071 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
5072 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5073 break;
5074 case BTC_CXP_PAUTO2_TD6060:
5075 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
5076 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
5077 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5078 break;
5079 case BTC_CXP_PAUTO2_TD2080:
5080 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5081 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
5082 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5083 break;
5084 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
5085 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5086 tbl_w1, SLOT_ISO);
5087 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
5088 tbl_b4, SLOT_MIX);
5089 break;
5090 }
5091 break;
5092 }
5093 _set_tdma_bind(rtwdev, tdma_on);
5094 }
5095 EXPORT_SYMBOL(rtw89_btc_set_policy);
5096
rtw89_btc_set_policy_v1(struct rtw89_dev * rtwdev,u16 policy_type)5097 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
5098 {
5099 struct rtw89_btc *btc = &rtwdev->btc;
5100 struct rtw89_btc_dm *dm = &btc->dm;
5101 struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
5102 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc;
5103 struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt0.link_info.hid_desc;
5104 struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt0.link_info.hfp_desc;
5105 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5106 u8 type, null_role;
5107 u32 tbl_w1, tbl_b1, tbl_b4;
5108 bool tdma_on = false;
5109 u16 dur_1 = 0, dur_2;
5110
5111 if (wl->status.map.lps) {
5112 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
5113 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
5114 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
5115 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
5116 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
5117 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
5118 }
5119
5120 type = FIELD_GET(BTC_CXP_MASK, policy_type);
5121
5122 if (btc->ant_type == BTC_ANT_SHARED) {
5123 if (btc->cx.wl.status.map._4way)
5124 tbl_w1 = cxtbl[1];
5125 else if (hid->exist && hid->type == BTC_HID_218)
5126 tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */
5127 else
5128 tbl_w1 = cxtbl[8];
5129
5130 if (dm->leak_ap &&
5131 (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) {
5132 tbl_b1 = cxtbl[3];
5133 tbl_b4 = cxtbl[3];
5134 } else if (hid->exist && hid->type == BTC_HID_218) {
5135 tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */
5136 tbl_b4 = cxtbl[4];
5137 } else {
5138 tbl_b1 = cxtbl[2];
5139 tbl_b4 = cxtbl[2];
5140 }
5141 } else {
5142 tbl_b1 = cxtbl[17];
5143 tbl_b4 = cxtbl[17];
5144
5145 if (wl->bg_mode)
5146 tbl_w1 = cxtbl[8];
5147 else if ((wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) &&
5148 hid->exist)
5149 tbl_w1 = cxtbl[19];
5150 else
5151 tbl_w1 = cxtbl[16];
5152 }
5153
5154 switch (type) {
5155 case BTC_CXP_USERDEF0:
5156 btc->update_policy_force = true;
5157 *t = t_def[CXTD_OFF];
5158 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
5159 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
5160 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
5161 break;
5162 case BTC_CXP_OFF: /* TDMA off */
5163 tdma_on = false;
5164 *t = t_def[CXTD_OFF];
5165 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
5166 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
5167
5168 switch (policy_type) {
5169 case BTC_CXP_OFF_BT:
5170 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
5171 break;
5172 case BTC_CXP_OFF_WL:
5173 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
5174 break;
5175 case BTC_CXP_OFF_WL2:
5176 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
5177 _slot_set_type(btc, CXST_OFF, SLOT_ISO);
5178 break;
5179 case BTC_CXP_OFF_EQ0:
5180 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
5181 _slot_set_type(btc, CXST_OFF, SLOT_ISO);
5182 break;
5183 case BTC_CXP_OFF_EQ1:
5184 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
5185 break;
5186 case BTC_CXP_OFF_EQ2:
5187 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
5188 break;
5189 case BTC_CXP_OFF_EQ3:
5190 _slot_set_tbl(btc, CXST_OFF, cxtbl[24]);
5191 break;
5192 case BTC_CXP_OFF_EQ4:
5193 _slot_set_tbl(btc, CXST_OFF, cxtbl[26]);
5194 break;
5195 case BTC_CXP_OFF_EQ5:
5196 _slot_set_tbl(btc, CXST_OFF, cxtbl[27]);
5197 break;
5198 case BTC_CXP_OFF_BWB0:
5199 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
5200 break;
5201 case BTC_CXP_OFF_BWB1:
5202 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
5203 break;
5204 case BTC_CXP_OFF_BWB2:
5205 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
5206 break;
5207 case BTC_CXP_OFF_BWB3:
5208 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
5209 break;
5210 default:
5211 break;
5212 }
5213 break;
5214 case BTC_CXP_OFFB: /* TDMA off + beacon protect */
5215 tdma_on = false;
5216 *t = t_def[CXTD_OFF_B2];
5217 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
5218 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
5219 _slot_set(btc, CXST_B2, 10, cxtbl[1], SLOT_ISO);
5220
5221 switch (policy_type) {
5222 case BTC_CXP_OFFB_BWB0:
5223 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
5224 break;
5225 case BTC_CXP_OFFB_BWB1:
5226 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
5227 break;
5228 case BTC_CXP_OFFB_BWB2:
5229 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
5230 break;
5231 case BTC_CXP_OFFB_BWB3:
5232 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
5233 break;
5234 case BTC_CXP_OFFB_BWB4:
5235 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
5236 break;
5237 }
5238 break;
5239 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
5240 tdma_on = true;
5241 *t = t_def[CXTD_OFF_EXT];
5242
5243 /* To avoid wl-s0 tx break by hid/hfp tx */
5244 if (hid->exist || hfp->exist)
5245 tbl_w1 = cxtbl[16];
5246
5247 if (dm->eslot_ctrl.en) {
5248 null_role = u8_encode_bits(dm->eslot_ctrl.nulltx_role1, 0x0f) |
5249 u8_encode_bits(dm->eslot_ctrl.nulltx_role2, 0xf0);
5250 _tdma_set_flctrl_role(btc, null_role);
5251 _tdma_set_rxflctrl(btc, 1);
5252 _tdma_set_txflctrl(btc, 1);
5253 /* Set Null-Tx time-tick by E2G duration */
5254 dm->eslot_ctrl.nulltx_pre_time = 5; /* TODO: BIS COEX */
5255 dur_1 = dm->eslot_ctrl.nulltx_pre_time;
5256 }
5257
5258 dur_2 = dm->e2g_slot_limit;
5259
5260 switch (policy_type) {
5261 case BTC_CXP_OFFE_2GBWISOB: /* for normal-case */
5262 _slot_set(btc, CXST_E2G, dur_1, tbl_w1, SLOT_ISO);
5263 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
5264 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
5265 _slot_set_dur(btc, CXST_EBT, dur_2);
5266 break;
5267 case BTC_CXP_OFFE_2GISOB: /* for bt no-link */
5268 _slot_set(btc, CXST_E2G, dur_1, cxtbl[1], SLOT_ISO);
5269 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
5270 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
5271 _slot_set_dur(btc, CXST_EBT, dur_2);
5272 break;
5273 case BTC_CXP_OFFE_DEF:
5274 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
5275 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
5276 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
5277 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
5278 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
5279 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
5280 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
5281 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
5282 _slot_set_dur(btc, CXST_EBT, dur_2);
5283 break;
5284 case BTC_CXP_OFFE_DEF2:
5285 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
5286 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
5287 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
5288 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
5289 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
5290 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
5291 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
5292 _slot_set_dur(btc, CXST_EBT, dur_2);
5293 break;
5294 case BTC_CXP_OFFE_2GBWMIXB:
5295 if (a2dp->exist)
5296 _slot_set(btc, CXST_E2G, dur_1, cxtbl[2], SLOT_MIX);
5297 else
5298 _slot_set(btc, CXST_E2G, dur_1, tbl_w1, SLOT_MIX);
5299 _slot_set_le(btc, CXST_EBT, cpu_to_le16(40),
5300 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
5301 _slot_set_dur(btc, CXST_EBT, dur_2);
5302 break;
5303 case BTC_CXP_OFFE_WL: /* for 4-way */
5304 _slot_set(btc, CXST_E2G, dur_1, cxtbl[1], SLOT_MIX);
5305 _slot_set(btc, CXST_EBT, dur_1, cxtbl[1], SLOT_MIX);
5306 break;
5307 default:
5308 break;
5309 }
5310 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
5311 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
5312 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
5313 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
5314 break;
5315 case BTC_CXP_FIX: /* TDMA Fix-Slot */
5316 tdma_on = true;
5317 *t = t_def[CXTD_FIX];
5318
5319 switch (policy_type) {
5320 case BTC_CXP_FIX_TD3030:
5321 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5322 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
5323 break;
5324 case BTC_CXP_FIX_TD5050:
5325 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
5326 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
5327 break;
5328 case BTC_CXP_FIX_TD2030:
5329 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5330 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
5331 break;
5332 case BTC_CXP_FIX_TD4010:
5333 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
5334 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
5335 break;
5336 case BTC_CXP_FIX_TD4010ISO:
5337 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
5338 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
5339 break;
5340 case BTC_CXP_FIX_TD4010ISO_DL:
5341 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
5342 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
5343 break;
5344 case BTC_CXP_FIX_TD4010ISO_UL:
5345 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
5346 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
5347 break;
5348 case BTC_CXP_FIX_TD7010:
5349 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
5350 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
5351 break;
5352 case BTC_CXP_FIX_TD2060:
5353 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5354 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
5355 break;
5356 case BTC_CXP_FIX_TD3060:
5357 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5358 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
5359 break;
5360 case BTC_CXP_FIX_TD2080:
5361 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5362 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
5363 break;
5364 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
5365 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5366 tbl_w1, SLOT_ISO);
5367 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
5368 tbl_b1, SLOT_MIX);
5369 break;
5370 default:
5371 break;
5372 }
5373 break;
5374 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
5375 tdma_on = true;
5376 *t = t_def[CXTD_PFIX];
5377
5378 switch (policy_type) {
5379 case BTC_CXP_PFIX_TD3030:
5380 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5381 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
5382 break;
5383 case BTC_CXP_PFIX_TD5050:
5384 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
5385 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
5386 break;
5387 case BTC_CXP_PFIX_TD2030:
5388 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5389 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
5390 break;
5391 case BTC_CXP_PFIX_TD2060:
5392 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5393 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
5394 break;
5395 case BTC_CXP_PFIX_TD3070:
5396 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5397 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
5398 break;
5399 case BTC_CXP_PFIX_TD2080:
5400 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5401 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
5402 break;
5403 case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */
5404 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5405 tbl_w1, SLOT_ISO);
5406 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
5407 tbl_b1, SLOT_MIX);
5408 break;
5409 default:
5410 break;
5411 }
5412 break;
5413 case BTC_CXP_AUTO: /* TDMA Auto-Slot */
5414 tdma_on = true;
5415 *t = t_def[CXTD_AUTO];
5416
5417 switch (policy_type) {
5418 case BTC_CXP_AUTO_TD50B1:
5419 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
5420 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5421 break;
5422 case BTC_CXP_AUTO_TD60B1:
5423 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
5424 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5425 break;
5426 case BTC_CXP_AUTO_TD20B1:
5427 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5428 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5429 break;
5430 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
5431 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5432 tbl_w1, SLOT_ISO);
5433 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
5434 tbl_b1, SLOT_MIX);
5435 break;
5436 default:
5437 break;
5438 }
5439 break;
5440 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
5441 tdma_on = true;
5442 *t = t_def[CXTD_PAUTO];
5443
5444 switch (policy_type) {
5445 case BTC_CXP_PAUTO_TD50B1:
5446 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
5447 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5448 break;
5449 case BTC_CXP_PAUTO_TD60B1:
5450 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
5451 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5452 break;
5453 case BTC_CXP_PAUTO_TD20B1:
5454 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5455 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5456 break;
5457 case BTC_CXP_PAUTO_TDW1B1:
5458 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5459 tbl_w1, SLOT_ISO);
5460 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
5461 tbl_b1, SLOT_MIX);
5462 break;
5463 default:
5464 break;
5465 }
5466 break;
5467 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
5468 tdma_on = true;
5469 *t = t_def[CXTD_AUTO2];
5470
5471 switch (policy_type) {
5472 case BTC_CXP_AUTO2_TD3050:
5473 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5474 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5475 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
5476 break;
5477 case BTC_CXP_AUTO2_TD3070:
5478 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5479 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5480 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
5481 break;
5482 case BTC_CXP_AUTO2_TD5050:
5483 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
5484 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5485 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
5486 break;
5487 case BTC_CXP_AUTO2_TD6060:
5488 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
5489 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5490 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
5491 break;
5492 case BTC_CXP_AUTO2_TD2080:
5493 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5494 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5495 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
5496 break;
5497 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
5498 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5499 tbl_w1, SLOT_ISO);
5500 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
5501 tbl_b1, SLOT_MIX);
5502 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
5503 tbl_b4, SLOT_MIX);
5504 break;
5505 default:
5506 break;
5507 }
5508 break;
5509 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
5510 tdma_on = true;
5511 *t = t_def[CXTD_PAUTO2];
5512
5513 switch (policy_type) {
5514 case BTC_CXP_PAUTO2_TD3050:
5515 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5516 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5517 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
5518 break;
5519 case BTC_CXP_PAUTO2_TD3070:
5520 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
5521 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5522 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
5523 break;
5524 case BTC_CXP_PAUTO2_TD5050:
5525 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
5526 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5527 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
5528 break;
5529 case BTC_CXP_PAUTO2_TD6060:
5530 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
5531 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5532 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
5533 break;
5534 case BTC_CXP_PAUTO2_TD2080:
5535 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
5536 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
5537 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
5538 break;
5539 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
5540 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
5541 tbl_w1, SLOT_ISO);
5542 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
5543 tbl_b1, SLOT_MIX);
5544 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
5545 tbl_b4, SLOT_MIX);
5546 break;
5547 default:
5548 break;
5549 }
5550 break;
5551 }
5552
5553 /* enter leak_slot after each null-1 */
5554 if (dm->leak_ap && dm->tdma.leak_n > 1)
5555 _tdma_set_lek(btc, 1);
5556
5557 if (dm->tdma_instant_excute ||
5558 dm->error.map.tdma_no_sync ||
5559 dm->error.map.slot_no_sync ||
5560 dm->lps_ctrl_change) {
5561 btc->dm.tdma.option_ctrl |= BIT(0);
5562 btc->update_policy_force = true;
5563 }
5564
5565 if (btc->cli_h2c_cmd)
5566 btc->update_policy_force = true;
5567
5568 _set_tdma_bind(rtwdev, tdma_on);
5569 }
5570 EXPORT_SYMBOL(rtw89_btc_set_policy_v1);
5571
_set_bt_plut(struct rtw89_dev * rtwdev,u8 phy_map,u8 tx_val,u8 rx_val)5572 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
5573 u8 tx_val, u8 rx_val)
5574 {
5575 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
5576 struct rtw89_mac_ax_plt plt;
5577
5578 plt.tx = tx_val;
5579 plt.rx = rx_val;
5580
5581 if (rtwdev->btc.ver->fwlrole == 8) {
5582 plt.band = wl->pta_req_mac;
5583 if (wl->bt_polut_type[plt.band] == tx_val)
5584 return;
5585
5586 wl->bt_polut_type[plt.band] = tx_val;
5587 rtw89_mac_cfg_plt(rtwdev, &plt);
5588 } else {
5589 plt.band = RTW89_MAC_0;
5590
5591 if (phy_map & BTC_PHY_0)
5592 rtw89_mac_cfg_plt(rtwdev, &plt);
5593
5594 if (!rtwdev->dbcc_en)
5595 return;
5596
5597 plt.band = RTW89_MAC_1;
5598 if (phy_map & BTC_PHY_1)
5599 rtw89_mac_cfg_plt(rtwdev, &plt);
5600 }
5601 }
5602
_set_ant(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)5603 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
5604 u8 phy_map, u8 type)
5605 {
5606 struct rtw89_btc *btc = &rtwdev->btc;
5607 struct rtw89_btc_cx *cx = &btc->cx;
5608 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5609 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5610 u32 ant_path_type = rtw89_get_antpath_type(phy_map, type);
5611 struct rtw89_btc_dm *dm = &btc->dm;
5612 u8 gwl = BTC_GNT_HW, gwl0, gwl1, gbt;
5613 bool cx_ctrl;
5614
5615 if (btc->cli_h2c_cmd || wl_rinfo->dbcc_chg ||
5616 dm->run_reason == BTC_RSN_NTFY_POWEROFF ||
5617 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE ||
5618 dm->run_reason == BTC_RSN_CMD_SET_COEX)
5619 force_exec = FC_EXEC;
5620
5621 if (wl_rinfo->link_mode != BTC_WLINK_DB_MCC &&
5622 btc->dm.wl_btg_rx == 2)
5623 force_exec = FC_EXEC;
5624
5625 if (!force_exec && ant_path_type == dm->set_ant_path) {
5626 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5627 "[BTC], %s(): return by no change!!\n",
5628 __func__);
5629 return;
5630 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
5631 wl->rfk_info.state != BTC_WRFK_STOP) {
5632 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5633 "[BTC], %s(): return by wl rfk!!\n", __func__);
5634 return;
5635 }
5636
5637 dm->set_ant_path = ant_path_type;
5638
5639 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5640 "[BTC], %s(): path=0x%x, set_type=0x%x\n",
5641 __func__, phy_map, dm->set_ant_path & 0xff);
5642
5643 switch (type) {
5644 case BTC_ANT_WPOWERON:
5645 cx_ctrl = BTC_CTRL_BY_BT;
5646 break;
5647 case BTC_ANT_WINIT:
5648 cx_ctrl = BTC_CTRL_BY_WL;
5649 /* To avoid BT MP driver case (bt_enable but no mailbox) */
5650 if ((cx->bt0.enable.now && cx->bt0.run_patch_code) ||
5651 (cx->bt1.enable.now && cx->bt1.run_patch_code))
5652 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
5653 BTC_WLACT_SW_LO);
5654 else
5655 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
5656 BTC_WLACT_SW_HI);
5657 break;
5658 case BTC_ANT_WONLY:
5659 cx_ctrl = BTC_CTRL_BY_WL;
5660 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
5661 BTC_WLACT_SW_HI);
5662 break;
5663 case BTC_ANT_WOFF:
5664 cx_ctrl = BTC_CTRL_BY_BT;
5665 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
5666 BTC_WLACT_SW_LO);
5667 break;
5668 case BTC_ANT_PTA:
5669 default:
5670 cx_ctrl = BTC_CTRL_BY_WL;
5671 gbt = BTC_GNT_HW;
5672 if ((rtwdev->chip->para_ver & BTC_FEAT_MULTI_PTA) ||
5673 !wl_rinfo->dbcc_en) {
5674 gwl = BTC_GNT_HW;
5675 _set_gnt(rtwdev, BTC_PHY_ALL, gwl, gbt, BTC_WLACT_HW);
5676 } else {
5677 /* for DBCC Only-1-PTA */
5678 if (wl_rinfo->dbcc_2g_phy == RTW89_PHY_0) {
5679 gwl0 = BTC_GNT_HW;
5680 gwl1 = BTC_GNT_SW_HI;
5681 } else {
5682 gwl0 = BTC_GNT_SW_HI;
5683 gwl1 = BTC_GNT_HW;
5684 }
5685 _set_gnt(rtwdev, BTC_PHY_0, gwl0, gbt, BTC_WLACT_HW);
5686 _set_gnt(rtwdev, BTC_PHY_1, gwl1, gbt, BTC_WLACT_HW);
5687 }
5688 break;
5689 case BTC_ANT_FDD:
5690 cx_ctrl = BTC_CTRL_BY_WL;
5691 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_HW,
5692 BTC_WLACT_HW);
5693 break;
5694 case BTC_ANT_FREERUN:
5695 cx_ctrl = BTC_CTRL_BY_WL;
5696 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_HI,
5697 BTC_WLACT_SW_LO);
5698 break;
5699 case BTC_ANT_WRFK:
5700 cx_ctrl = BTC_CTRL_BY_WL;
5701 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
5702 BTC_WLACT_HW);
5703 break;
5704 case BTC_ANT_WRFK2:
5705 cx_ctrl = BTC_CTRL_BY_WL;
5706 _set_gnt(rtwdev, BTC_PHY_ALL, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
5707 BTC_WLACT_SW_HI); /* no BT-Tx */
5708 break;
5709 }
5710
5711 rtw89_chip_cfg_ctrl_path(rtwdev, cx_ctrl);
5712 _set_bt_plut(rtwdev, phy_map, BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
5713 }
5714
_action_wl_only(struct rtw89_dev * rtwdev)5715 static void _action_wl_only(struct rtw89_dev *rtwdev)
5716 {
5717 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
5718 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY);
5719 }
5720
_action_wl_init(struct rtw89_dev * rtwdev)5721 static void _action_wl_init(struct rtw89_dev *rtwdev)
5722 {
5723 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
5724
5725 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT);
5726 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT);
5727 }
5728
_action_wl_off(struct rtw89_dev * rtwdev,u8 mode)5729 static void _action_wl_off(struct rtw89_dev *rtwdev, u8 mode)
5730 {
5731 struct rtw89_btc *btc = &rtwdev->btc;
5732 struct rtw89_btc_dm *dm = &btc->dm;
5733 struct rtw89_btc_cx *cx = &btc->cx;
5734 struct rtw89_btc_wl_info *wl = &cx->wl;
5735
5736 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
5737
5738 if (wl->status.map.rf_off || btc->dm.bt_only)
5739 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF);
5740 else if (wl->status.map.lps == BTC_LPS_RF_ON ||
5741 cx->bt0.whql_test || cx->bt1.whql_test)
5742 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_PTA);
5743
5744 if (dm->out_of_band)
5745 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OFF);
5746 else if (cx->bt0.whql_test || cx->bt1.whql_test)
5747 _set_policy(rtwdev, BTC_CXP_OFFB_BWB4, BTC_ACT_WL_OFF);
5748 else
5749 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
5750 }
5751
_action_freerun(struct rtw89_dev * rtwdev)5752 static void _action_freerun(struct rtw89_dev *rtwdev)
5753 {
5754 struct rtw89_btc *btc = &rtwdev->btc;
5755
5756 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
5757
5758 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN);
5759 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN);
5760
5761 btc->dm.freerun = true;
5762 }
5763
_action_bt_whql(struct rtw89_dev * rtwdev)5764 static void _action_bt_whql(struct rtw89_dev *rtwdev)
5765 {
5766 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
5767
5768 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5769 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL);
5770 }
5771
_action_bt_off(struct rtw89_dev * rtwdev)5772 static void _action_bt_off(struct rtw89_dev *rtwdev)
5773 {
5774 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
5775
5776 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
5777 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF);
5778 }
5779
_action_bt_idle(struct rtw89_dev * rtwdev)5780 static void _action_bt_idle(struct rtw89_dev *rtwdev)
5781 {
5782 struct rtw89_btc *btc = &rtwdev->btc;
5783 struct rtw89_btc_bt_link_info *b = &btc->cx.bt0.link_info;
5784 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5785
5786 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5787
5788 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5789 switch (btc->cx.state_map) {
5790 case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/
5791 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */
5792 if (b->status.map.connect)
5793 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_IDLE);
5794 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
5795 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_DL, BTC_ACT_BT_IDLE);
5796 else
5797 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_UL, BTC_ACT_BT_IDLE);
5798 break;
5799 case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */
5800 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050,
5801 BTC_ACT_BT_IDLE);
5802 break;
5803 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */
5804 _set_policy(rtwdev, BTC_CXP_FIX_TD5050,
5805 BTC_ACT_BT_IDLE);
5806 break;
5807 case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */
5808 _set_policy(rtwdev, BTC_CXP_FIX_TD7010,
5809 BTC_ACT_BT_IDLE);
5810 break;
5811 case BTC_WIDLE: /* wl-idle + bt-idle */
5812 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE);
5813 break;
5814 }
5815 } else { /* dedicated-antenna */
5816 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE);
5817 }
5818 }
5819
_action_bt_hfp(struct rtw89_dev * rtwdev)5820 static void _action_bt_hfp(struct rtw89_dev *rtwdev)
5821 {
5822 struct rtw89_btc *btc = &rtwdev->btc;
5823 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5824
5825 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5826
5827 if (btc->ant_type == BTC_ANT_SHARED) {
5828 if (btc->cx.wl.status.map._4way) {
5829 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP);
5830 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
5831 btc->cx.bt0.scan_rx_low_pri = true;
5832 _set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP);
5833 } else {
5834 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
5835 }
5836 } else {
5837 if (wl->bg_mode)
5838 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
5839 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
5840 _set_policy(rtwdev, BTC_CXP_OFF_EQ5, BTC_ACT_BT_HFP);
5841 else
5842 _set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP);
5843 }
5844 }
5845
_action_bt_hid(struct rtw89_dev * rtwdev)5846 static void _action_bt_hid(struct rtw89_dev *rtwdev)
5847 {
5848 const struct rtw89_chip_info *chip = rtwdev->chip;
5849 struct rtw89_btc *btc = &rtwdev->btc;
5850 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5851 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
5852 struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc;
5853 u16 policy_type = BTC_CXP_OFF_BT;
5854
5855 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5856
5857 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5858 if (wl->status.map._4way) {
5859 policy_type = BTC_CXP_OFF_WL;
5860 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
5861 btc->cx.bt0.scan_rx_low_pri = true;
5862 if (hid->type & BTC_HID_BLE)
5863 policy_type = BTC_CXP_OFF_BWB0;
5864 else
5865 policy_type = BTC_CXP_OFF_BWB2;
5866 } else if (hid->type == BTC_HID_218) {
5867 bt->scan_rx_low_pri = true;
5868 policy_type = BTC_CXP_OFF_BWB2;
5869 } else if (chip->para_ver == 0x1) {
5870 policy_type = BTC_CXP_OFF_BWB3;
5871 } else {
5872 policy_type = BTC_CXP_OFF_BWB1;
5873 }
5874 } else { /* dedicated-antenna */
5875 if (wl->bg_mode)
5876 policy_type = BTC_CXP_OFF_BWB1;
5877 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
5878 policy_type = BTC_CXP_OFF_EQ4;
5879 else
5880 policy_type = BTC_CXP_OFF_EQ3;
5881 }
5882
5883 _set_policy(rtwdev, policy_type, BTC_ACT_BT_HID);
5884 }
5885
_action_bt_a2dp(struct rtw89_dev * rtwdev)5886 static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
5887 {
5888 struct rtw89_btc *btc = &rtwdev->btc;
5889 struct rtw89_btc_dm *dm = &btc->dm;
5890
5891 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5892
5893 dm->slot_dur[CXST_W1] = 20;
5894 dm->slot_dur[CXST_B1] = BTC_B1_MAX;
5895
5896 switch (btc->cx.state_map) {
5897 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
5898 _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
5899 break;
5900 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
5901 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP);
5902 break;
5903 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */
5904 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP);
5905 break;
5906 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
5907 case BTC_WLINKING: /* wl-connecting + bt-A2DP */
5908 if (btc->cx.wl.rfk_info.con_rfk)
5909 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP);
5910 else
5911 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP);
5912 break;
5913 case BTC_WIDLE: /* wl-idle + bt-A2DP */
5914 _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP);
5915 break;
5916 }
5917 }
5918
_action_bt_a2dpsink(struct rtw89_dev * rtwdev)5919 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev)
5920 {
5921 struct rtw89_btc *btc = &rtwdev->btc;
5922
5923 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5924
5925 switch (btc->cx.state_map) {
5926 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */
5927 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK);
5928 break;
5929 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */
5930 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK);
5931 break;
5932 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */
5933 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK);
5934 break;
5935 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */
5936 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK);
5937 break;
5938 case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */
5939 if (btc->cx.wl.rfk_info.con_rfk)
5940 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DPSINK);
5941 else
5942 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
5943 break;
5944 case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */
5945 _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK);
5946 break;
5947 }
5948 }
5949
_action_bt_pan(struct rtw89_dev * rtwdev)5950 static void _action_bt_pan(struct rtw89_dev *rtwdev)
5951 {
5952 struct rtw89_btc *btc = &rtwdev->btc;
5953 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt0.link_info;
5954 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
5955 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
5956
5957 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5958
5959 switch (btc->cx.state_map) {
5960 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */
5961 if (a2dp.active || !pan.exist) {
5962 btc->dm.slot_dur[CXST_W1] = 80;
5963 btc->dm.slot_dur[CXST_B1] = 20;
5964 _set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN);
5965 } else {
5966 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
5967 }
5968 break;
5969 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */
5970 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN);
5971 break;
5972 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */
5973 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN);
5974 break;
5975 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */
5976 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN);
5977 break;
5978 case BTC_WLINKING: /* wl-connecting + bt-PAN */
5979 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO, BTC_ACT_BT_PAN);
5980 break;
5981 case BTC_WIDLE: /* wl-idle + bt-pan */
5982 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN);
5983 break;
5984 }
5985 }
5986
_action_bt_a2dp_hid(struct rtw89_dev * rtwdev)5987 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
5988 {
5989 struct rtw89_btc *btc = &rtwdev->btc;
5990 struct rtw89_btc_dm *dm = &btc->dm;
5991
5992 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5993
5994 dm->slot_dur[CXST_W1] = 20;
5995 dm->slot_dur[CXST_B1] = BTC_B1_MAX;
5996
5997 switch (btc->cx.state_map) {
5998 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */
5999 case BTC_WIDLE: /* wl-idle + bt-A2DP */
6000 _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
6001 break;
6002 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */
6003 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_HID);
6004 break;
6005
6006 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */
6007 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
6008 break;
6009 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */
6010 case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */
6011 if (btc->cx.wl.rfk_info.con_rfk)
6012 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP_HID);
6013 else
6014 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
6015 break;
6016 }
6017 }
6018
_action_bt_a2dp_pan(struct rtw89_dev * rtwdev)6019 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev)
6020 {
6021 struct rtw89_btc *btc = &rtwdev->btc;
6022
6023 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6024
6025 switch (btc->cx.state_map) {
6026 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */
6027 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
6028 break;
6029 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */
6030 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
6031 break;
6032 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */
6033 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN);
6034 break;
6035 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */
6036 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
6037 break;
6038 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */
6039 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN);
6040 break;
6041 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */
6042 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN);
6043 break;
6044 }
6045 }
6046
_action_bt_pan_hid(struct rtw89_dev * rtwdev)6047 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev)
6048 {
6049 struct rtw89_btc *btc = &rtwdev->btc;
6050
6051 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6052
6053 switch (btc->cx.state_map) {
6054 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */
6055 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID);
6056 break;
6057 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */
6058 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID);
6059 break;
6060 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */
6061 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID);
6062 break;
6063 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */
6064 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID);
6065 break;
6066 case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */
6067 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID);
6068 break;
6069 case BTC_WIDLE: /* wl-idle + bt-PAN+HID */
6070 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID);
6071 break;
6072 }
6073 }
6074
_action_bt_bis(struct rtw89_dev * rtwdev)6075 static void _action_bt_bis(struct rtw89_dev *rtwdev)
6076 {
6077 struct rtw89_btc *btc = &rtwdev->btc;
6078 struct rtw89_btc_dm *dm = &btc->dm;
6079 u16 policy_type;
6080
6081 if (dm->bis_tdma)
6082 policy_type = BTC_CXP_OFFE_2GBWISOB;
6083 else
6084 policy_type = BTC_CXP_OFF_EQ0;
6085
6086 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_PTA);
6087 _set_policy(rtwdev, policy_type, BTC_ACT_BT_BIS);
6088 }
6089
_action_bt_cis(struct rtw89_dev * rtwdev)6090 static void _action_bt_cis(struct rtw89_dev *rtwdev)
6091 {
6092 struct rtw89_btc *btc = &rtwdev->btc;
6093 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt0.link_info;
6094 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6095 struct rtw89_btc_dm *dm = &btc->dm;
6096 u16 policy_type;
6097
6098 if (bt_linfo->a2dp_desc.active) {
6099 dm->slot_dur[CXST_W1] = 80;
6100 dm->slot_dur[CXST_B1] = 20;
6101 policy_type = BTC_CXP_PFIX_TDW1B1;
6102 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
6103 policy_type = BTC_CXP_OFF_BWB0;
6104 } else {
6105 policy_type = BTC_CXP_OFF_BWB1;
6106 }
6107
6108 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_PTA);
6109 _set_policy(rtwdev, policy_type, BTC_ACT_BT_CIS);
6110 }
6111
_action_bt_a2dp_pan_hid(struct rtw89_dev * rtwdev)6112 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev)
6113 {
6114 struct rtw89_btc *btc = &rtwdev->btc;
6115
6116 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6117
6118 switch (btc->cx.state_map) {
6119 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */
6120 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
6121 BTC_ACT_BT_A2DP_PAN_HID);
6122 break;
6123 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */
6124 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
6125 BTC_ACT_BT_A2DP_PAN_HID);
6126 break;
6127 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */
6128 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070,
6129 BTC_ACT_BT_A2DP_PAN_HID);
6130 break;
6131 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */
6132 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */
6133 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050,
6134 BTC_ACT_BT_A2DP_PAN_HID);
6135 break;
6136 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */
6137 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080,
6138 BTC_ACT_BT_A2DP_PAN_HID);
6139 break;
6140 }
6141 }
6142
_action_wl_5g(struct rtw89_dev * rtwdev)6143 static void _action_wl_5g(struct rtw89_dev *rtwdev)
6144 {
6145 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_FDD);
6146 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G);
6147 }
6148
_action_wl_other(struct rtw89_dev * rtwdev)6149 static void _action_wl_other(struct rtw89_dev *rtwdev)
6150 {
6151 struct rtw89_btc *btc = &rtwdev->btc;
6152
6153 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6154
6155 if (btc->ant_type == BTC_ANT_SHARED)
6156 _set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER);
6157 else
6158 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER);
6159 }
6160
_action_wl_nc(struct rtw89_dev * rtwdev)6161 static void _action_wl_nc(struct rtw89_dev *rtwdev)
6162 {
6163 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6164 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC);
6165 }
6166
_action_wl_rfk(struct rtw89_dev * rtwdev)6167 static void _action_wl_rfk(struct rtw89_dev *rtwdev)
6168 {
6169 struct rtw89_btc *btc = &rtwdev->btc;
6170 struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info;
6171
6172 if (rfk.state != BTC_WRFK_START)
6173 return;
6174
6175 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n",
6176 __func__, rfk.band);
6177
6178 btc->dm.tdma_instant_excute = 1;
6179
6180 if (rfk.state == BTC_WRFK_ONESHOT_START ||
6181 btc->ant_type == BTC_ANT_SHARED) {
6182 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2);
6183 _set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK);
6184 } else {
6185 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
6186 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK);
6187 }
6188 }
6189
_set_btg_ctrl(struct rtw89_dev * rtwdev)6190 static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
6191 {
6192 struct rtw89_btc *btc = &rtwdev->btc;
6193 struct rtw89_btc_dm *dm = &btc->dm;
6194 struct rtw89_btc_fbtc_outsrc_set_info *o_info = &dm->ost_info;
6195 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6196 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
6197 const struct rtw89_chip_info *chip = rtwdev->chip;
6198 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
6199 u32 is_btg = BTC_BTGCTRL_DISABLE;
6200
6201 if (btc->manual_ctrl)
6202 return;
6203
6204 /* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */
6205 if (btc->ant_type == BTC_ANT_SHARED) {
6206 if (!(bt->run_patch_code && bt->enable.now))
6207 is_btg = BTC_BTGCTRL_DISABLE;
6208 else if (wl->rf_band_map[RTW89_MAC_0] & BIT(RTW89_BAND_2G) ||
6209 wl->rf_band_map[RTW89_MAC_1] & BIT(RTW89_BAND_2G))
6210 is_btg = BTC_BTGCTRL_ENABLE;
6211 else
6212 is_btg = BTC_BTGCTRL_DISABLE;
6213
6214 /* bb call ctrl_btg() in WL FW by slot */
6215 if (!btc->ver->fcxosi &&
6216 wl_rinfo->link_mode == BTC_WLINK_DB_MCC)
6217 is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL;
6218 }
6219
6220 if (is_btg == dm->wl_btg_rx)
6221 return;
6222 else
6223 dm->wl_btg_rx = is_btg;
6224
6225 /* skip setup if btg_ctrl set by wl fw */
6226 if (!btc->ver->fcxosi && is_btg > BTC_BTGCTRL_ENABLE)
6227 return;
6228
6229 /* Below flow is for BTC_FEAT_NEW_BBAPI_FLOW = 1 */
6230 if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */
6231 if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */
6232 o_info->btg_rx[BTC_RF_S0] = BTC_BTGCTRL_DISABLE;
6233 else
6234 o_info->btg_rx[BTC_RF_S0] = is_btg;
6235
6236 if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */
6237 o_info->btg_rx[BTC_RF_S1] = BTC_BTGCTRL_DISABLE;
6238 else
6239 o_info->btg_rx[BTC_RF_S1] = is_btg;
6240 } else { /* 2+0 or 0+2 */
6241 o_info->btg_rx[BTC_RF_S0] = is_btg;
6242 o_info->btg_rx[BTC_RF_S1] = is_btg;
6243 }
6244
6245 if (btc->ver->fcxosi)
6246 return;
6247
6248 chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S0],
6249 RTW89_PHY_0);
6250 if (chip->chip_id != RTL8922A)
6251 return;
6252
6253 chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S1],
6254 RTW89_PHY_1);
6255 }
6256
_set_wl_preagc_ctrl(struct rtw89_dev * rtwdev)6257 static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev)
6258 {
6259 struct rtw89_btc *btc = &rtwdev->btc;
6260 struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info;
6261 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt0.link_info;
6262 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6263 struct rtw89_btc_wl_role_info *rinfo = &wl->role_info;
6264 const struct rtw89_chip_info *chip = rtwdev->chip;
6265 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
6266 struct rtw89_btc_dm *dm = &btc->dm;
6267 u8 is_preagc, val;
6268
6269 if (btc->manual_ctrl)
6270 return;
6271
6272 if (!(bt->run_patch_code && bt->enable.now)) {
6273 is_preagc = BTC_PREAGC_DISABLE;
6274 } else if (dm->tdd_bind.rf_band == BIT(RTW89_BAND_5G)) {
6275 is_preagc = BTC_PREAGC_DISABLE;
6276 } else if (rinfo->link_mode == BTC_WLINK_NOLINK ||
6277 btc->cx.bt0.link_info.link_cnt.now == 0) {
6278 is_preagc = BTC_PREAGC_DISABLE;
6279 } else if (dm->tdma_now.type != CXTDMA_OFF &&
6280 !bt_linfo->hfp_desc.exist &&
6281 !bt_linfo->hid_desc.exist &&
6282 dm->fddt_train == BTC_FDDT_DISABLE) {
6283 is_preagc = BTC_PREAGC_DISABLE;
6284 } else if (rinfo->dbcc_en && (rinfo->dbcc_2g_phy != RTW89_PHY_1)) {
6285 is_preagc = BTC_PREAGC_DISABLE;
6286 } else if (btc->ant_type == BTC_ANT_SHARED) {
6287 is_preagc = BTC_PREAGC_DISABLE;
6288 } else {
6289 is_preagc = BTC_PREAGC_ENABLE;
6290 }
6291
6292 if (!btc->ver->fcxosi && rinfo->link_mode == BTC_WLINK_DB_MCC)
6293 is_preagc = BTC_PREAGC_BB_FWCTRL;
6294
6295 if (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
6296 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) {
6297 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val);
6298 dm->wl_pre_agc_rb = val;
6299 }
6300
6301 if ((wl->coex_mode == BTC_MODE_NORMAL &&
6302 (dm->run_reason == BTC_RSN_NTFY_INIT ||
6303 dm->run_reason == BTC_RSN_NTFY_SWBAND ||
6304 dm->wl_pre_agc_rb != dm->wl_pre_agc)) ||
6305 is_preagc != dm->wl_pre_agc) {
6306 dm->wl_pre_agc = is_preagc;
6307
6308 if (!btc->ver->fcxosi && is_preagc > BTC_PREAGC_ENABLE)
6309 return;
6310
6311 if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */
6312 if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */
6313 o_info->nbtg_tx[BTC_RF_S0] = BTC_PREAGC_DISABLE;
6314 else
6315 o_info->nbtg_tx[BTC_RF_S0] = is_preagc;
6316
6317 if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */
6318 o_info->nbtg_tx[BTC_RF_S1] = BTC_PREAGC_DISABLE;
6319 else
6320 o_info->nbtg_tx[BTC_RF_S1] = is_preagc;
6321
6322 } else { /* 2+0 or 0+2 */
6323 o_info->nbtg_tx[BTC_RF_S0] = is_preagc;
6324 o_info->nbtg_tx[BTC_RF_S1] = is_preagc;
6325 }
6326
6327 if (btc->ver->fcxosi)
6328 return;
6329
6330 chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S0],
6331 RTW89_PHY_0);
6332 if (chip->chip_id != RTL8922A)
6333 return;
6334 chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S1],
6335 RTW89_PHY_1);
6336 }
6337 }
6338
6339 struct rtw89_txtime_data {
6340 struct rtw89_dev *rtwdev;
6341 int type;
6342 u32 tx_time;
6343 u8 tx_retry;
6344 u16 enable;
6345 bool reenable;
6346 };
6347
__rtw89_tx_time_iter(struct rtw89_vif_link * rtwvif_link,struct rtw89_sta_link * rtwsta_link,struct rtw89_txtime_data * iter_data)6348 static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link,
6349 struct rtw89_sta_link *rtwsta_link,
6350 struct rtw89_txtime_data *iter_data)
6351 {
6352 struct rtw89_dev *rtwdev = iter_data->rtwdev;
6353 struct rtw89_btc *btc = &rtwdev->btc;
6354 struct rtw89_btc_cx *cx = &btc->cx;
6355 struct rtw89_btc_wl_info *wl = &cx->wl;
6356 struct rtw89_btc_wl_link_info *plink = NULL;
6357 u8 port = rtwvif_link->port;
6358 u32 tx_time = iter_data->tx_time;
6359 u8 tx_retry = iter_data->tx_retry;
6360 u16 enable = iter_data->enable;
6361 bool reenable = iter_data->reenable;
6362
6363 plink = &wl->rlink_info[port][rtwsta_link->link_id];
6364
6365 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6366 "[BTC], %s(): port = %d\n", __func__, port);
6367
6368 if (!plink->connected) {
6369 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6370 "[BTC], %s(): connected = %d\n",
6371 __func__, plink->connected);
6372 return;
6373 }
6374
6375 /* backup the original tx time before tx-limit on */
6376 if (reenable) {
6377 rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time);
6378 rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry);
6379 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6380 "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n",
6381 __func__, plink->tx_time, plink->tx_retry);
6382 }
6383
6384 /* restore the original tx time if no tx-limit */
6385 if (!enable) {
6386 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time);
6387 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true,
6388 plink->tx_retry);
6389 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6390 "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n",
6391 __func__, plink->tx_time, plink->tx_retry);
6392
6393 } else {
6394 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time);
6395 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry);
6396 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6397 "[BTC], %s(): set, tx_time=%d tx_retry= %d\n",
6398 __func__, tx_time, tx_retry);
6399 }
6400 }
6401
rtw89_tx_time_iter(void * data,struct ieee80211_sta * sta)6402 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
6403 {
6404 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
6405 struct rtw89_txtime_data *iter_data =
6406 (struct rtw89_txtime_data *)data;
6407 struct rtw89_vif_link *rtwvif_link;
6408 struct rtw89_sta_link *rtwsta_link;
6409 unsigned int link_id;
6410
6411 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
6412 rtwvif_link = rtwsta_link->rtwvif_link;
6413 __rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data);
6414 }
6415 }
6416
_set_wl_tx_limit(struct rtw89_dev * rtwdev)6417 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
6418 {
6419 struct rtw89_btc *btc = &rtwdev->btc;
6420 struct rtw89_btc_cx *cx = &btc->cx;
6421 struct rtw89_btc_dm *dm = &btc->dm;
6422 struct rtw89_btc_wl_info *wl = &cx->wl;
6423 struct rtw89_btc_bt_info *bt = &cx->bt0;
6424 struct rtw89_btc_bt_link_info *b = &bt->link_info;
6425 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
6426 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
6427 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
6428 struct rtw89_txtime_data data = {.rtwdev = rtwdev};
6429 bool reenable = false;
6430 u8 tx_retry;
6431 u32 tx_time;
6432 u16 enable;
6433
6434 if (btc->manual_ctrl)
6435 return;
6436
6437 if (btc->dm.freerun || btc->ctrl.igno_bt || b->link_cnt.now == 0 ||
6438 dm->tdd_bind.rf_band == BIT(RTW89_BAND_5G) ||
6439 wl_rinfo->link_mode == BTC_WLINK_NOLINK) {
6440 enable = 0;
6441 tx_time = BTC_MAX_TX_TIME_DEF;
6442 tx_retry = BTC_MAX_TX_RETRY_DEF;
6443 } else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) {
6444 enable = 1;
6445 tx_time = BTC_MAX_TX_TIME_L2;
6446 tx_retry = BTC_MAX_TX_RETRY_L1;
6447 } else if (hfp->exist || hid->exist) {
6448 enable = 1;
6449 tx_time = BTC_MAX_TX_TIME_L3;
6450 tx_retry = BTC_MAX_TX_RETRY_L1;
6451 } else {
6452 enable = 0;
6453 tx_time = BTC_MAX_TX_TIME_DEF;
6454 tx_retry = BTC_MAX_TX_RETRY_DEF;
6455 }
6456
6457 if (dm->wl_tx_limit.enable == enable &&
6458 dm->wl_tx_limit.tx_time == tx_time &&
6459 dm->wl_tx_limit.tx_retry == tx_retry)
6460 return;
6461
6462 if (!dm->wl_tx_limit.enable && enable)
6463 reenable = true;
6464
6465 dm->wl_tx_limit.enable = enable;
6466 dm->wl_tx_limit.tx_time = tx_time;
6467 dm->wl_tx_limit.tx_retry = tx_retry;
6468
6469 data.enable = enable;
6470 data.tx_time = tx_time;
6471 data.tx_retry = tx_retry;
6472 data.reenable = reenable;
6473
6474 ieee80211_iterate_stations_atomic(rtwdev->hw,
6475 rtw89_tx_time_iter,
6476 &data);
6477 }
6478
_set_phl_bt_slot_req(struct rtw89_dev * rtwdev)6479 static void _set_phl_bt_slot_req(struct rtw89_dev *rtwdev)
6480 {
6481 struct rtw89_btc *btc = &rtwdev->btc;
6482 struct rtw89_btc_cx *cx = &btc->cx;
6483 struct rtw89_btc_wl_info *wl = &cx->wl;
6484 struct rtw89_btc_dm *dm = &btc->dm;
6485 u8 len = 0;
6486 u8 i;
6487
6488 /* don't change bt slot req state during RFK for p2p/mcc case */
6489 if (dm->run_reason == BTC_RSN_NTFY_WL_RFK ||
6490 wl->status.map.transacting)
6491 return;
6492
6493 /* enable bt-slot req if ext-slot-control */
6494 if (dm->tdma_now.type == CXTDMA_OFF &&
6495 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
6496 dm->tdd_bind.bt_sel != 0) {
6497 if (btc->cx.wl.status.val & btc_scanning_map.val)
6498 btc->bt_req_en = false;
6499 else
6500 btc->bt_req_en = true;
6501 } else {
6502 btc->bt_req_en = false;
6503 }
6504
6505 if (dm->slot_req_more) {
6506 len = BTC_BSLOT_A2DP_HID;
6507 } else {
6508 if (dm->tdd_bind.bt_link_weight >= BTC_BSLOT_A2DP_HID)
6509 len = BTC_BSLOT_A2DP_HID;
6510 else if (dm->tdd_bind.bt_link_weight <= BTC_BSLOT_IDLE)
6511 len = BTC_BSLOT_IDLE;
6512 else
6513 len = dm->tdd_bind.bt_link_weight;
6514 }
6515
6516 if (dm->tdd_bind.rf_band == BIT(RTW89_BAND_5G))
6517 len = 100 - len;
6518
6519 if (!btc->bt_req_en)
6520 len = 0;
6521
6522 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++) {
6523 if (!(dm->tdd_bind.wl_hwb_sel & BIT(i)))
6524 continue;
6525
6526 if (len == btc->bt_req_len[i])
6527 continue;
6528
6529 btc->bt_req_len[i] = len;
6530
6531 rtw89_core_ntfy_btc_event(rtwdev,
6532 RTW89_BTC_HMSG_SET_BT_REQ_SLOT, i);
6533
6534 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6535 "[BTC], %s(): HWB%d bt_req_len = %d\n",
6536 __func__, i, btc->bt_req_len[i]);
6537 }
6538 }
6539
_set_bt_rx_agc(struct rtw89_dev * rtwdev)6540 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
6541 {
6542 struct rtw89_btc *btc = &rtwdev->btc;
6543 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6544 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
6545 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
6546 bool bt_hi_lna_rx = false;
6547
6548 if (wl_rinfo->link_mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
6549 bt_hi_lna_rx = true;
6550
6551 if (bt_hi_lna_rx == bt->hi_lna_rx)
6552 return;
6553
6554 _write_scbd(rtwdev, BTC_BT_1ST, BTC_WSCB_BT_HILNA, bt_hi_lna_rx);
6555 }
6556
_set_bt_rx_scan_pri(struct rtw89_dev * rtwdev)6557 static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev)
6558 {
6559 struct rtw89_btc *btc = &rtwdev->btc;
6560 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
6561
6562 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_RXSCAN_PRI,
6563 (bool)(!!bt->scan_rx_low_pri));
6564 }
6565
_wl_req_mac(struct rtw89_dev * rtwdev,u8 mac)6566 static void _wl_req_mac(struct rtw89_dev *rtwdev, u8 mac)
6567 {
6568 struct rtw89_btc *btc = &rtwdev->btc;
6569 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6570 struct rtw89_btc_dm *dm = &btc->dm;
6571 u32 add;
6572
6573 if (mac == wl->pta_req_mac)
6574 return;
6575
6576 dm->ost_info.pta_req_hw_band = mac;
6577 wl->pta_req_mac = mac;
6578 wl->pta_reg_mac_chg = true;
6579
6580 if (btc->ver->fcxosi)
6581 return;
6582
6583 if (rtwdev->chip->chip_gen == RTW89_CHIP_BE)
6584 add = R_BE_BTC_CFG;
6585 else
6586 add = R_AX_BTC_CFG;
6587
6588 if (mac == RTW89_MAC_0)
6589 rtw89_write32_clr(rtwdev, add, B_AX_WL_SRC);
6590 else
6591 rtw89_write32_set(rtwdev, add, B_AX_WL_SRC);
6592 }
6593
_update_zb_coex_tbl(struct rtw89_dev * rtwdev)6594 static void _update_zb_coex_tbl(struct rtw89_dev *rtwdev)
6595 {
6596 struct rtw89_btc *btc = &rtwdev->btc;
6597 u32 zb_tbl0 = 0xda5a5a5a, zb_tbl1 = 0xda5a5a5a;
6598 u8 link_mode_chg = btc->cx.wl.link_mode_chg;
6599 u8 mode = btc->cx.wl.role_info.link_mode;
6600
6601 if (btc->dm.run_reason != BTC_RSN_NTFY_INIT && !link_mode_chg)
6602 return;
6603
6604 if (!(btc->mdinfo.wa_type & BTC_WA_HFP_ZB))
6605 return;
6606
6607 if (btc->dm.tdd_bind.rf_band == BIT(RTW89_BAND_5G) ||
6608 rtwdev->btc.dm.freerun) {
6609 zb_tbl0 = 0xffffffff;
6610 zb_tbl1 = 0xffffffff;
6611 } else if (mode == BTC_WLINK_DB_MCC) {
6612 zb_tbl0 = 0xffffffff; /* for E5G slot */
6613 zb_tbl1 = 0xda5a5a5a; /* for E2G slot */
6614 }
6615 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_0, zb_tbl0);
6616 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_1, zb_tbl1);
6617 }
6618
_set_fw_report_map(struct rtw89_dev * rtwdev)6619 static void _set_fw_report_map(struct rtw89_dev *rtwdev)
6620 {
6621 struct rtw89_btc *btc = &rtwdev->btc;
6622 struct rtw89_btc_wl_smap *wl_smap = &btc->cx.wl.status.map;
6623 struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0;
6624 struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1;
6625 u32 rpt_map = btc->fwinfo.rpt_en_map;
6626 u32 bt_rom_code_id, bt_fw_ver;
6627 bool bt_ver_unknown = false;
6628 u32 bitmap;
6629
6630 if (wl_smap->rf_off == 1 || wl_smap->lps != BTC_LPS_OFF) {
6631 rtw89_btc_fw_en_rpt(rtwdev, false, 0);
6632 return;
6633 }
6634
6635 rpt_map |= rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_MREG);
6636
6637 bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_SCAN_INFO);
6638 if ((bt0->run_patch_code && bt0->enable.now) ||
6639 (bt1->run_patch_code && bt1->enable.now))
6640 rpt_map |= bitmap;
6641 else
6642 rpt_map &= ~bitmap;
6643
6644 bt_rom_code_id = chip_id_to_bt_rom_code_id(rtwdev->btc.ver->chip_id);
6645 bt_fw_ver = bt0->ver_info.fw & 0xffff;
6646 if (bt_fw_ver == 0 ||
6647 (bt_fw_ver == bt_rom_code_id && bt0->run_patch_code))
6648 bt_ver_unknown = true;
6649
6650 bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_VER_INFO);
6651 if (bt0->enable.now && bt_ver_unknown)
6652 rpt_map |= bitmap;
6653 else
6654 rpt_map &= ~bitmap;
6655
6656 bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_AFH_MAP) |
6657 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_AFH_MAP_LE) |
6658 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_TX_PWR_LVL);
6659 if (bt0->link_info.link_cnt.now ||
6660 bt0->link_info_56g.link_cnt.now ||
6661 bt1->link_info.link_cnt.now ||
6662 bt1->link_info_56g.link_cnt.now)
6663 rpt_map |= bitmap;
6664 else
6665 rpt_map &= ~bitmap;
6666
6667 bitmap = rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_BT_DEVICE_INFO);
6668 if ((bt0->link_info.a2dp_desc.exist &&
6669 bt0->link_info.a2dp_desc.play_latency) ||
6670 (bt1->link_info.a2dp_desc.exist &&
6671 bt1->link_info.a2dp_desc.play_latency))
6672 rpt_map |= bitmap;
6673 else
6674 rpt_map &= ~bitmap;
6675
6676 rtw89_btc_fw_en_rpt(rtwdev, false, rpt_map);
6677 }
6678
_action_common(struct rtw89_dev * rtwdev)6679 static void _action_common(struct rtw89_dev *rtwdev)
6680 {
6681 struct rtw89_btc *btc = &rtwdev->btc;
6682 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6683 struct rtw89_btc_wl_role_info *rinfo = &wl->role_info;
6684 struct rtw89_btc_dm *dm = &btc->dm;
6685 u8 i;
6686
6687 _wl_req_mac(rtwdev, rinfo->pta_req_band);
6688 _update_zb_coex_tbl(rtwdev);
6689 _set_btg_ctrl(rtwdev);
6690 _set_wl_preagc_ctrl(rtwdev);
6691 _set_wl_tx_limit(rtwdev);
6692 _set_phl_bt_slot_req(rtwdev);
6693 _set_bt_afh_info(rtwdev);
6694 _set_bt_rx_agc(rtwdev);
6695 _set_rf_trx_para(rtwdev);
6696 _set_bt_rx_scan_pri(rtwdev);
6697 _set_fw_report_map(rtwdev);
6698
6699 if (dm->run_reason == BTC_RSN_NTFY_INIT ||
6700 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE ||
6701 dm->run_reason == BTC_RSN_NTFY_POWEROFF)
6702 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6703
6704 for (i = BTC_BT_1ST; i <= BTC_BT_2ND; i++)
6705 _sned_h2c_w2bscbd(rtwdev, false, i);
6706
6707 if (btc->ver->fcxosi) {
6708 if (memcmp(&dm->ost_info_last, &dm->ost_info,
6709 sizeof(dm->ost_info_last)) ||
6710 dm->run_reason == BTC_RSN_NTFY_INIT ||
6711 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE) {
6712 dm->ost_info_last = dm->ost_info;
6713 _fw_set_drv_info(rtwdev, CXDRVINFO_OSI);
6714 }
6715 }
6716 dm->tdma_instant_excute = 0;
6717 dm->lps_ctrl_change = false;
6718 wl->role_info.link_mode_chg = 0;
6719 wl->pta_reg_mac_chg = false;
6720 dm->pre_agc_chg = false;
6721 wl->dbcc_chg = 0;
6722 }
6723
_action_by_bt(struct rtw89_dev * rtwdev)6724 static void _action_by_bt(struct rtw89_dev *rtwdev)
6725 {
6726 struct rtw89_btc *btc = &rtwdev->btc;
6727 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
6728 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
6729 struct rtw89_btc_bt_leaudio_desc leaudio = bt_linfo->leaudio_desc;
6730 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
6731 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
6732 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
6733 struct rtw89_btc_dm *dm = &btc->dm;
6734 u8 profile_map = 0;
6735
6736 if (dm->freerun_chk) {
6737 _action_freerun(rtwdev);
6738 return;
6739 }
6740
6741 if (bt_linfo->hfp_desc.exist)
6742 profile_map |= BTC_BT_HFP;
6743
6744 if (bt_linfo->hid_desc.exist)
6745 profile_map |= BTC_BT_HID;
6746
6747 if (bt_linfo->a2dp_desc.exist)
6748 profile_map |= BTC_BT_A2DP;
6749
6750 if (bt_linfo->pan_desc.exist)
6751 profile_map |= BTC_BT_PAN;
6752
6753 if (leaudio.bis_exist)
6754 profile_map |= BTC_BT_BIS;
6755
6756 if (leaudio.cis_exist)
6757 profile_map |= BTC_BT_CIS;
6758
6759 switch (profile_map) {
6760 case BTC_BT_NOPROFILE:
6761 if (pan.active)
6762 _action_bt_pan(rtwdev);
6763 else
6764 _action_bt_idle(rtwdev);
6765 break;
6766 case BTC_BT_HFP:
6767 _action_bt_hfp(rtwdev);
6768 break;
6769 case BTC_BT_HFP | BTC_BT_HID:
6770 case BTC_BT_HID:
6771 _action_bt_hid(rtwdev);
6772 break;
6773 case BTC_BT_A2DP:
6774 if (a2dp.sink)
6775 _action_bt_a2dpsink(rtwdev);
6776 else if (bt_linfo->multi_link.now && !hid.pair_cnt)
6777 _action_bt_a2dp_pan(rtwdev);
6778 else
6779 _action_bt_a2dp(rtwdev);
6780 break;
6781 case BTC_BT_PAN:
6782 _action_bt_pan(rtwdev);
6783 break;
6784 case BTC_BT_BIS:
6785 _action_bt_bis(rtwdev);
6786 break;
6787 case BTC_BT_CIS:
6788 case BTC_BT_CIS | BTC_BT_HID:
6789 _action_bt_cis(rtwdev);
6790 break;
6791 case BTC_BT_A2DP | BTC_BT_HFP:
6792 case BTC_BT_A2DP | BTC_BT_HID:
6793 case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID:
6794 if (a2dp.sink)
6795 _action_bt_a2dpsink(rtwdev);
6796 else if (pan.active)
6797 _action_bt_a2dp_pan_hid(rtwdev);
6798 else
6799 _action_bt_a2dp_hid(rtwdev);
6800 break;
6801 case BTC_BT_A2DP | BTC_BT_PAN:
6802 if (a2dp.sink)
6803 _action_bt_a2dpsink(rtwdev);
6804 else
6805 _action_bt_a2dp_pan(rtwdev);
6806 break;
6807 case BTC_BT_PAN | BTC_BT_HFP:
6808 case BTC_BT_PAN | BTC_BT_HID:
6809 case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID:
6810 _action_bt_pan_hid(rtwdev);
6811 break;
6812 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID:
6813 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP:
6814 default:
6815 if (a2dp.sink)
6816 _action_bt_a2dpsink(rtwdev);
6817 else
6818 _action_bt_a2dp_pan_hid(rtwdev);
6819 break;
6820 }
6821 }
6822
_action_wl_2g_sta(struct rtw89_dev * rtwdev)6823 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev)
6824 {
6825 _action_by_bt(rtwdev);
6826 }
6827
_action_wl_25g_mcc(struct rtw89_dev * rtwdev)6828 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev)
6829 {
6830 struct rtw89_btc *btc = &rtwdev->btc;
6831 u16 policy_type = BTC_CXP_OFF_BT;
6832
6833 if (btc->ant_type == BTC_ANT_SHARED) {
6834 if (btc->cx.wl.status.map._4way)
6835 policy_type = BTC_CXP_OFFE_WL;
6836 else if (btc->cx.wl.status.val & btc_scanning_map.val)
6837 policy_type = BTC_CXP_OFFE_2GBWMIXB;
6838 else if (btc->cx.bt0.link_info.status.map.connect == 0)
6839 policy_type = BTC_CXP_OFFE_2GISOB;
6840 else
6841 policy_type = BTC_CXP_OFFE_2GBWISOB;
6842 } else { /* dedicated-antenna */
6843 policy_type = BTC_CXP_OFF_EQ0;
6844 }
6845
6846 btc->dm.e2g_slot_limit = BTC_E2G_LIMIT_DEF;
6847
6848 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
6849 _set_policy(rtwdev, policy_type, BTC_ACT_WL_25G_MCC);
6850 }
6851
_action_wl_scan(struct rtw89_dev * rtwdev)6852 static void _action_wl_scan(struct rtw89_dev *rtwdev)
6853 {
6854 struct rtw89_btc *btc = &rtwdev->btc;
6855 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6856 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6857
6858 if (btc->cx.state_map != BTC_WLINKING &&
6859 btc->ctrl.wl_ctrl_info.fw_scan) {
6860 _action_wl_25g_mcc(rtwdev);
6861 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n");
6862 } else if (rtwdev->dbcc_en) {
6863 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G &&
6864 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
6865 _action_wl_5g(rtwdev);
6866 else
6867 _action_by_bt(rtwdev);
6868 } else {
6869 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G)
6870 _action_wl_5g(rtwdev);
6871 else
6872 _action_by_bt(rtwdev);
6873 }
6874 }
6875
_action_wl_2g_mcc(struct rtw89_dev * rtwdev)6876 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev)
6877 { struct rtw89_btc *btc = &rtwdev->btc;
6878
6879 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6880
6881 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6882 if (btc->cx.bt0.link_info.link_cnt.now == 0)
6883 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
6884 BTC_ACT_WL_2G_MCC);
6885 else
6886 _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
6887 BTC_ACT_WL_2G_MCC);
6888 } else { /* dedicated-antenna */
6889 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC);
6890 }
6891 }
6892
_action_wl_2g_scc(struct rtw89_dev * rtwdev)6893 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev)
6894 {
6895 struct rtw89_btc *btc = &rtwdev->btc;
6896 struct rtw89_btc_dm *dm = &btc->dm;
6897 u16 policy_type;
6898
6899 if (!dm->tdd_bind.bt_smap.connect)
6900 policy_type = BTC_CXP_OFFE_2GISOB;
6901 else
6902 policy_type = BTC_CXP_OFFE_2GBWISOB;
6903
6904 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_PTA);
6905 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
6906 }
6907
_action_wl_2g_ap(struct rtw89_dev * rtwdev)6908 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
6909 {
6910 struct rtw89_btc *btc = &rtwdev->btc;
6911
6912 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6913
6914 if (btc->ant_type == BTC_ANT_SHARED) {
6915 if (btc->cx.bt0.link_info.link_cnt.now == 0)
6916 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
6917 BTC_ACT_WL_2G_AP);
6918 else
6919 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP);
6920 } else {/* dedicated-antenna */
6921 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP);
6922 }
6923 }
6924
_action_wl_2g_go(struct rtw89_dev * rtwdev)6925 static void _action_wl_2g_go(struct rtw89_dev *rtwdev)
6926 {
6927 struct rtw89_btc *btc = &rtwdev->btc;
6928
6929 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6930
6931 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6932 if (btc->cx.bt0.link_info.link_cnt.now == 0)
6933 _set_policy(rtwdev,
6934 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO);
6935 else
6936 _set_policy(rtwdev,
6937 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO);
6938 } else { /* dedicated-antenna */
6939 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO);
6940 }
6941 }
6942
_action_wl_2g_gc(struct rtw89_dev * rtwdev)6943 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev)
6944 {
6945 struct rtw89_btc *btc = &rtwdev->btc;
6946
6947 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6948
6949 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6950 _action_by_bt(rtwdev);
6951 } else {/* dedicated-antenna */
6952 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC);
6953 }
6954 }
6955
_action_wl_2g_nan(struct rtw89_dev * rtwdev)6956 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev)
6957 {
6958 struct rtw89_btc *btc = &rtwdev->btc;
6959
6960 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6961
6962 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6963 if (btc->cx.bt0.link_info.link_cnt.now == 0)
6964 _set_policy(rtwdev,
6965 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN);
6966 else
6967 _set_policy(rtwdev,
6968 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN);
6969 } else { /* dedicated-antenna */
6970 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN);
6971 }
6972 }
6973
_sned_h2c_w2bscbd(struct rtw89_dev * rtwdev,bool force_exec,u8 bid)6974 static u8 _sned_h2c_w2bscbd(struct rtw89_dev *rtwdev, bool force_exec, u8 bid)
6975 {
6976 struct rtw89_btc *btc = &rtwdev->btc;
6977 struct rtw89_btc_cx *cx = &btc->cx;
6978 struct rtw89_btc_wl_info *wl = &cx->wl;
6979 u8 cnt_idx = BTC_WCNT_SCBDUPDATE;
6980 u8 h2c_func = SET_IOFLD_SCBD;
6981 u8 buf[4];
6982
6983 if (bid == BTC_BT_2ND) {
6984 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))
6985 return 0;
6986
6987 h2c_func |= BT_H2C_FUNC_BT2ND;
6988 cnt_idx = BTC_WCNT_SCBDUPDATE2;
6989 }
6990
6991 if (wl->scbd_chg[bid] || force_exec) {
6992 /* Add delay to avoid BT FW loss information */
6993
6994 btc_dw2b(buf, 0, (wl->scbd[bid] | BIT(31))); /* trig */
6995 if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO) {
6996 if (!_send_fw_cmd(rtwdev, BTFC_SET,
6997 h2c_func, buf, sizeof(buf)))
6998 return 0;
6999 } else {
7000 rtw89_mac_cfg_sb(rtwdev, wl->scbd[bid]);
7001 }
7002 wl->scbd_chg[bid] = 0;
7003 wl->wcnt[cnt_idx]++;
7004 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7005 "[BTC], %s() write BT%d scbd:0x%08x\n",
7006 __func__, bid, wl->scbd[bid]);
7007 }
7008 return 1;
7009 }
7010
_write_scbd(struct rtw89_dev * rtwdev,u8 bid,u32 val,bool state)7011 static void _write_scbd(struct rtw89_dev *rtwdev, u8 bid, u32 val, bool state)
7012 {
7013 const struct rtw89_chip_info *chip = rtwdev->chip;
7014 struct rtw89_btc *btc = &rtwdev->btc;
7015 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7016 struct rtw89_btc_dm *dm = &btc->dm;
7017 u8 force_exec, id, id_start, id_stop;
7018 u32 scbd = 0;
7019
7020 if (!chip->scbd)
7021 return;
7022
7023 if (bid == BTC_ALL_BT) {
7024 id_start = BTC_BT_1ST;
7025 id_stop = BTC_BT_2ND;
7026 } else {
7027 id_start = bid;
7028 id_stop = bid;
7029 }
7030
7031 for (id = id_start; id <= id_stop; id++) {
7032 force_exec = false;
7033 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) &&
7034 id == BTC_BT_2ND)
7035 continue;
7036
7037 if (state)
7038 scbd = wl->scbd[id] | val;
7039 else
7040 scbd = wl->scbd[id] & (~val);
7041
7042 if (val & BTC_WSCB_CTCODE ||
7043 val & BTC_WSCB_RXGAIN ||
7044 val & BTC_WSCB_RXGAIN_56G) { /* instant exec */
7045 force_exec = true;
7046 wl->scbd[id] = scbd;
7047 dm->scbd_write_instant = 1;
7048 if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO)
7049 _sned_h2c_w2bscbd(rtwdev, force_exec, id);
7050 else
7051 rtw89_mac_cfg_sb(rtwdev, wl->scbd[id]);
7052 dm->scbd_write_instant = 0;
7053 } else if ((val & BTC_WSCB_ACTIVE ||
7054 val & BTC_WSCB_ON ||
7055 val & BTC_WSCB_WLRFK) ||
7056 scbd != wl->scbd[id]) {
7057 /*
7058 * Just update wl->scbd[] and set wl->scbd_chg[],
7059 * moved "Write scoreboard I/O" to _action_common()
7060 * _write_scbd will be executed if run_coex()
7061 */
7062 wl->scbd[id] = scbd;
7063 wl->scbd_chg[id] = 1;
7064 }
7065 }
7066 }
7067
7068 static u8
_update_rssi_state(struct rtw89_dev * rtwdev,u8 pre_state,u8 rssi,u8 thresh)7069 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh)
7070 {
7071 const struct rtw89_chip_info *chip = rtwdev->chip;
7072 u8 next_state, tol = chip->rssi_tol;
7073
7074 if (pre_state == BTC_RSSI_ST_LOW ||
7075 pre_state == BTC_RSSI_ST_STAY_LOW) {
7076 if (rssi >= (thresh + tol))
7077 next_state = BTC_RSSI_ST_HIGH;
7078 else
7079 next_state = BTC_RSSI_ST_STAY_LOW;
7080 } else {
7081 if (rssi < thresh)
7082 next_state = BTC_RSSI_ST_LOW;
7083 else
7084 next_state = BTC_RSSI_ST_STAY_HIGH;
7085 }
7086
7087 return next_state;
7088 }
7089
7090 static
_update_dbcc_band(struct rtw89_dev * rtwdev,enum rtw89_phy_idx phy_idx)7091 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
7092 {
7093 struct rtw89_btc *btc = &rtwdev->btc;
7094
7095 btc->cx.wl.dbcc_info.real_band[phy_idx] =
7096 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ?
7097 btc->cx.wl.dbcc_info.scan_band[phy_idx] :
7098 btc->cx.wl.dbcc_info.op_band[phy_idx];
7099 }
7100
7101 #define BTC_CHK_HANG_MAX 3
7102 #define BTC_SCB_INV_VALUE GENMASK(31, 0)
7103
_get_role_link_mode(u8 role)7104 static u8 _get_role_link_mode(u8 role)
7105 {
7106 switch (role) {
7107 case RTW89_WIFI_ROLE_STATION:
7108 default:
7109 return BTC_WLINK_STA;
7110 case RTW89_WIFI_ROLE_P2P_GO:
7111 return BTC_WLINK_GO;
7112 case RTW89_WIFI_ROLE_P2P_CLIENT:
7113 return BTC_WLINK_GC;
7114 case RTW89_WIFI_ROLE_AP:
7115 return BTC_WLINK_AP;
7116 }
7117 }
7118
_chk_role_ch_group(const struct rtw89_btc_chdef * r1,const struct rtw89_btc_chdef * r2)7119 static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1,
7120 const struct rtw89_btc_chdef *r2)
7121 {
7122 if (r1->chan != r2->chan) { /* primary ch is different */
7123 return false;
7124 } else if (r1->bw == RTW89_CHANNEL_WIDTH_40 &&
7125 r2->bw == RTW89_CHANNEL_WIDTH_40) {
7126 if (r1->offset != r2->offset)
7127 return false;
7128 }
7129 return true;
7130 }
7131
_chk_dbcc(struct rtw89_dev * rtwdev,struct rtw89_btc_chdef * ch,u8 * phy,u8 * role,u8 link_cnt)7132 static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch,
7133 u8 *phy, u8 *role, u8 link_cnt)
7134 {
7135 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
7136 struct rtw89_btc_wl_role_info *rinfo = &wl->role_info;
7137 bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false;
7138 u8 j, k, dbcc_2g_cid = 0, dbcc_2g_cid2 = 0;
7139
7140 /* find out the 2G-PHY by connect-id ->ch */
7141 for (j = 0; j < link_cnt; j++) {
7142 if (ch[j].center_ch <= 14) {
7143 is_2g_ch_exist = true;
7144 break;
7145 }
7146 }
7147
7148 /* If no any 2G-port exist, it's impossible because 5G-exclude */
7149 if (!is_2g_ch_exist)
7150 return BTC_WLINK_SB_MCC;
7151
7152 dbcc_2g_cid = j;
7153 rinfo->dbcc_2g_phy = phy[dbcc_2g_cid];
7154
7155 if (rinfo->dbcc_2g_phy == RTW89_PHY_1)
7156 rinfo->pta_req_band = RTW89_PHY_1;
7157 else
7158 rinfo->pta_req_band = RTW89_PHY_0;
7159
7160 /* connect_cnt <= 2 */
7161 if (link_cnt < BTC_TDMA_WLROLE_MAX)
7162 return _get_role_link_mode(role[dbcc_2g_cid]);
7163
7164 /* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */
7165 for (k = 0; k < link_cnt; k++) {
7166 if (k == dbcc_2g_cid)
7167 continue;
7168
7169 if (phy[k] == rinfo->dbcc_2g_phy) {
7170 is_multi_role_in_2g_phy = true;
7171 dbcc_2g_cid2 = k;
7172 break;
7173 }
7174 }
7175
7176 /* Single-role in 2G-PHY */
7177 if (!is_multi_role_in_2g_phy)
7178 return _get_role_link_mode(role[dbcc_2g_cid]);
7179
7180 /* 2-role in 2G-PHY */
7181 if (ch[dbcc_2g_cid2].center_ch > 14)
7182 return BTC_WLINK_DB_MCC;
7183 else if (_chk_role_ch_group(&ch[dbcc_2g_cid], &ch[dbcc_2g_cid2]))
7184 return BTC_WLINK_SCC;
7185 else
7186 return BTC_WLINK_SB_MCC;
7187 }
7188
_update_wl_link_mode(struct rtw89_dev * rtwdev,u8 hw_band,u8 type)7189 static void _update_wl_link_mode(struct rtw89_dev *rtwdev, u8 hw_band, u8 type)
7190 {
7191 struct rtw89_btc *btc = &rtwdev->btc;
7192 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7193 struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info;
7194 struct rtw89_btc_wl_role_info *r = &wl->role_info;
7195 u8 p2p_exist = wl->role_info.p2p_exist;
7196
7197 if (hw_band == RTW89_PHY_1)
7198 p2p_exist = wl->role_info.p2p_exist_hb1;
7199
7200 /* MLD: nLmR --> 2L1R: 2-Link by 1-RF, 2L2R: 2-link by 2-RF */
7201 switch (type) {
7202 case RTW89_MR_WTYPE_NONE: /* no-link */
7203 r->link_mode = BTC_WLINK_NOLINK;
7204 break;
7205 case RTW89_MR_WTYPE_NONMLD: /* Non_MLO 1-role 2+0/0+2 */
7206 case RTW89_MR_WTYPE_MLD1L1R: /* MLO only-1 link 2+0/0+2 */
7207 if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) {
7208 r->link_mode = BTC_WLINK_GO;
7209 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT &&
7210 p2p_exist) {
7211 r->link_mode = BTC_WLINK_GC;
7212 } else {
7213 r->link_mode = BTC_WLINK_STA;
7214 }
7215 break;
7216 case RTW89_MR_WTYPE_NONMLD_NONMLD: /* Non_MLO 2-role 2+0/0+2 */
7217 case RTW89_MR_WTYPE_MLD1L1R_NONMLD: /* MLO only-1 link + P2P 2+0/0+2 */
7218 if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_5GHZ ||
7219 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_6GHZ) {
7220 r->link_mode = BTC_WLINK_DB_MCC;
7221 } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ ||
7222 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_5GHZ ||
7223 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_6GHZ ||
7224 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_5GHZ_6GHZ) {
7225 r->link_mode = BTC_WLINK_SB_MCC;
7226 } else {
7227 r->link_mode = BTC_WLINK_SCC;
7228 }
7229 break;
7230 case RTW89_MR_WTYPE_MLD2L1R: /* MLO_MLSR 2+0/0+2 */
7231 if (p2p_exist) /* MLO_MLSR only support STA/GC */
7232 r->link_mode = BTC_WLINK_GC;
7233 else
7234 r->link_mode = BTC_WLINK_STA;
7235 break;
7236 case RTW89_MR_WTYPE_MLD2L1R_NONMLD: /* MLO_MLSR + P2P 2+0/0+2 */
7237 case RTW89_MR_WTYPE_MLD2L2R_NONMLD: /* MLO_MLMR + P2P 1+1/2+2*/
7238 /* driver may doze 1-link (1+1) or 2+0->0+2->1+1
7239 * 2G+5G -> TDMA slot switch by E2G/E5G
7240 * 5G only -> TDMA slot switch by E5G
7241 */
7242 r->link_mode = BTC_WLINK_DB_MCC;
7243 break;
7244 case RTW89_MR_WTYPE_MLD2L2R: /* MLO_MLMR 1+1/2+2 */
7245 /* MLMR only support STA now (2024) */
7246 r->link_mode = BTC_WLINK_STA;
7247 break;
7248 }
7249 }
7250
_update_wl_mlo_info(struct rtw89_dev * rtwdev,u8 hw_band)7251 static void _update_wl_mlo_info(struct rtw89_dev *rtwdev, u8 hw_band)
7252 {
7253 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
7254 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
7255 struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info;
7256 struct rtw89_mr_chanctx_info qinfo;
7257 struct rtw89_chanctx *ch;
7258 u8 rf_band = RTW89_BAND_2G;
7259 u8 i, type;
7260
7261 /* parse MLO info form PHL API for each HW-band */
7262 for (i = RTW89_MAC_0; i <= RTW89_MAC_1; i++) {
7263 memset(&qinfo, 0, sizeof(qinfo));
7264
7265 rtw89_query_mr_chanctx_info(rtwdev, i, &qinfo);
7266
7267 switch (qinfo.ctxtype) {
7268 default:
7269 mlo_info->hwb_rf_band[i] = 0;
7270 break;
7271 case RTW89_MR_CTX1_2GHZ:
7272 case RTW89_MR_CTX2_2GHZ:
7273 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_2G);
7274 break;
7275 case RTW89_MR_CTX1_5GHZ:
7276 case RTW89_MR_CTX2_5GHZ:
7277 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_5G);
7278 break;
7279 case RTW89_MR_CTX1_6GHZ:
7280 case RTW89_MR_CTX2_6GHZ:
7281 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_6G);
7282 break;
7283 case RTW89_MR_CTX2_2GHZ_5GHZ:
7284 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_2G) |
7285 BIT(RTW89_BAND_5G);
7286 break;
7287 case RTW89_MR_CTX2_2GHZ_6GHZ:
7288 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_2G) |
7289 BIT(RTW89_BAND_6G);
7290 break;
7291 case RTW89_MR_CTX2_5GHZ_6GHZ:
7292 mlo_info->hwb_rf_band[i] = BIT(RTW89_BAND_5G) |
7293 BIT(RTW89_BAND_6G);
7294 break;
7295 }
7296 mlo_info->wmode[i] = qinfo.wmode;
7297 mlo_info->ch_type[i] = qinfo.ctxtype;
7298 mlo_info->wtype = qinfo.wtype;
7299 wl->rf_band_map[i] = mlo_info->hwb_rf_band[i];
7300 ch = &rtwdev->hal.chanctx[i];
7301 wl->rf_ch_info[i].center_ch = ch->chan.channel;
7302 wl->rf_ch_info[i].band = ch->chan.band_type;
7303 wl->rf_ch_info[i].chan = ch->chan.channel;
7304 wl->rf_ch_info[i].offset = ch->chan.pri_ch_idx;
7305 wl->rf_ch_info[i].bw = ch->chan.band_width;
7306 }
7307
7308 mlo_info->link_status = rtwdev->mlo_dbcc_mode;
7309 type = mlo_info->wtype;
7310
7311 if (mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R ||
7312 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R ||
7313 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R ||
7314 mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R_NONMLD ||
7315 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD ||
7316 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R_NONMLD)
7317 mlo_info->mlo_en = 1;
7318 else
7319 mlo_info->mlo_en = 0;
7320
7321 if (mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_NONE &&
7322 mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_UNKNOWN &&
7323 mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_NONE &&
7324 mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_UNKNOWN)
7325 mlo_info->dual_hw_band_en = 1; /* two HW-hand link exist */
7326 else
7327 mlo_info->dual_hw_band_en = 0;
7328
7329 if (mlo_info->link_status == MLO_2_PLUS_0_2RF ||
7330 mlo_info->link_status == MLO_0_PLUS_2_2RF ||
7331 mlo_info->link_status == MLO_2_PLUS_2_2RF)
7332 mlo_info->mlo_adie = 2;
7333 else
7334 mlo_info->mlo_adie = 1;
7335
7336 switch (mlo_info->link_status) {
7337 default:
7338 case MLO_2_PLUS_0_1RF: /* 2+0 */
7339 case MLO_2_PLUS_0_2RF:
7340 _update_wl_link_mode(rtwdev, RTW89_MAC_0, type);
7341 wl_rinfo->link_mode_hb1 = wl_rinfo->link_mode;
7342 wl_rinfo->pta_req_band = RTW89_MAC_0;
7343 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0;
7344 wl_rinfo->dbcc_en = 0;
7345
7346 rf_band = wl->rf_band_map[RTW89_PHY_0];
7347 mlo_info->path_rf_band[BTC_RF_S0] = rf_band;
7348 mlo_info->path_rf_band[BTC_RF_S1] = rf_band;
7349 break;
7350 case MLO_0_PLUS_2_1RF: /* 0+2 */
7351 case MLO_0_PLUS_2_2RF:
7352 _update_wl_link_mode(rtwdev, RTW89_MAC_1, type);
7353 wl_rinfo->link_mode_hb1 = wl_rinfo->link_mode;
7354 wl_rinfo->pta_req_band = RTW89_MAC_1;
7355 wl_rinfo->dbcc_2g_phy = RTW89_PHY_1;
7356 wl_rinfo->dbcc_en = 0;
7357
7358 rf_band = wl->rf_band_map[RTW89_PHY_1];
7359 mlo_info->path_rf_band[BTC_RF_S0] = rf_band;
7360 mlo_info->path_rf_band[BTC_RF_S1] = rf_band;
7361 break;
7362 case MLO_1_PLUS_1_1RF: /* 1+1 */
7363 case MLO_1_PLUS_1_2RF: /* 1+1 */
7364 case MLO_2_PLUS_2_2RF: /* 2+2 */
7365 case DBCC_LEGACY: /* DBCC 1+1 */
7366 /* Check ch count from ch_type and modify type*/
7367 if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_2GHZ ||
7368 mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_5GHZ ||
7369 mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_6GHZ)
7370 type = RTW89_MR_WTYPE_NONMLD; /* only 1-role */
7371 else
7372 type = RTW89_MR_WTYPE_NONMLD_NONMLD;
7373
7374 rf_band = wl->rf_band_map[hw_band];
7375 _update_wl_link_mode(rtwdev, hw_band, type);
7376
7377 if (hw_band == RTW89_MAC_0) {
7378 mlo_info->path_rf_band[BTC_RF_S0] = rf_band;
7379 } else {
7380 wl_rinfo->link_mode_hb1 = wl_rinfo->link_mode;
7381 mlo_info->path_rf_band[BTC_RF_S1] = rf_band;
7382 }
7383
7384 /* set pta_req_band for 1-PTA architecture */
7385 if (wl->rf_band_map[RTW89_MAC_0] & BIT(RTW89_BAND_2G)) {
7386 wl_rinfo->pta_req_band = RTW89_MAC_0;
7387 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0;
7388 } else if (wl->rf_band_map[RTW89_MAC_1] & BIT(RTW89_BAND_2G)) {
7389 wl_rinfo->pta_req_band = RTW89_MAC_1;
7390 wl_rinfo->dbcc_2g_phy = RTW89_PHY_1;
7391 } else { /* Both HW-BAND are not on 2.4G*/
7392 wl_rinfo->pta_req_band = RTW89_MAC_0;
7393 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0;
7394 }
7395 break;
7396 }
7397
7398 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(), mode=%s, pta_band=%d",
7399 __func__, id_to_linkmode(wl_rinfo->link_mode),
7400 wl_rinfo->pta_req_band);
7401 }
7402
_update_wl_non_mlo_info(struct rtw89_dev * rtwdev)7403 static void _update_wl_non_mlo_info(struct rtw89_dev *rtwdev)
7404 {
7405 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
7406 struct rtw89_btc_wl_rlink *rlink = NULL;
7407 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
7408 struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7409 u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7410 u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7411 bool b2g = false, b5g = false, outloop = false;
7412 u8 mode = BTC_WLINK_NOLINK;
7413 u8 cnt_2g = 0, cnt_5g = 0;
7414 u8 i, j, cnt = 0;
7415
7416 for (j = RTW89_PHY_0; j < RTW89_PHY_NUM; j++) {
7417 wl->rf_band_map[j] = 0; /* j=link id, is the link use which band */
7418 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
7419 rlink = &wl_rinfo->rlink[i][j];
7420
7421 if (!rlink->active || !rlink->connected)
7422 continue;
7423
7424 if (cnt >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER) {
7425 outloop = true;
7426 break;
7427 }
7428
7429 cid_ch[cnt] = wl->rlink_info[i][j].chdef;
7430 cid_phy[cnt] = rlink->phy;
7431 cid_role[cnt] = rlink->role;
7432 cnt++;
7433
7434 if (rlink->rf_band != RTW89_BAND_2G) {
7435 cnt_5g++;
7436 b5g = true;
7437 } else {
7438 cnt_2g++;
7439 b2g = true;
7440 }
7441 wl->rf_band_map[j] |= BIT(rlink->rf_band);
7442 }
7443 if (outloop)
7444 break;
7445 }
7446
7447 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7448 "[BTC], %s(): cnt_2g=%d, cnt_5g=%d\n", __func__, cnt_2g, cnt_5g);
7449
7450 wl_rinfo->pta_req_band = RTW89_PHY_0; /* no 0+2 for non-MLO */
7451 wl_rinfo->dbcc_en = rtwdev->dbcc_en;
7452
7453 /* Be careful to change the following sequence!! */
7454 if (cnt == 0) {
7455 mode = BTC_WLINK_NOLINK;
7456 } else if (wl_rinfo->dbcc_en) {
7457 /* update pta_req_band to 2.4GHz HW-BAND for DBCC = 1*/
7458 mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt);
7459 } else if (!b2g && b5g) {
7460 mode = _get_role_link_mode(cid_role[0]);
7461 } else if (b2g && b5g) {
7462 mode = BTC_WLINK_DB_MCC;
7463 } else if (cnt >= 2) {
7464 if (_chk_role_ch_group(&cid_ch[0], &cid_ch[1]))
7465 mode = BTC_WLINK_SCC;
7466 else
7467 mode = BTC_WLINK_SB_MCC;
7468 } else {
7469 mode = _get_role_link_mode(cid_role[0]);
7470 }
7471
7472 wl_rinfo->link_mode = mode;
7473 wl_rinfo->link_mode_hb1 = mode;
7474 }
7475
_sync_wl_link_mode_v0(struct rtw89_dev * rtwdev)7476 static void _sync_wl_link_mode_v0(struct rtw89_dev *rtwdev)
7477 {
7478 struct rtw89_btc_wl_role_info *r = &rtwdev->btc.cx.wl.role_info;
7479 bool has_2g = false;
7480 int i, j;
7481
7482 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER && !has_2g; i++)
7483 for (j = 0; j < RTW89_MAC_NUM && !has_2g; j++)
7484 if (r->rlink[i][j].connected &&
7485 r->rlink[i][j].rf_band == RTW89_BAND_2G)
7486 has_2g = true;
7487
7488 if (!has_2g && r->link_mode != BTC_WLINK_NOLINK) {
7489 r->link_mode_v0 = BTC_WLINK_V0_5G;
7490 return;
7491 }
7492
7493 switch (r->link_mode) {
7494 case BTC_WLINK_NOLINK:
7495 r->link_mode_v0 = BTC_WLINK_V0_NOLINK;
7496 break;
7497 case BTC_WLINK_STA:
7498 r->link_mode_v0 = BTC_WLINK_V0_2G_STA;
7499 break;
7500 case BTC_WLINK_AP:
7501 r->link_mode_v0 = BTC_WLINK_V0_2G_AP;
7502 break;
7503 case BTC_WLINK_GO:
7504 r->link_mode_v0 = BTC_WLINK_V0_2G_GO;
7505 break;
7506 case BTC_WLINK_GC:
7507 r->link_mode_v0 = BTC_WLINK_V0_2G_GC;
7508 break;
7509 case BTC_WLINK_SCC:
7510 r->link_mode_v0 = BTC_WLINK_V0_2G_SCC;
7511 break;
7512 case BTC_WLINK_SB_MCC:
7513 r->link_mode_v0 = BTC_WLINK_V0_2G_MCC;
7514 break;
7515 case BTC_WLINK_DB_MCC:
7516 r->link_mode_v0 = BTC_WLINK_V0_25G_MCC;
7517 break;
7518 default:
7519 r->link_mode_v0 = BTC_WLINK_V0_OTHER;
7520 break;
7521 }
7522 }
7523
_modify_role_link_mode(struct rtw89_dev * rtwdev,u8 hw_band)7524 static void _modify_role_link_mode(struct rtw89_dev *rtwdev, u8 hw_band)
7525 {
7526 struct rtw89_btc *btc = &rtwdev->btc;
7527 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7528 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
7529 u8 go_cleint_exist = wl->go_client_exist;
7530 u8 *link_mode = &wl_rinfo->link_mode;
7531 u32 role_map = wl_rinfo->role_map;
7532 u8 noa_exist = wl->noa_exist;
7533 u32 mrole = BTC_WLMROLE_NONE;
7534
7535 if (hw_band == RTW89_PHY_1) {
7536 *link_mode = wl_rinfo->link_mode_hb1;
7537 role_map = wl_rinfo->role_map_hb1;
7538 go_cleint_exist = wl->go_client_exist_hb1;
7539 }
7540
7541 /* if no client_joined, don't care P2P-GO/AP role */
7542 if (((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
7543 (role_map & BIT(RTW89_WIFI_ROLE_AP))) && !go_cleint_exist) {
7544 if (*link_mode == BTC_WLINK_SCC) {
7545 *link_mode = BTC_WLINK_STA;
7546 } else if (*link_mode == BTC_WLINK_GO ||
7547 *link_mode == BTC_WLINK_AP) {
7548 *link_mode = BTC_WLINK_NOLINK;
7549 }
7550 }
7551
7552 /* Identify 2-Role type */
7553 if (*link_mode == BTC_WLINK_SCC ||
7554 *link_mode == BTC_WLINK_SB_MCC ||
7555 *link_mode == BTC_WLINK_DB_MCC) {
7556 if ((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
7557 (role_map & BIT(RTW89_WIFI_ROLE_AP))) {
7558 if (noa_exist)
7559 mrole = BTC_WLMROLE_STA_GO_NOA;
7560 else
7561 mrole = BTC_WLMROLE_STA_GO;
7562 } else if (role_map & BIT(RTW89_WIFI_ROLE_P2P_CLIENT)) {
7563 if (noa_exist)
7564 mrole = BTC_WLMROLE_STA_GC_NOA;
7565 else
7566 mrole = BTC_WLMROLE_STA_GC;
7567 } else {
7568 mrole = BTC_WLMROLE_STA_STA;
7569 }
7570
7571 if (hw_band == RTW89_PHY_0) {
7572 wl_rinfo->mrole_type &= GENMASK(31, 16); /* clear Low-Word */
7573 wl_rinfo->mrole_type |= mrole;
7574 } else {
7575 wl_rinfo->mrole_type &= GENMASK(15, 0); /* clear high-Word */
7576 wl_rinfo->mrole_type |= (mrole << 16);
7577 }
7578 } else {
7579 wl_rinfo->mrole_type = BTC_WLMROLE_NONE;
7580 }
7581
7582 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7583 "[BTC], %s(): link_mode=%s, mrole_type=%d\n", __func__,
7584 id_to_linkmode(wl_rinfo->link_mode), wl_rinfo->mrole_type);
7585 }
7586
_update_wl_info(struct rtw89_dev * rtwdev,struct rtw89_btc_wl_link_info * wl_linfo)7587 static void _update_wl_info(struct rtw89_dev *rtwdev, struct rtw89_btc_wl_link_info *wl_linfo)
7588 {
7589 struct rtw89_btc *btc = &rtwdev->btc;
7590 struct rtw89_btc_dm *dm = &btc->dm;
7591 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7592 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
7593 struct rtw89_btc_wl_rlink *rlink = NULL;
7594 u8 dbcc_en_ori, is_5g_hi_ch = 0, bg_mode = 0, p2p_exist = 0;
7595 u8 go_client_exist = 0, noa_exist = 0;
7596 u8 rlink_id = wl_linfo->phy;
7597 u8 role_id = wl_linfo->pid;
7598 u8 i, link_mode_ori;
7599 u32 role_map = 0;
7600
7601 if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id >= RTW89_BAND_NUM)
7602 return;
7603
7604 /*
7605 * Extract wl->link_info[role_id][rlink_id] to wl->role_info
7606 * role_id: role index
7607 * rlink_id: rlink index (= HW-band index)
7608 * pid: port_index
7609 */
7610 rlink = &wl_rinfo->rlink[role_id][rlink_id];
7611
7612 rlink->role = wl_linfo->role;
7613 rlink->active = wl_linfo->active; /* Doze or not */
7614 rlink->pid = wl_linfo->pid;
7615 rlink->mac_id = wl_linfo->mac_id;
7616 rlink->phy = wl_linfo->phy;
7617 rlink->rf_band = wl_linfo->chdef.band;
7618 rlink->ch = wl_linfo->chdef.center_ch;
7619 rlink->bw = wl_linfo->chdef.bw;
7620 rlink->noa = wl_linfo->noa;
7621 rlink->noa_dur = wl_linfo->noa_duration / 1000;
7622 rlink->client_cnt = wl_linfo->client_cnt;
7623 rlink->mode = wl_linfo->mode;
7624
7625 /* check if rlink connect? */
7626 switch (wl_linfo->connected) {
7627 case MLME_NO_LINK:
7628 rlink->connected = 0;
7629 break;
7630 case MLME_LINKED:
7631 rlink->connected = 1;
7632
7633 /* reset special-AP flag if station mode linked */
7634 dm->leak_ap = 0;
7635 break;
7636 default:
7637 return;
7638 }
7639
7640 /* update by HW-Band */
7641 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) { /* i = role_id */
7642 rlink = &wl_rinfo->rlink[i][rlink_id];
7643
7644 if (!rlink->active || !rlink->connected)
7645 continue;
7646
7647 role_map |= BIT(rlink->role);
7648
7649 /* Identify if P2P-Go (GO/GC/AP) exist at 2GHz band */
7650 if (((rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
7651 rlink->role == RTW89_WIFI_ROLE_AP) &&
7652 rlink->client_cnt > 1)) {
7653 p2p_exist = 1;
7654 go_client_exist = 1;
7655 }
7656
7657 if (rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)
7658 p2p_exist = 1;
7659
7660 /* only one noa-role exist */
7661 if (rlink->noa && rlink->noa_dur > 0)
7662 noa_exist = 1;
7663
7664 /* for WL 5G-Rx interfered with BT issue */
7665 if (rlink->rf_band == RTW89_BAND_5G && rlink->ch >= 100)
7666 is_5g_hi_ch = 1;
7667
7668 if ((rlink->mode & BIT(BTC_WL_MODE_11B)) ||
7669 (rlink->mode & BIT(BTC_WL_MODE_11G)))
7670 bg_mode = 1;
7671 }
7672
7673 if (rlink_id == RTW89_PHY_0) {
7674 link_mode_ori = wl_rinfo->link_mode;
7675 wl->is_5g_hi_ch = is_5g_hi_ch;
7676 wl->bg_mode = bg_mode;
7677 wl->go_client_exist = go_client_exist;
7678 wl->noa_exist = noa_exist;
7679 wl_rinfo->p2p_exist = p2p_exist;
7680 wl_rinfo->role_map = role_map;
7681 } else {
7682 link_mode_ori = wl_rinfo->link_mode_hb1;
7683 wl->is_5g_hi_ch_hb1 = is_5g_hi_ch;
7684 wl->bg_mode_hb1 = bg_mode;
7685 wl->go_client_exist_hb1 = go_client_exist;
7686 wl->noa_exist_hb1 = noa_exist;
7687 wl_rinfo->p2p_exist_hb1 = p2p_exist;
7688 wl_rinfo->role_map_hb1 = role_map;
7689 }
7690
7691 dbcc_en_ori = wl_rinfo->dbcc_en;
7692
7693 /* for MLO-supported, link-mode from driver directly */
7694 if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) {
7695 _update_wl_mlo_info(rtwdev, rlink_id);
7696 } else { /* for non-MLO-supported, link-mode by BTC */
7697 _update_wl_non_mlo_info(rtwdev);
7698 }
7699
7700 _modify_role_link_mode(rtwdev, rlink_id);
7701 _sync_wl_link_mode_v0(rtwdev);
7702
7703 if ((rlink_id == RTW89_PHY_0 && wl_rinfo->link_mode != link_mode_ori) ||
7704 (rlink_id == RTW89_PHY_1 && wl_rinfo->link_mode_hb1 != link_mode_ori)) {
7705 wl_rinfo->link_mode_chg = 1;
7706 wl->link_mode_chg = 1;
7707 }
7708
7709 if (wl_rinfo->dbcc_en != dbcc_en_ori) {
7710 wl->dbcc_chg = 1;
7711 wl->role_info.dbcc_chg = 1;
7712 wl->wcnt[BTC_WCNT_DBCC_CHG]++;
7713 }
7714 }
7715
rtw89_coex_act1_work(struct wiphy * wiphy,struct wiphy_work * work)7716 void rtw89_coex_act1_work(struct wiphy *wiphy, struct wiphy_work *work)
7717 {
7718 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7719 coex_act1_work.work);
7720 struct rtw89_btc *btc = &rtwdev->btc;
7721 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7722 struct rtw89_btc_cx *cx = &btc->cx;
7723 struct rtw89_btc_wl_info *wl = &cx->wl;
7724
7725 lockdep_assert_wiphy(wiphy);
7726
7727 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7728 dm->cnt_notify[BTC_NCNT_TIMER]++;
7729 if (wl->status.map.handshake ||
7730 wl->status.map._4way ||
7731 wl->status.map.dhcp) {
7732 wl->status.map._4way = 0;
7733 wl->status.map.dhcp = 0;
7734 wl->status.map.handshake = 0;
7735 }
7736 _run_coex(rtwdev, BTC_RSN_ACT1_WORK);
7737 }
7738
rtw89_coex_bt_devinfo_work(struct wiphy * wiphy,struct wiphy_work * work)7739 void rtw89_coex_bt_devinfo_work(struct wiphy *wiphy, struct wiphy_work *work)
7740 {
7741 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7742 coex_bt_devinfo_work.work);
7743 struct rtw89_btc *btc = &rtwdev->btc;
7744 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7745 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc;
7746
7747 lockdep_assert_wiphy(wiphy);
7748
7749 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7750 dm->cnt_notify[BTC_NCNT_TIMER]++;
7751 a2dp->play_latency = 0;
7752 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK);
7753 }
7754
rtw89_coex_rfk_chk_work(struct wiphy * wiphy,struct wiphy_work * work)7755 void rtw89_coex_rfk_chk_work(struct wiphy *wiphy, struct wiphy_work *work)
7756 {
7757 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7758 coex_rfk_chk_work.work);
7759 struct rtw89_btc *btc = &rtwdev->btc;
7760 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7761 struct rtw89_btc_cx *cx = &btc->cx;
7762 struct rtw89_btc_wl_info *wl = &cx->wl;
7763
7764 lockdep_assert_wiphy(wiphy);
7765
7766 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7767 dm->cnt_notify[BTC_NCNT_TIMER]++;
7768 if (wl->rfk_info.state != BTC_WRFK_STOP) {
7769 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7770 "[BTC], %s(): RFK timeout\n", __func__);
7771 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]++;
7772 dm->error.map.wl_rfk_timeout = true;
7773 wl->rfk_info.state = BTC_WRFK_STOP;
7774 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLRFK, false);
7775 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK);
7776 }
7777 }
7778
_update_bt_ctrl_lps(struct rtw89_dev * rtwdev)7779 static void _update_bt_ctrl_lps(struct rtw89_dev *rtwdev)
7780 {
7781 struct rtw89_btc *btc = &rtwdev->btc;
7782 struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0;
7783 struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1;
7784 struct rtw89_btc_dm *dm = &btc->dm;
7785 bool lps_ctrl = false;
7786
7787 if (dm->out_of_band || dm->freerun)
7788 lps_ctrl = false;
7789 else if (bt0->whql_test || bt1->whql_test)
7790 lps_ctrl = true;
7791 else if (bt0->link_info.a2dp_desc.exist ||
7792 bt0->link_info.hfp_desc.exist ||
7793 bt0->link_info.pan_desc.exist)
7794 lps_ctrl = true;
7795 else if (bt1->link_info.a2dp_desc.exist ||
7796 bt1->link_info.hfp_desc.exist ||
7797 bt1->link_info.pan_desc.exist)
7798 lps_ctrl = true;
7799
7800 if (dm->lps_ctrl_scbd != lps_ctrl) {
7801 dm->lps_ctrl_scbd = lps_ctrl;
7802 dm->lps_ctrl_change = true;
7803 } else {
7804 dm->lps_ctrl_change = false;
7805 }
7806 }
7807
_update_bt_scbd(struct rtw89_dev * rtwdev,u8 bid)7808 static void _update_bt_scbd(struct rtw89_dev *rtwdev, u8 bid)
7809 {
7810 struct rtw89_btc_bt_link_info *bt_2g, *bt_56g;
7811 struct rtw89_btc *btc = &rtwdev->btc;
7812 struct rtw89_btc_cx *cx = &btc->cx;
7813 struct rtw89_btc_dm *dm = &btc->dm;
7814 struct rtw89_btc_bt_info *bt;
7815 u32 val, any_bt_connect, any_bt_6g_connect = 0;
7816 bool bt_link_change = false;
7817 u8 id, id_start, id_stop;
7818
7819 if (!rtwdev->chip->scbd || bid > BTC_ALL_BT)
7820 return;
7821
7822 if (bid == BTC_ALL_BT) {
7823 id_start = BTC_BT_1ST;
7824 id_stop = BTC_BT_2ND;
7825 } else {
7826 id_start = bid;
7827 id_stop = bid;
7828 }
7829
7830 dm->lps_ctrl_change = false;
7831 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s()\n", __func__);
7832
7833 for (id = id_start; id <= id_stop; id++) {
7834 bt = (id == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1;
7835 bt_2g = &bt->link_info;
7836 bt_56g = &bt->link_info_56g;
7837
7838 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) && id == BTC_BT_2ND)
7839 break;
7840
7841 val = bt->scbd_c2h;
7842
7843 if (val == 0xffffffff) {
7844 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7845 "[BTC], %s return by invalid scbd value\n",
7846 __func__);
7847 return;
7848 }
7849
7850 if (!(val & BTC_BSCB_ON))
7851 bt->enable.now = 0;
7852 else
7853 bt->enable.now = 1;
7854
7855 if (bt->enable.now != bt->enable.last)
7856 bt_link_change = true;
7857
7858 /* reset bt info if bt re-enable */
7859 if (bt->enable.now && !bt->enable.last) {
7860 if (id == BTC_BT_1ST)
7861 _reset_btc_var(rtwdev, BTC_RESET_BTINFO);
7862 else
7863 _reset_btc_var(rtwdev, BTC_RESET_BTINFO2);
7864
7865 bt->bcnt[BTC_BCNT_REENABLE]++;
7866 bt->enable.now = 1;
7867 bt->rf_band_map = BIT(RTW89_BAND_2G);
7868 bt->link_weight[BTC_BT_B2G] = 5; /* no-profile */
7869 }
7870 bt->enable.last = bt->enable.now;
7871
7872 /* if BT will disconnect and adopt protect plan */
7873 if ((val & BTC_BSCB_BT_PROTECT) &&
7874 !(bt->scbd & BTC_BSCB_BT_PROTECT))
7875 bt->bcnt[BTC_BCNT_PROTECT]++;
7876
7877 bt->mbx_avl = !!(val & BTC_BSCB_ACT);
7878 if (bt->whql_test != !!(val & BTC_BSCB_WHQL))
7879 bt_link_change = true;
7880
7881 bt->whql_test = !!(val & BTC_BSCB_WHQL);
7882 bt->btg_type = (val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE);
7883
7884 bt_2g->a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT);
7885 bt_2g->pan_desc.exist = !!(val & BTC_BSCB_PAN_ACT);
7886 bt_2g->hfp_desc.exist = !!(val & BTC_BSCB_HFP_ACT);
7887
7888 bt->lna_constrain = 4 + !!(val & BTC_BSCB_BT_LNAB0) +
7889 !!(val & BTC_BSCB_BT_LNAB1) * 2;
7890
7891 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) {
7892 if (val & BTC_BSCB_BT_15DOT4)
7893 bt->func_type |= (BTC_BTF_THREAD | BTC_BTF_ZB);
7894 else
7895 bt->func_type &= ~(BTC_BTF_THREAD | BTC_BTF_ZB);
7896 }
7897
7898 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
7899 any_bt_connect = !!(val & BTC_BSCB_BT_CONNECT);
7900
7901 /* if connect change */
7902 if (bt_2g->status.map.connect != any_bt_connect ||
7903 bt_56g->status.map.connect != any_bt_6g_connect) {
7904 bt_link_change = true;
7905 bt_2g->status.map.connect = any_bt_connect;
7906 bt_56g->status.map.connect = any_bt_6g_connect;
7907 }
7908
7909 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
7910 bt->scbd = val;
7911 }
7912
7913 _update_bt_ctrl_lps(rtwdev);
7914
7915 if (bt_link_change) {
7916 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7917 "[BTC], %s: bt status change!!\n", __func__);
7918 /* TODO: Need to notify driver to update EXT-CTRL-BT-SLOT */
7919 }
7920 }
7921
_update_bt_link_cnt(struct rtw89_dev * rtwdev,struct rtw89_btc_bt_info * bt,bool b56g)7922 static void _update_bt_link_cnt(struct rtw89_dev *rtwdev,
7923 struct rtw89_btc_bt_info *bt, bool b56g)
7924 {
7925 struct rtw89_btc_bt_link_info *b = b56g ? &bt->link_info_56g :
7926 &bt->link_info;
7927 struct rtw89_btc_bt_leaudio_desc *leaudio = &b->leaudio_desc;
7928 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
7929 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
7930 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
7931 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc;
7932 u8 bt_rf_band = b56g ? BTC_BT_B5G : BTC_BT_B2G;
7933 u8 val;
7934
7935 b->link_cnt.last = b->link_cnt.now;
7936 b->link_cnt.now = 0;
7937 b->link_cnt.chg = 0;
7938
7939 b->link_cnt.now += hfp->exist;
7940 b->link_cnt.now += hid->exist;
7941 b->link_cnt.now += a2dp->exist;
7942 b->link_cnt.now += pan->exist;
7943 b->link_cnt.now += leaudio->bis_exist;
7944 b->link_cnt.now += leaudio->cis_exist;
7945
7946 if (leaudio->bis_exist || a2dp->sink) {
7947 val = 70;
7948 } else if (a2dp->exist) {
7949 val = 40;
7950 if (a2dp->vendor_id == 0x4c)
7951 val += 10;
7952 if (hid->exist)
7953 val += 10;
7954 } else if (pan->exist || pan->active || a2dp->active ||
7955 b->status.map.inq_pag) {
7956 val = 30;
7957 } else if (b->link_cnt.now == 0) {
7958 val = 5;
7959 } else {
7960 val = 9;
7961 }
7962 bt->link_weight[bt_rf_band] = val;
7963
7964 if (b->link_cnt.last != b->link_cnt.now)
7965 b->link_cnt.chg = 1;
7966 }
7967
_update_bt_leaudio_info(struct rtw89_dev * rtwdev,u8 bid,void * buf,u32 len)7968 static void _update_bt_leaudio_info(struct rtw89_dev *rtwdev, u8 bid,
7969 void *buf, u32 len)
7970 {
7971 const struct rtw89_chip_info *chip = rtwdev->chip;
7972 struct rtw89_btc *btc = &rtwdev->btc;
7973 struct rtw89_btc_cx *cx = &btc->cx;
7974 struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1;
7975 struct rtw89_btc_bt_link_info *b = &bt->link_info;
7976 struct rtw89_btc_bt_leaudio_info *src = buf;
7977 struct rtw89_btc_bt_leaudio_desc *leaudio;
7978 bool bt_56g = false, cis_exist, bis_exist;
7979 u8 bis_cnt, cis_cnt;
7980
7981 if ((src->len & BIT(7)) && bt->band_56G_support) {
7982 b = &bt->link_info_56g;
7983 bt_56g = true;
7984 }
7985
7986 leaudio = &b->leaudio_desc;
7987
7988 if (!memcmp(b->leaudio_raw_info, src, BTC_BTINFO_MAX)) {
7989 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7990 "[BTC], %s return by leaudio-info duplicate!\n",
7991 __func__);
7992 bt->bcnt[BTC_BCNT_LEAUDIO_INFOSAME]++;
7993 return;
7994 }
7995
7996 memcpy(b->leaudio_raw_info, src, BTC_BTINFO_MAX);
7997
7998 bis_exist = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_BIS_EX);
7999 cis_exist = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_CIS_EX);
8000 bis_cnt = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_BIS_CNT);
8001 cis_cnt = u8_get_bits(src->bis_cis, RTW89_BTC_LEAU_INFO_L2_CIS_CNT);
8002
8003 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8004 "[BTC], %s: bis_exist:%d bis_cnt:%d cis_exist:%d cis_cnt:%d rssi:%d\n",
8005 __func__, bis_exist, bis_cnt, cis_exist, cis_cnt, src->rssi);
8006
8007 if (!bis_exist && !cis_exist)
8008 memset(leaudio, 0, sizeof(*leaudio));
8009
8010 leaudio->bis_cnt = bis_cnt;
8011 leaudio->bis_exist = bis_exist;
8012 leaudio->cis_cnt = cis_cnt;
8013 leaudio->cis_exist = cis_exist;
8014
8015 if (leaudio->bis_exist)
8016 b->status.map.profile_map |= BTC_BT_BIS;
8017 else
8018 b->status.map.profile_map &= ~BTC_BT_BIS;
8019
8020 if (leaudio->cis_exist)
8021 b->status.map.profile_map |= BTC_BT_CIS;
8022 else
8023 b->status.map.profile_map &= ~BTC_BT_CIS;
8024
8025 _update_bt_link_cnt(rtwdev, bt, bt_56g);
8026
8027 leaudio->rssi = chip->ops->btc_get_bt_rssi(rtwdev, src->rssi);
8028
8029 leaudio->bis_cnt_last = leaudio->bis_cnt;
8030 leaudio->bis_exist_last = leaudio->bis_exist;
8031 leaudio->cis_cnt_last = leaudio->cis_cnt;
8032 leaudio->cis_exist_last = leaudio->cis_exist;
8033 }
8034
_update_bt_bistdma_info(struct rtw89_dev * rtwdev,u8 bid,void * buf,u32 len)8035 static void _update_bt_bistdma_info(struct rtw89_dev *rtwdev, u8 bid,
8036 void *buf, u32 len)
8037 {
8038 struct rtw89_btc *btc = &rtwdev->btc;
8039 struct rtw89_btc_cx *cx = &btc->cx;
8040 struct rtw89_btc_dm *dm = &btc->dm;
8041 struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1;
8042 struct rtw89_btc_bt_link_info *b = &bt->link_info;
8043 struct rtw89_btc_bt_bistdma_info_le *src = buf;
8044 struct rtw89_btc_bt_leaudio_desc *leaudio;
8045
8046 if ((src->len & BIT(7)) && bt->band_56G_support)
8047 b = &bt->link_info_56g;
8048
8049 leaudio = &b->leaudio_desc;
8050
8051 if (!memcmp(b->bistdma_raw_info, src, BTC_BTINFO_MAX)) {
8052 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8053 "[BTC], %s return by bistdma-info duplicate!\n",
8054 __func__);
8055 bt->bcnt[BTC_BCNT_LEAUDIO_INFOSAME]++;
8056 return;
8057 }
8058
8059 memcpy(b->bistdma_raw_info, src, BTC_BTINFO_MAX);
8060
8061 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8062 "[BTC], %s: bis_start_end:%d bis_trx:%d\n",
8063 __func__,
8064 u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_START_END),
8065 u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_TRX));
8066
8067 leaudio->bis_trx = u8_get_bits(src->bis, RTW89_BTC_BIS_INFO_L2_TRX);
8068 leaudio->bis_start_end = u8_get_bits(src->bis,
8069 RTW89_BTC_BIS_INFO_L2_START_END);
8070
8071 leaudio->diff_t = (src->diff_t_hb * 256 + src->diff_t_lb) * 625 / 1000;
8072
8073 if (btc->ant_type == BTC_ANT_SHARED && leaudio->diff_t > 13)
8074 dm->bis_tdma = true;
8075 else
8076 dm->bis_tdma = false;
8077 }
8078
8079 #define BTC_BTINFO_PWR_LEN 5
_update_bt_txpwr_info(struct rtw89_dev * rtwdev,u8 * buf,u32 len)8080 static void _update_bt_txpwr_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
8081 {
8082 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt0;
8083 struct rtw89_btc_bt_link_info *b = &bt->link_info;
8084
8085 if (len != BTC_BTINFO_PWR_LEN)
8086 return;
8087
8088 if (!memcmp(bt->txpwr_info, buf, sizeof(bt->txpwr_info))) {
8089 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8090 "[BTC], %s return by info duplicate!\n", __func__);
8091 return;
8092 }
8093
8094 memcpy(bt->txpwr_info, buf, BTC_BTINFO_MAX);
8095 memcpy(&b->bt_txpwr_desc, &buf[2], sizeof(b->bt_txpwr_desc));
8096 }
8097
_set_bind_info(struct rtw89_btc * btc,u8 type)8098 static void _set_bind_info(struct rtw89_btc *btc, u8 type)
8099 {
8100 struct rtw89_btc_cx *cx = &btc->cx;
8101 struct rtw89_btc_dm *dm = &btc->dm;
8102 struct rtw89_btc_wl_info *wl = &cx->wl;
8103 struct rtw89_btc_bt_info *bt = &cx->bt0;
8104 struct rtw89_btc_bt_link_info *b;
8105 struct rtw89_btc_bind_info *bd;
8106 u8 path_hwb[BTC_RF_NUM] = {RTW89_PHY_0, RTW89_PHY_1};
8107 u8 link_weight[BTC_ALL_BT_EZL][BTC_BT_BMAX];
8108 u8 map[BTC_RF_NUM][BTC_ALL_BT_EZL];
8109 u8 b2g_score = 0, b5g_score = 0;
8110 u8 i, j, rf_band_map, thres;
8111 u8 weight[BTC_BT_BMAX] = {};
8112
8113 if (type == BTC_MECH_TDD) {
8114 bd = &dm->tdd_bind;
8115 memcpy(map, dm->tdd_map, sizeof(map));
8116 thres = 30; /* BT profile score threshold for TDMA */
8117 } else {
8118 bd = &dm->fdd_bind;
8119 memcpy(map, dm->fdd_map, sizeof(map));
8120 thres = 5;
8121 }
8122
8123 memset(bd, 0, sizeof(*bd));
8124 /* compare BT 2GHz/5GHz profile by link-weighting */
8125 for (i = 0; i < BTC_BT_BMAX; i++) {
8126 if (!cx->bt0.enable.now)
8127 cx->bt0.link_weight[i] = 0;
8128 if (!cx->bt1.enable.now)
8129 cx->bt1.link_weight[i] = 0;
8130 link_weight[BTC_BT_1ST][i] = cx->bt0.link_weight[i];
8131 link_weight[BTC_BT_2ND][i] = cx->bt1.link_weight[i];
8132 link_weight[BTC_BT_EXT][i] = cx->bt_ext.link_weight[i];
8133 }
8134
8135 /*
8136 * get 2GHz/5GHz link weight score by "band-overlap" map
8137 * link_weight from _update_bt_link_cnt(),
8138 * if link_weight >30 --> TDMA-required
8139 */
8140 for (j = 0; j < BTC_ALL_BT_EZL; j++) {
8141 rf_band_map = map[BTC_RF_S0][j] | map[BTC_RF_S1][j];
8142 if (rf_band_map & BIT(RTW89_BAND_2G))
8143 b2g_score += link_weight[j][BTC_BT_B2G];
8144 if (rf_band_map & BIT(RTW89_BAND_5G))
8145 b5g_score += link_weight[j][BTC_BT_B5G];
8146 }
8147
8148 /* rf-band bound by comparing link weight */
8149 if (b2g_score == 0 && b5g_score == 0) /* no-rf-band overlap */
8150 bd->rf_band = 0;
8151 else if (b5g_score > b2g_score)
8152 bd->rf_band = BIT(BTC_BT_B5G);
8153 else
8154 bd->rf_band = BIT(BTC_BT_B2G);
8155
8156 /*
8157 * if MR_WTYPE_MLD2L1R_NONMLD, FW will change 2+0/0+2/1+1
8158 * Therefore, BTC_MLO_RF_xxx is not real-time state.
8159 * In this case, RF_S0->HWB0, RF_S1->HWB1
8160 * If link-mode change by _ntfy_generic(BTC_GNTFY_MRCX_INFO)
8161 * HW-Band is decided by wl->mlo_info.mrcx_act_hwb_map
8162 */
8163 if (wl->mlo_info.wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD) {
8164 if (wl->role_info.link_mode != BTC_WLINK_DB_MCC) { /* mode chg */
8165 if (wl->mlo_info.mrcx_act_hwb_map == BIT(RTW89_MAC_1))
8166 path_hwb[BTC_RF_S0] = RTW89_PHY_1; /* S0/1->HWB1 */
8167 else
8168 path_hwb[BTC_RF_S1] = RTW89_PHY_0; /* S0/1->HWB0 */
8169 }
8170 } else {
8171 /*
8172 * Dual-RF_band(HWB)TDMA if BT-profile is TDMA-type at both
8173 * 2GHz and 5GHz.
8174 * ex: 1+1: HWB0 5GHz + BT0 5GHz (BIS, HDT)
8175 * && HWB1 2.4GHz + BT1 2.4GHz(PAN)
8176 * for TDD: the link score must > 30 (from _bt_link_cnt)
8177 * for FDD: the link score must > 5 (bt enable)
8178 */
8179 if ((wl->mlo_info.rf_combination == BTC_MLO_RF_1_PLUS_1 ||
8180 wl->mlo_info.rf_combination == BTC_MLO_RF_2_PLUS_2) &&
8181 (b2g_score >= thres && b5g_score >= thres)) {
8182 bd->rf_band = BIT(BTC_BT_B2G) | BIT(BTC_BT_B5G);
8183 }
8184
8185 if (wl->mlo_info.rf_combination == BTC_MLO_RF_2_PLUS_0)
8186 path_hwb[BTC_RF_S1] = RTW89_PHY_0; /* 2+0 RF-S0/1->HWB0 */
8187 else if (wl->mlo_info.rf_combination == BTC_MLO_RF_0_PLUS_2)
8188 path_hwb[BTC_RF_S0] = RTW89_PHY_1; /* 2+0 RF-S0/1->HWB1 */
8189 }
8190
8191 /* Get HWB-sel and BT-sel by rf-band-binding */
8192 for (i = 0; i < BTC_RF_NUM; i++) {
8193 for (j = 0; j < BTC_ALL_BT_EZL; j++) {
8194 if (!(map[i][j] & bd->rf_band)) /* no-overlap */
8195 continue;
8196
8197 bd->wl_hwb_sel |= BIT(path_hwb[i]);
8198 bd->bt_sel |= BIT(j);
8199 }
8200 }
8201
8202 if (wl->mlo_info.wtype == RTW89_MR_WTYPE_MLD2L2R &&
8203 (bd->wl_hwb_sel == (BIT(RTW89_MAC_1) | BIT(RTW89_MAC_0)))) {
8204 if (wl->role_info.link_mode == BTC_WLINK_AP ||
8205 wl->role_info.link_mode_hb1 == BTC_WLINK_AP)
8206 bd->wl_link_mode = BTC_WLINK_DB_MCC;
8207 else
8208 bd->wl_link_mode = BTC_WLINK_STA;
8209 bd->wl_bg_mode = wl->bg_mode | wl->bg_mode_hb1;
8210 } else if (bd->wl_hwb_sel == (BIT(RTW89_MAC_1))) {
8211 bd->wl_link_mode = wl->role_info.link_mode_hb1;
8212 bd->wl_bg_mode = wl->bg_mode_hb1;
8213 } else {/* HW-BAND-0 or no-hw-band */
8214 bd->wl_hwb_sel = BIT(RTW89_MAC_0);
8215 bd->wl_link_mode = wl->role_info.link_mode;
8216 bd->wl_bg_mode = wl->bg_mode;
8217 }
8218
8219 /* update Bind-BT status map for BT0/BT1 */
8220 for (i = BTC_BT_1ST; i < BTC_ALL_BT_EZL; i++) {
8221 if (!(bd->bt_sel & BIT(i)))
8222 continue;
8223
8224 for (j = BTC_BT_B2G; j <= BTC_BT_B5G; j++) {
8225 if (!(bd->rf_band & BIT(j)))
8226 continue;
8227
8228 if (i == BTC_BT_EXT) {
8229 bd->bt_profile |= cx->bt_ext.profile_map[j];
8230 weight[j] = cx->bt_ext.link_weight[j];
8231 if (weight[j] > bd->bt_link_weight) /* max */
8232 bd->bt_link_weight = weight[j];
8233 continue;
8234 } else if (i == BTC_BT_1ST) {
8235 bt = &cx->bt0;
8236 } else {
8237 bt = &cx->bt1;
8238 }
8239
8240 if (j == BTC_BT_B2G)
8241 b = &bt->link_info;
8242 else
8243 b = &bt->link_info_56g;
8244
8245 bd->bt_profile |= b->status.map.profile_map;
8246 bd->bt_smap.a2dp_active |= b->a2dp_desc.active;
8247 bd->bt_smap.a2dp_sink |= b->a2dp_desc.sink;
8248 bd->bt_smap.pan_active |= b->pan_desc.active;
8249 bd->bt_smap.connect |= b->status.map.connect;
8250 bd->bt_smap.hid_cnt += b->hid_desc.pair_cnt;
8251 bd->bt_smap.hid_type |= b->hid_desc.type;
8252 bd->bt_smap.cis_cnt += b->leaudio_desc.cis_cnt;
8253 bd->bt_smap.link_cnt += b->link_cnt.now;
8254 bd->bt_smap.inq_page |= b->status.map.inq_pag;
8255 bd->bt_smap.page |= b->pag;
8256
8257 if (bt->link_weight[j] > bd->bt_link_weight) /* max */
8258 bd->bt_link_weight = bt->link_weight[j];
8259
8260 if (b->slave_role)
8261 bd->bt_smap.slave_role = b->slave_role;
8262
8263 if (b->a2dp_desc.vendor_id != 0)
8264 bd->bt_smap.a2dp_vendor_id =
8265 b->a2dp_desc.vendor_id;
8266 }
8267 }
8268
8269 if (bd->bt_profile & BTC_BT_HFP)
8270 bd->bt_smap.hfp_exist = 1;
8271 if (bd->bt_profile & BTC_BT_HID)
8272 bd->bt_smap.hid_exist = 1;
8273 if (bd->bt_profile & BTC_BT_A2DP)
8274 bd->bt_smap.a2dp_exist = 1;
8275 if (bd->bt_profile & BTC_BT_PAN)
8276 bd->bt_smap.pan_exist = 1;
8277 if (bd->bt_profile & BTC_BT_BIS)
8278 bd->bt_smap.bis_exist = 1;
8279 if (bd->bt_profile & BTC_BT_CIS)
8280 bd->bt_smap.cis_exist = 1;
8281 if (bd->bt_profile & BTC_BT_THREAD)
8282 bd->bt_smap.thread_exist = 1;
8283 if (bd->bt_profile & BTC_BT_ULL)
8284 bd->bt_smap.ull_exist = 1;
8285 }
8286
8287 #define _bind_is_btonly 0x7
_set_coex_binding(struct rtw89_btc * btc)8288 static void _set_coex_binding(struct rtw89_btc *btc)
8289 {
8290 struct rtw89_btc_cx *cx = &btc->cx;
8291 struct rtw89_btc_extsoc_info *bt2 = &cx->bt_ext;
8292 struct rtw89_btc_bt_info *bt0 = &cx->bt0;
8293 struct rtw89_btc_bt_info *bt1 = &cx->bt1;
8294 struct rtw89_btc_wl_info *wl = &cx->wl;
8295 struct rtw89_btc_dm *dm = &btc->dm;
8296 u8 path_hwb[BTC_RF_NUM] = {RTW89_PHY_0, RTW89_PHY_1};
8297 u8 wl_rf_band[RTW89_BAND_NUM] = {};
8298 u8 i, j, val = 0;
8299
8300 /*
8301 * sit_xmap(Space-Interaction) = ant_xmap | xtk_xmap
8302 * 1: WL-BT space-interference, always 1 if BTG/BTA/SPDT = 1
8303 * if dedicated-ant, it may be 1 if BT-Tx is bigger than WL-Rx(xtk_xmap)
8304 *
8305 * ant_xmap(ANT-Division-Multiplexing)
8306 * ==> dedicated-ant->0, BTG/BTA/SPDT->1
8307 *
8308 * xtk_xmap(Cross-talk map)-> calculate WL/BT interference by SIR
8309 * ==> 1: interference, 0: no-interference
8310 *
8311 * fdm_map(Frequency-Division-Multiplexing): WL/BT RF_Band overlap-map
8312 * 2bit-map: bit[1]:5/6GHz, bit[0]:2.4GHz
8313 */
8314 for (i = 0; i < RTW89_PHY_NUM; i++) {
8315 if (wl->rf_band_map[i] & BIT(RTW89_BAND_2G))
8316 wl_rf_band[i] |= BIT(RTW89_BAND_2G);
8317
8318 if (wl->rf_band_map[i] & (BIT(RTW89_BAND_5G) | BIT(RTW89_BAND_6G)))
8319 wl_rf_band[i] |= BIT(RTW89_BAND_5G);
8320
8321 dm->fit_xmap[i][BTC_BT_1ST] = wl_rf_band[i] & bt0->rf_band_map;
8322 dm->fit_xmap[i][BTC_BT_2ND] = wl_rf_band[i] & bt1->rf_band_map;
8323 dm->fit_xmap[i][BTC_BT_EXT] = wl_rf_band[i] & bt2->rf_band_map;
8324 }
8325
8326 /*
8327 * if MR_WTYPE_MLD2L1R_NONMLD, FW will change 2+0/0+2/1+1
8328 * Therefore, BTC_MLO_RF_xxx is not real-time state.
8329 * if link mode change by _ntfy_generic(BTC_GNTFY_MRCX_INFO)
8330 * the HW-BAND is decided by wl->mlo_info.mrcx_act_hwb_map
8331 * In this case, BTC_RF_S0->HWB0, BTC_RF_S1->HWB1
8332 */
8333 if (wl->mlo_info.wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD) {
8334 if (wl->role_info.link_mode != BTC_WLINK_DB_MCC) {/* mode chg */
8335 if (wl->mlo_info.mrcx_act_hwb_map == BIT(RTW89_PHY_1))
8336 path_hwb[BTC_RF_S0] = RTW89_PHY_1;/* S0/1->HWB1 */
8337 else
8338 path_hwb[BTC_RF_S1] = RTW89_PHY_0;/* S0/1->HWB0 */
8339 }
8340 } else {
8341 if (wl->mlo_info.rf_combination == BTC_MLO_RF_2_PLUS_0)
8342 path_hwb[BTC_RF_S1] = RTW89_PHY_0; /* 2+0 RF-S0/1->HWB0 */
8343 else if (wl->mlo_info.rf_combination == BTC_MLO_RF_0_PLUS_2)
8344 path_hwb[BTC_RF_S0] = RTW89_PHY_1; /* 2+0 RF-S0/1->HWB1 */
8345 }
8346
8347 /*
8348 * tdd_map = sit_xmap * fdm_map, 1: WL-RF-Sx vs. BTx take TDD-Action
8349 * fdd_map =(!sit_xmap) * fdm_map, 1: WL-RF-Sx vs.BTx take FDD-Action
8350 * co-rx map = ant_xmap * fdm_map 1:WL/BT co-rx (for halbb-btg-ctrl)
8351 * sit_xmap,ant_xmap = 0 or 1, so tdd/fdd use multiplication (*)
8352 */
8353
8354 for (i = 0; i < BTC_RF_NUM; i++)
8355 for (j = 0; j < BTC_ALL_BT_EZL; j++) {
8356 dm->tdd_map[i][j] = dm->sit_xmap[i][j] *
8357 dm->fit_xmap[path_hwb[i]][j];
8358 dm->fdd_map[i][j] = !dm->sit_xmap[i][j] *
8359 dm->fit_xmap[path_hwb[i]][j];
8360 dm->corx_map[i][j] = dm->ant_xmap[i][j] *
8361 dm->fit_xmap[path_hwb[i]][j];
8362 }
8363
8364 /* TDD-Binding */
8365 _set_bind_info(btc, BTC_MECH_TDD);
8366
8367 /* FDD-Binding */
8368 _set_bind_info(btc, BTC_MECH_FDD);
8369
8370 dm->out_of_band = !dm->tdd_bind.rf_band && !dm->fdd_bind.rf_band;
8371 dm->fdd_en = !!dm->fdd_bind.rf_band;
8372 dm->tdd_en = !!dm->tdd_bind.rf_band;
8373
8374 /* set BT on/off state for GNT_WL Combined-MUX control */
8375 if (bt0->enable.now)
8376 val |= BIT(0);
8377
8378 if (bt1->enable.now)
8379 val |= BIT(1);
8380
8381 if (bt2->func_type)
8382 val |= BIT(2);
8383
8384 dm->ost_info.bt_enable_state = dm->bt_only ? _bind_is_btonly : val;
8385 }
8386
_update_run_ctrl_info(struct rtw89_dev * rtwdev)8387 static void _update_run_ctrl_info(struct rtw89_dev *rtwdev)
8388 {
8389 struct rtw89_btc *btc = &rtwdev->btc;
8390 struct rtw89_btc_dm *dm = &btc->dm;
8391 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8392 struct rtw89_btc_ctrl ctrl = btc->ctrl;
8393 struct rtw89_fbtc_wl_ctrl_info *wl_ctrl_info = &ctrl.wl_ctrl_info;
8394 u8 i;
8395
8396 ctrl.wl_only = dm->wl_only;
8397 ctrl.bt_only = dm->bt_only;
8398 ctrl.ntfy_type = dm->run_reason;
8399
8400 wl_ctrl_info->smap_val = wl->status.val;
8401 wl_ctrl_info->rfk_state = wl->rfk_info.state;
8402 wl_ctrl_info->rfk_type = wl->rfk_info.type;
8403 wl_ctrl_info->client_pstdma_on = dm->client_ps_tdma_on;
8404 wl_ctrl_info->fw_scan = wl->scan_info.fw_scan;
8405
8406 for (i = RTW89_MAC_0; i <= RTW89_MAC_1; i++) {
8407 wl_ctrl_info->rf_band_map[i] = wl->rf_band_map[i];
8408 wl_ctrl_info->rf_ch[i] = wl->rf_ch_info[i].center_ch;
8409 }
8410
8411 if (!memcmp(&btc->ctrl, &ctrl, sizeof(struct rtw89_btc_ctrl))) {
8412 memcpy(&btc->ctrl, &ctrl, sizeof(struct rtw89_btc_ctrl));
8413 if (btc->ver->fcxctrl >= 9)
8414 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
8415 }
8416 }
8417
8418 static
_run_coex(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason)8419 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
8420 {
8421 struct rtw89_btc *btc = &rtwdev->btc;
8422 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
8423 struct rtw89_btc_cx *cx = &btc->cx;
8424 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8425 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
8426 u8 mode = btc->dm.tdd_bind.wl_link_mode;
8427 u8 mode_v0 = BTC_WLINK_V0_OTHER;
8428 bool has_2ghz;
8429
8430 lockdep_assert_wiphy(rtwdev->hw->wiphy);
8431
8432 dm->run_reason = reason;
8433 _update_dm_step(rtwdev, reason);
8434
8435 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
8436 __func__, reason, mode);
8437 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
8438 __func__, dm->wl_only, dm->bt_only);
8439
8440 /* Be careful to change the following function sequence!! */
8441 if (btc->manual_ctrl) {
8442 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8443 "[BTC], %s(): return for Manual CTRL!!\n",
8444 __func__);
8445 return;
8446 }
8447
8448 if (!wl->status.map.init_ok) {
8449 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8450 "[BTC], %s(): return for WL init fail!!\n",
8451 __func__);
8452 return;
8453 }
8454
8455 if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
8456 wl->status.map.lps_pre == wl->status.map.lps &&
8457 !dm->lps_ctrl_change && !dm->lps_ctrl_scbd) {
8458 if (reason == BTC_RSN_NTFY_POWEROFF ||
8459 reason == BTC_RSN_NTFY_RADIO_STATE) {
8460 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8461 "[BTC], %s(): return for WL rf off state no change!!\n",
8462 __func__);
8463 return;
8464 }
8465 if (wl->status.map.rf_off == 1 ||
8466 wl->status.map.lps == BTC_LPS_RF_OFF) {
8467 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8468 "[BTC], %s(): return for WL rf off state!!\n",
8469 __func__);
8470 return;
8471 }
8472 }
8473
8474 _update_run_ctrl_info(rtwdev);
8475
8476 if (reason == BTC_RSN_NTFY_INIT || reason == BTC_RSN_NTFY_RADIO_STATE)
8477 _update_bt_scbd(rtwdev, false);
8478
8479 dm->freerun = false;
8480 dm->cnt_dm[BTC_DCNT_RUN]++;
8481 dm->fddt_train = BTC_FDDT_DISABLE;
8482 bt->scan_rx_low_pri = false;
8483
8484 _set_coex_binding(btc);
8485 _update_btc_state_map(rtwdev);
8486
8487 dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */
8488
8489 if (btc->ctrl.always_freerun) {
8490 _action_freerun(rtwdev);
8491 goto exit;
8492 }
8493
8494 if (dm->wl_only) {
8495 _action_wl_only(rtwdev);
8496 goto exit;
8497 }
8498
8499 if (wl->status.map.rf_off || dm->bt_only || wl->status.map.lps) {
8500 _action_wl_off(rtwdev, mode);
8501 goto exit;
8502 }
8503
8504 if (reason == BTC_RSN_NTFY_INIT) {
8505 _action_wl_init(rtwdev);
8506 goto exit;
8507 }
8508
8509 if (!cx->bt0.enable.now && !cx->bt_ext.func_type) {
8510 _action_bt_off(rtwdev);
8511 goto exit;
8512 }
8513
8514 if (cx->bt0.whql_test) {
8515 _action_bt_whql(rtwdev);
8516 goto exit;
8517 }
8518
8519 if (wl->rfk_info.state != BTC_WRFK_STOP) {
8520 _action_wl_rfk(rtwdev);
8521 goto exit;
8522 }
8523
8524 if (wl->status.val & btc_scanning_map.val && !wl->rfk_info.con_rfk) {
8525 _action_wl_scan(rtwdev);
8526 bt->scan_rx_low_pri = true;
8527 goto exit;
8528 }
8529
8530 if (mode == BTC_WLINK_NOLINK) {
8531 mode_v0 = BTC_WLINK_V0_NOLINK;
8532 } else if (btc->dm.tdd_bind.rf_band == BIT(RTW89_BAND_5G)) {
8533 mode_v0 = BTC_WLINK_V0_5G;
8534 } else if (btc->dm.tdd_bind.rf_band & BIT(RTW89_BAND_5G) &&
8535 btc->dm.tdd_bind.rf_band & BIT(RTW89_BAND_2G)) {
8536 mode_v0 = BTC_WLINK_V0_25G_MCC;
8537 } else if (btc->dm.tdd_bind.rf_band == BIT(RTW89_BAND_2G)) {
8538 switch (mode) {
8539 case BTC_WLINK_STA:
8540 mode_v0 = BTC_WLINK_V0_2G_STA;
8541 break;
8542 case BTC_WLINK_AP:
8543 mode_v0 = BTC_WLINK_V0_2G_AP;
8544 break;
8545 case BTC_WLINK_GO:
8546 mode_v0 = BTC_WLINK_V0_2G_GO;
8547 break;
8548 case BTC_WLINK_GC:
8549 mode_v0 = BTC_WLINK_V0_2G_GC;
8550 break;
8551 case BTC_WLINK_SCC:
8552 mode_v0 = BTC_WLINK_V0_2G_SCC;
8553 break;
8554 case BTC_WLINK_SB_MCC:
8555 mode_v0 = BTC_WLINK_V0_2G_MCC;
8556 break;
8557 default:
8558 mode_v0 = BTC_WLINK_V0_OTHER;
8559 break;
8560 }
8561 } else {
8562 /* No binding (out_of_band): derive mode_v0 from link_mode + rf_band_map */
8563 has_2ghz = wl->rf_band_map[RTW89_MAC_0] & BIT(RTW89_BAND_2G) ||
8564 wl->rf_band_map[RTW89_MAC_1] & BIT(RTW89_BAND_2G);
8565
8566 if (!has_2ghz) {
8567 mode_v0 = BTC_WLINK_V0_5G;
8568 } else if (mode == BTC_WLINK_DB_MCC) {
8569 mode_v0 = BTC_WLINK_V0_25G_MCC;
8570 } else {
8571 switch (mode) {
8572 case BTC_WLINK_STA:
8573 mode_v0 = BTC_WLINK_V0_2G_STA;
8574 break;
8575 case BTC_WLINK_AP:
8576 mode_v0 = BTC_WLINK_V0_2G_AP;
8577 break;
8578 case BTC_WLINK_GO:
8579 mode_v0 = BTC_WLINK_V0_2G_GO;
8580 break;
8581 case BTC_WLINK_GC:
8582 mode_v0 = BTC_WLINK_V0_2G_GC;
8583 break;
8584 case BTC_WLINK_SCC:
8585 mode_v0 = BTC_WLINK_V0_2G_SCC;
8586 break;
8587 case BTC_WLINK_SB_MCC:
8588 mode_v0 = BTC_WLINK_V0_2G_MCC;
8589 break;
8590 default:
8591 mode_v0 = BTC_WLINK_V0_OTHER;
8592 break;
8593 }
8594 }
8595 }
8596
8597 switch (mode_v0) {
8598 case BTC_WLINK_NOLINK:
8599 _action_wl_nc(rtwdev);
8600 break;
8601 case BTC_WLINK_V0_2G_STA:
8602 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
8603 bt->scan_rx_low_pri = true;
8604 _action_wl_2g_sta(rtwdev);
8605 break;
8606 case BTC_WLINK_V0_2G_AP:
8607 bt->scan_rx_low_pri = true;
8608 _action_wl_2g_ap(rtwdev);
8609 break;
8610 case BTC_WLINK_V0_2G_GO:
8611 bt->scan_rx_low_pri = true;
8612 _action_wl_2g_go(rtwdev);
8613 break;
8614 case BTC_WLINK_V0_2G_GC:
8615 bt->scan_rx_low_pri = true;
8616 _action_wl_2g_gc(rtwdev);
8617 break;
8618 case BTC_WLINK_V0_2G_SCC:
8619 bt->scan_rx_low_pri = true;
8620 _action_wl_2g_scc(rtwdev);
8621 break;
8622 case BTC_WLINK_V0_2G_MCC:
8623 bt->scan_rx_low_pri = true;
8624 _action_wl_2g_mcc(rtwdev);
8625 break;
8626 case BTC_WLINK_V0_25G_MCC:
8627 bt->scan_rx_low_pri = true;
8628 _action_wl_25g_mcc(rtwdev);
8629 break;
8630 case BTC_WLINK_V0_5G:
8631 _action_wl_5g(rtwdev);
8632 break;
8633 case BTC_WLINK_V0_2G_NAN:
8634 _action_wl_2g_nan(rtwdev);
8635 break;
8636 default:
8637 _action_wl_other(rtwdev);
8638 break;
8639 }
8640
8641 exit:
8642 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__);
8643 _action_common(rtwdev);
8644 }
8645
rtw89_btc_init(struct rtw89_dev * rtwdev)8646 void rtw89_btc_init(struct rtw89_dev *rtwdev)
8647 {
8648 const struct rtw89_chip_info *chip = rtwdev->chip;
8649 struct rtw89_btc *btc = &rtwdev->btc;
8650 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8651
8652 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8653 "[BTC], %s(): Init %s !!\n", __func__,
8654 chip_id_str(chip->chip_id));
8655
8656 _reset_btc_var(rtwdev, BTC_RESET_ALL);
8657
8658 btc->dm.run_reason = BTC_RSN_NONE;
8659 btc->dm.run_action = BTC_ACT_NONE;
8660 wl->status.map.init_ok = true;
8661 }
8662
rtw89_btc_ntfy_poweron(struct rtw89_dev * rtwdev)8663 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
8664 {
8665 struct rtw89_btc *btc = &rtwdev->btc;
8666
8667 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
8668 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++;
8669 }
8670
rtw89_btc_ntfy_poweroff(struct rtw89_dev * rtwdev)8671 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
8672 {
8673 struct rtw89_btc *btc = &rtwdev->btc;
8674 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8675
8676 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
8677 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
8678
8679 btc->cx.wl.status.map.rf_off = 1;
8680 btc->cx.wl.status.map.busy = 0;
8681 wl->status.map.lps = BTC_LPS_OFF;
8682
8683 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ALL, false);
8684 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
8685
8686 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
8687 }
8688
8689 #define BTC_PLATFORM_LITTLE_ENDIAN 0
_set_init_info(struct rtw89_dev * rtwdev)8690 static void _set_init_info(struct rtw89_dev *rtwdev)
8691 {
8692 const struct rtw89_chip_info *chip = rtwdev->chip;
8693 struct rtw89_btc *btc = &rtwdev->btc;
8694 struct rtw89_btc_dm *dm = &btc->dm;
8695 struct rtw89_btc_cx *cx = &btc->cx;
8696 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8697
8698 dm->init_info.init_mode = wl->coex_mode;
8699 dm->init_info.wl_init_ok = wl->status.map.init_ok;
8700 dm->init_info.endian_type = BTC_PLATFORM_LITTLE_ENDIAN;
8701 dm->init_info.bt0_function = cx->bt0.func_type;
8702 dm->init_info.bt1_function = cx->bt1.func_type;
8703 dm->init_info.bt2_function = cx->bt_ext.func_type;
8704 dm->init_info.pta_mode = RTW89_MAC_AX_COEX_RTK_MODE;
8705 dm->init_info.pta_direction = RTW89_MAC_AX_COEX_INNER;
8706 dm->init_info.wl_only = dm->wl_only;
8707 dm->init_info.bt_only = dm->bt_only;
8708 dm->init_info.wl_init_ok = wl->status.map.init_ok;
8709 dm->init_info.cx_other = btc->cx.bt_ext.func_type;
8710 dm->init_info.wl_guard_ch = chip->afh_guard_ch;
8711 dm->init_info.dbcc_en = rtwdev->dbcc_en;
8712
8713 dm->init_info.module = btc->mdinfo;
8714
8715 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
8716 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
8717 rtw89_btc_fw_set_slots(rtwdev);
8718 btc_fw_set_monreg(rtwdev);
8719 _set_ext_interface(rtwdev);
8720 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR, RTW89_PHY_0);
8721 }
8722
rtw89_btc_ntfy_init(struct rtw89_dev * rtwdev,u8 mode)8723 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
8724 {
8725 struct rtw89_btc *btc = &rtwdev->btc;
8726 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
8727 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8728 const struct rtw89_chip_info *chip = rtwdev->chip;
8729
8730 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8731 "[BTC], %s(): mode=%d\n", __func__, mode);
8732
8733 wl->coex_mode = mode;
8734 dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
8735 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0;
8736 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0;
8737 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0;
8738 dm->vid = rtwdev->custid;
8739 btc->ctrl.always_freerun = mode == BTC_MODE_COTX;
8740
8741 if (!wl->status.map.init_ok) {
8742 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8743 "[BTC], %s(): return for WL init fail!!\n",
8744 __func__);
8745 dm->error.map.init = true;
8746 return;
8747 }
8748
8749 btc->cx.bt0.enable.now = 1;
8750 btc->cx.bt0.run_patch_code = 1;
8751 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) {
8752 btc->cx.bt1.enable.now = 1;
8753 btc->cx.bt1.run_patch_code = 1;
8754 }
8755
8756 if (rtwdev->chip->para_ver & BTC_FEAT_H2C_MACRO)
8757 btc->io_oflld_type = BTC_IO_OFLD_BTC_H2C;
8758 else
8759 btc->io_oflld_type = BTC_IO_OFLD_NO_SUPPORT;
8760
8761 chip->ops->btc_set_rfe(rtwdev);
8762 chip->ops->btc_init_cfg(rtwdev);
8763
8764 _write_scbd(rtwdev, BTC_ALL_BT,
8765 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
8766
8767 if (rtw89_mac_get_ctrl_path(rtwdev)) {
8768 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8769 "[BTC], %s(): PTA owner warning!!\n",
8770 __func__);
8771 dm->error.map.pta_owner = true;
8772 }
8773
8774 _set_init_info(rtwdev);
8775 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR, RTW89_PHY_0);
8776 btc_fw_set_monreg(rtwdev);
8777 rtw89_btc_fw_set_slots(rtwdev);
8778 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
8779 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
8780
8781 _run_coex(rtwdev, BTC_RSN_NTFY_INIT);
8782 }
8783
rtw89_btc_ntfy_scan_start(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)8784 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
8785 {
8786 struct rtw89_btc *btc = &rtwdev->btc;
8787 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8788
8789 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8790 "[BTC], %s(): phy_idx=%d, band=%d\n",
8791 __func__, phy_idx, band);
8792
8793 if (phy_idx >= RTW89_PHY_NUM)
8794 return;
8795
8796 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
8797 wl->status.map.scan = true;
8798 wl->scan_info.band[phy_idx] = band;
8799 wl->scan_info.phy_map |= BIT(phy_idx);
8800 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
8801
8802 if (rtwdev->dbcc_en) {
8803 wl->dbcc_info.scan_band[phy_idx] = band;
8804 _update_dbcc_band(rtwdev, phy_idx);
8805 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
8806 }
8807
8808 if (RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw))
8809 btc->ctrl.wl_ctrl_info.fw_scan = 1;
8810
8811 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START);
8812 }
8813
rtw89_btc_ntfy_scan_finish(struct rtw89_dev * rtwdev,u8 phy_idx)8814 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
8815 {
8816 struct rtw89_btc *btc = &rtwdev->btc;
8817 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8818
8819 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8820 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
8821 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
8822
8823 wl->status.map.scan = false;
8824 wl->scan_info.phy_map &= ~BIT(phy_idx);
8825 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
8826
8827 if (rtwdev->dbcc_en) {
8828 _update_dbcc_band(rtwdev, phy_idx);
8829 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
8830 }
8831
8832 btc->dm.tdma_instant_excute = 1;
8833
8834 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
8835 }
8836
rtw89_btc_ntfy_switch_band(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)8837 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
8838 {
8839 struct rtw89_btc *btc = &rtwdev->btc;
8840 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8841
8842 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8843 "[BTC], %s(): phy_idx=%d, band=%d\n",
8844 __func__, phy_idx, band);
8845
8846 if (phy_idx >= RTW89_PHY_NUM)
8847 return;
8848
8849 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
8850
8851 if (rtwdev->dbcc_en) {
8852 wl->dbcc_info.scan_band[phy_idx] = band;
8853 _update_dbcc_band(rtwdev, phy_idx);
8854 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
8855 }
8856 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND);
8857 }
8858
rtw89_btc_ntfy_specific_packet(struct rtw89_dev * rtwdev,enum btc_pkt_type pkt_type)8859 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev,
8860 enum btc_pkt_type pkt_type)
8861 {
8862 struct rtw89_btc *btc = &rtwdev->btc;
8863 struct rtw89_btc_cx *cx = &btc->cx;
8864 struct rtw89_btc_wl_info *wl = &cx->wl;
8865 struct rtw89_btc_bt_link_info *b = &cx->bt0.link_info;
8866 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
8867 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
8868 u32 cnt;
8869 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD;
8870 bool delay_work = false;
8871
8872 switch (pkt_type) {
8873 case PACKET_DHCP:
8874 cnt = ++wl->wcnt[BTC_WCNT_DHCP];
8875 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8876 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt);
8877 wl->status.map.handshake = 0;
8878 wl->status.map._4way = 0;
8879 wl->status.map.dhcp = 1;
8880 delay_work = true;
8881 break;
8882 case PACKET_EAPOL:
8883 cnt = ++wl->wcnt[BTC_WCNT_EAPOL];
8884 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8885 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt);
8886 wl->status.map.handshake = 0;
8887 wl->status.map._4way = 1;
8888 wl->status.map.dhcp = 0;
8889 delay_work = true;
8890 if (hfp->exist || hid->exist)
8891 delay /= 2;
8892 break;
8893 case PACKET_EAPOL_END:
8894 cnt = ++wl->wcnt[BTC_WCNT_EAPOL];
8895 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8896 "[BTC], %s(): EAPOL_End cnt=%d\n",
8897 __func__, cnt);
8898 wl->status.map._4way = 0;
8899 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work);
8900 break;
8901 case PACKET_ARP:
8902 cnt = ++wl->wcnt[BTC_WCNT_ARP];
8903 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8904 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt);
8905 return;
8906 case PACKET_ICMP:
8907 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8908 "[BTC], %s(): ICMP pkt\n", __func__);
8909 return;
8910 default:
8911 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8912 "[BTC], %s(): unknown packet type %d\n",
8913 __func__, pkt_type);
8914 return;
8915 }
8916
8917 if (delay_work) {
8918 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work);
8919 wiphy_delayed_work_queue(rtwdev->hw->wiphy,
8920 &rtwdev->coex_act1_work, delay);
8921 }
8922
8923 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
8924 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET);
8925 }
8926
rtw89_btc_ntfy_eapol_packet_work(struct wiphy * wiphy,struct wiphy_work * work)8927 void rtw89_btc_ntfy_eapol_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
8928 {
8929 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
8930 btc.eapol_notify_work);
8931
8932 lockdep_assert_wiphy(wiphy);
8933
8934 rtw89_leave_ps_mode(rtwdev);
8935 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL);
8936 }
8937
rtw89_btc_ntfy_arp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)8938 void rtw89_btc_ntfy_arp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
8939 {
8940 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
8941 btc.arp_notify_work);
8942
8943 lockdep_assert_wiphy(wiphy);
8944
8945 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP);
8946 }
8947
rtw89_btc_ntfy_dhcp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)8948 void rtw89_btc_ntfy_dhcp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
8949 {
8950 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
8951 btc.dhcp_notify_work);
8952
8953 lockdep_assert_wiphy(wiphy);
8954
8955 rtw89_leave_ps_mode(rtwdev);
8956 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP);
8957 }
8958
rtw89_btc_ntfy_icmp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)8959 void rtw89_btc_ntfy_icmp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
8960 {
8961 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
8962 btc.icmp_notify_work);
8963
8964 lockdep_assert_wiphy(wiphy);
8965
8966 rtw89_leave_ps_mode(rtwdev);
8967 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP);
8968 }
8969
_update_bt_rssi_level(struct rtw89_dev * rtwdev,u8 rssi)8970 static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi)
8971 {
8972 const struct rtw89_chip_info *chip = rtwdev->chip;
8973 struct rtw89_btc *btc = &rtwdev->btc;
8974 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
8975 u8 *rssi_st, rssi_th, rssi_level = 0;
8976 u8 i;
8977
8978 /* for rssi locate in which {40, 36, 31, 28}
8979 * if rssi >= 40% (-60dBm) --> rssi_level = 4
8980 * if 36% <= rssi < 40% --> rssi_level = 3
8981 * if 31% <= rssi < 36% --> rssi_level = 2
8982 * if 28% <= rssi < 31% --> rssi_level = 1
8983 * if rssi < 28% --> rssi_level = 0
8984 */
8985
8986 /* check if rssi across bt_rssi_thres boundary */
8987 for (i = 0; i < BTC_BT_RSSI_THMAX; i++) {
8988 rssi_th = chip->bt_rssi_thres[i];
8989 rssi_st = &bt->link_info.rssi_state[i];
8990
8991 *rssi_st = _update_rssi_state(rtwdev, *rssi_st, rssi, rssi_th);
8992
8993 if (BTC_RSSI_HIGH(*rssi_st)) {
8994 rssi_level = BTC_BT_RSSI_THMAX - i;
8995 break;
8996 }
8997 }
8998 return rssi_level;
8999 }
9000
9001 #define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4)
9002
_update_bt_info(struct rtw89_dev * rtwdev,u8 bid,u8 * buf,u32 len)9003 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 bid, u8 *buf, u32 len)
9004 {
9005 const struct rtw89_chip_info *chip = rtwdev->chip;
9006 struct rtw89_btc *btc = &rtwdev->btc;
9007 struct rtw89_btc_bt_a2dp_desc *a2dp;
9008 struct rtw89_btc_cx *cx = &btc->cx;
9009 struct rtw89_btc_bt_hfp_desc *hfp;
9010 struct rtw89_btc_bt_hid_desc *hid;
9011 struct rtw89_btc_bt_pan_desc *pan;
9012 struct rtw89_btc_bt_link_info *b;
9013 struct rtw89_btc_bt_info *bt;
9014 union btc_btinfo btinfo;
9015 u8 is_bt_56g = 0;
9016 u8 *raw_info;
9017
9018 /* Bit7 is used for RF-band: 0:BT_2.4 GHz, 1:BT_5/6 GHz */
9019 if ((buf[BTC_BTINFO_L1] & 0x7f) != 6)
9020 return;
9021
9022 bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1;
9023
9024 if ((buf[BTC_BTINFO_L1] & BIT(7)) && bt->band_56G_support) {
9025 b = &bt->link_info_56g;
9026 is_bt_56g = 1;
9027 if (b->status.map.connect)
9028 bt->rf_band_map |= BIT(RTW89_BAND_5G);
9029 else
9030 bt->rf_band_map &= ~BIT(RTW89_BAND_5G);
9031 } else {
9032 b = &bt->link_info;
9033 bt->rf_band_map |= BIT(RTW89_BAND_2G);
9034 }
9035
9036 hfp = &b->hfp_desc;
9037 hid = &b->hid_desc;
9038 a2dp = &b->a2dp_desc;
9039 pan = &b->pan_desc;
9040 raw_info = is_bt_56g ? bt->raw_info_56g : bt->raw_info;
9041
9042 if (!memcmp(raw_info, buf, BTC_BTINFO_MAX)) {
9043 rtw89_debug(rtwdev, RTW89_DBG_BTC,
9044 "[BTC], %s(): return by bt-info duplicate!!\n",
9045 __func__);
9046 bt->bcnt[BTC_BCNT_INFOSAME]++;
9047 return;
9048 }
9049
9050 memcpy(raw_info, buf, BTC_BTINFO_MAX);
9051
9052 rtw89_debug(rtwdev, RTW89_DBG_BTC,
9053 "[BTC], %s(): bt_info[2]=0x%02x\n",
9054 __func__, raw_info[2]);
9055
9056 hid->type = 0;
9057
9058 /* parse raw info low-Byte2 */
9059 btinfo.val = raw_info[BTC_BTINFO_L2];
9060 b->status.map.connect = btinfo.lb2.connect;
9061 b->status.map.sco_busy = btinfo.lb2.sco_busy;
9062 b->status.map.acl_busy = btinfo.lb2.acl_busy;
9063 b->status.map.inq_pag = btinfo.lb2.inq_pag;
9064 bt->inq_pag.now = btinfo.lb2.inq_pag;
9065 bt->bcnt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
9066
9067 hfp->exist = btinfo.lb2.hfp;
9068 hid->exist = btinfo.lb2.hid;
9069 a2dp->exist = btinfo.lb2.a2dp;
9070 pan->exist = btinfo.lb2.pan;
9071 _update_bt_link_cnt(rtwdev, bt, is_bt_56g);
9072 btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK);
9073
9074 /* parse raw info low-Byte3 */
9075 btinfo.val = raw_info[BTC_BTINFO_L3];
9076 if (btinfo.lb3.retry != 0)
9077 bt->bcnt[BTC_BCNT_RETRY]++;
9078 b->cqddr = btinfo.lb3.cqddr;
9079 bt->bcnt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
9080 bt->inq = btinfo.lb3.inq;
9081 bt->bcnt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
9082 bt->pag = btinfo.lb3.pag;
9083
9084 b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
9085 /* parse raw info high-Byte0 */
9086 btinfo.val = raw_info[BTC_BTINFO_H0];
9087 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/
9088 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi);
9089 bt->rssi_level = _update_bt_rssi_level(rtwdev, b->rssi);
9090 btc->dm.trx_info.bt_rssi = bt->rssi_level;
9091
9092 /* parse raw info high-Byte1 */
9093 btinfo.val = raw_info[BTC_BTINFO_H1];
9094 b->status.map.ble_connect = btinfo.hb1.ble_connect;
9095 if (btinfo.hb1.ble_connect) {
9096 if (hid->exist)
9097 hid->type |= BTC_HID_BLE;
9098 else if (btinfo.hb1.voice)
9099 hid->type |= BTC_HID_RCU_VOICE;
9100 else
9101 hid->type |= BTC_HID_RCU;
9102 }
9103
9104 bt->bcnt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
9105 bt->reinit = btinfo.hb1.reinit;
9106 bt->bcnt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
9107 b->relink.now = btinfo.hb1.relink;
9108 bt->bcnt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
9109 bt->igno_wl = btinfo.hb1.igno_wl;
9110
9111 if (bt->igno_wl && !cx->wl.status.map.rf_off)
9112 _set_bt_ignore_wlan_act(rtwdev, false);
9113
9114 bt->ble_scan_en = btinfo.hb1.ble_scan;
9115
9116 bt->bcnt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
9117 b->role_sw = btinfo.hb1.role_sw;
9118
9119 b->multi_link.now = btinfo.hb1.multi_link;
9120
9121 /* parse raw info high-Byte2 */
9122 btinfo.val = raw_info[BTC_BTINFO_H2];
9123 pan->active = !!btinfo.hb2.pan_active;
9124
9125 bt->bcnt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
9126 b->afh_update = btinfo.hb2.afh_update;
9127 a2dp->active = btinfo.hb2.a2dp_active;
9128 b->slave_role = btinfo.hb2.slave;
9129 hid->slot_info = btinfo.hb2.hid_slot;
9130 hid->pair_cnt = btinfo.hb2.hid_cnt;
9131 if (!b->status.map.ble_connect || hid->pair_cnt > 1)
9132 hid->type |= (hid->slot_info == BTC_HID_218 ?
9133 BTC_HID_218 : BTC_HID_418);
9134 /* parse raw info high-Byte3 */
9135 btinfo.val = raw_info[BTC_BTINFO_H3];
9136 a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
9137
9138 if (b->tx_3m != (u32)btinfo.hb3.tx_3m)
9139 bt->bcnt[BTC_BCNT_RATECHG]++;
9140 b->tx_3m = (u32)btinfo.hb3.tx_3m;
9141
9142 a2dp->sink = btinfo.hb3.a2dp_sink;
9143
9144 if (!a2dp->exist_last && a2dp->exist) {
9145 a2dp->vendor_id = 0;
9146 a2dp->flush_time = 0;
9147 a2dp->play_latency = 1;
9148 wiphy_delayed_work_queue(rtwdev->hw->wiphy,
9149 &rtwdev->coex_bt_devinfo_work,
9150 RTW89_COEX_BT_DEVINFO_WORK_PERIOD);
9151 }
9152
9153 _update_bt_ctrl_lps(rtwdev);
9154 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
9155 }
9156
_ntfy_role_info(struct rtw89_dev * rtwdev,u8 rid,struct rtw89_btc_wl_link_info * info,enum btc_role_state reason)9157 static void _ntfy_role_info(struct rtw89_dev *rtwdev, u8 rid,
9158 struct rtw89_btc_wl_link_info *info,
9159 enum btc_role_state reason)
9160 {
9161 struct rtw89_btc *btc = &rtwdev->btc;
9162 struct rtw89_btc_wl_link_info *wlinfo = NULL;
9163 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9164 const struct rtw89_btc_ver *ver = btc->ver;
9165 u8 rlink_id = info->phy; /* 1 role_id has 2 rlink_id(by HW_Band0/1) */
9166 bool refresh_role = false;
9167
9168 rtw89_debug(rtwdev, RTW89_DBG_BTC,
9169 "[BTC], %s(), role_id=%d, reason=%d\n",
9170 __func__, rid, reason);
9171
9172 if (rid >= ver->max_role_num || rlink_id >= RTW89_PHY_NUM)
9173 return;
9174
9175 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
9176
9177 wlinfo = &wl->rlink_info[rid][rlink_id];
9178 memcpy(wlinfo, info, sizeof(struct rtw89_btc_wl_link_info));
9179
9180 switch (reason) {
9181 case BTC_ROLE_START:
9182 wlinfo->active = true;
9183 return;
9184 case BTC_ROLE_STOP:
9185 wlinfo->active = false;
9186 return;
9187 case BTC_ROLE_MSTS_STA_CONN_START:
9188 wl->status.map.transacting = 1;
9189 wiphy_delayed_work_cancel(rtwdev->hw->wiphy,
9190 &rtwdev->coex_act1_work);
9191 wiphy_delayed_work_queue(rtwdev->hw->wiphy,
9192 &rtwdev->coex_act1_work,
9193 RTW89_COEX_ACT1_WORK_PERIOD);
9194 break;
9195 case BTC_ROLE_MSTS_STA_CONN_END:
9196 wl->status.map.transacting = 0;
9197 refresh_role = true;
9198 break;
9199 case BTC_ROLE_MSTS_STA_DIS_CONN:
9200 wl->status.map.transacting = 1;
9201 refresh_role = false;
9202 wiphy_delayed_work_cancel(rtwdev->hw->wiphy,
9203 &rtwdev->coex_act1_work);
9204 wiphy_delayed_work_queue(rtwdev->hw->wiphy,
9205 &rtwdev->coex_act1_work,
9206 RTW89_COEX_ACT1_WORK_PERIOD);
9207 break;
9208 case BTC_ROLE_MSTS_AP_START:
9209 case BTC_ROLE_MSTS_AP_STOP:
9210 refresh_role = true;
9211 break;
9212 case BTC_ROLE_STATE_UNKNOWN:
9213 rtw89_debug(rtwdev, RTW89_DBG_BTC,
9214 "[BTC], %s(), role_id=%d, Unknown reason return!\n",
9215 __func__, rid);
9216 return;
9217 default:
9218 return;
9219 }
9220
9221 if (refresh_role) {
9222 _update_wl_info(rtwdev, wlinfo);
9223 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
9224 }
9225
9226 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
9227 }
9228
rtw89_btc_ntfy_role_info(struct rtw89_dev * rtwdev,struct rtw89_vif_link * rtwvif_link,struct rtw89_sta_link * rtwsta_link,enum btc_role_state state)9229 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev,
9230 struct rtw89_vif_link *rtwvif_link,
9231 struct rtw89_sta_link *rtwsta_link,
9232 enum btc_role_state state)
9233 {
9234 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
9235 rtwvif_link->chanctx_idx);
9236 struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
9237 struct ieee80211_p2p_noa_attr *noa_attr;
9238 struct ieee80211_p2p_noa_desc *noa_desc;
9239 struct ieee80211_bss_conf *bss_conf;
9240 struct ieee80211_link_sta *link_sta;
9241 struct rtw89_btc_wl_link_info r = {0};
9242 u8 i, role_id, mode = 0;
9243
9244 rcu_read_lock();
9245
9246 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
9247
9248 role_id = rtwvif_link->port;
9249
9250 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
9251 rtw89_debug(rtwdev, RTW89_DBG_BTC,
9252 "[BTC], role is STA=%d\n",
9253 vif->type == NL80211_IFTYPE_STATION);
9254 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", role_id);
9255 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
9256 chan->band_type, chan->channel, chan->band_width);
9257 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
9258 state == BTC_ROLE_MSTS_STA_CONN_END);
9259 rtw89_debug(rtwdev, RTW89_DBG_BTC,
9260 "[BTC], bcn_period=%d dtim_period=%d\n",
9261 bss_conf->beacon_int, bss_conf->dtim_period);
9262
9263 if (rtwsta_link) {
9264 link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
9265
9266 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
9267 rtwsta_link->mac_id);
9268
9269 rtw89_debug(rtwdev, RTW89_DBG_BTC,
9270 "[BTC], STA support HE=%d VHT=%d HT=%d\n",
9271 link_sta->he_cap.has_he,
9272 link_sta->vht_cap.vht_supported,
9273 link_sta->ht_cap.ht_supported);
9274 if (link_sta->he_cap.has_he)
9275 mode |= BIT(BTC_WL_MODE_HE);
9276 if (link_sta->vht_cap.vht_supported)
9277 mode |= BIT(BTC_WL_MODE_VHT);
9278 if (link_sta->ht_cap.ht_supported)
9279 mode |= BIT(BTC_WL_MODE_HT);
9280
9281 r.mode = mode;
9282 }
9283
9284 if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) {
9285 rcu_read_unlock();
9286 return;
9287 }
9288
9289 rtw89_debug(rtwdev, RTW89_DBG_BTC,
9290 "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role);
9291
9292 if (vif->type == NL80211_IFTYPE_P2P_GO ||
9293 vif->type == NL80211_IFTYPE_P2P_CLIENT) {
9294 noa_attr = &bss_conf->p2p_noa_attr;
9295
9296 for (i = 0; i < RTW89_P2P_MAX_NOA_NUM; i++) {
9297 noa_desc = &noa_attr->desc[i];
9298 if (noa_desc->count != 0) {
9299 r.noa = 1;
9300 r.noa_duration = le32_to_cpu(noa_desc->duration);
9301 break;
9302 }
9303 }
9304 }
9305
9306 r.mode = mode;
9307 r.role = rtwvif_link->wifi_role;
9308 r.phy = rtwvif_link->phy_idx;
9309 r.pid = role_id;
9310 r.active = true;
9311 if (vif->active_links) {
9312 if (rtwvif_link->link_id < 16)
9313 r.active = !!(vif->active_links & BIT(rtwvif_link->link_id));
9314 }
9315 r.bcn_period = bss_conf->beacon_int;
9316 r.dtim_period = bss_conf->dtim_period;
9317 r.band = chan->band_type;
9318 r.ch = chan->channel;
9319 r.bw = chan->band_width;
9320 r.chdef.band = chan->band_type;
9321 r.chdef.center_ch = chan->channel;
9322 r.chdef.bw = chan->band_width;
9323 r.chdef.chan = chan->primary_channel;
9324
9325 if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION) {
9326 r.mac_id = rtwsta_link->mac_id;
9327 ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr);
9328 }
9329
9330 switch (state) {
9331 case BTC_ROLE_MSTS_STA_CONN_END:
9332 case BTC_ROLE_MSTS_AP_START:
9333 r.connected = MLME_LINKED;
9334 break;
9335 default:
9336 r.connected = MLME_NO_LINK;
9337 break;
9338 }
9339
9340 rcu_read_unlock();
9341
9342 _ntfy_role_info(rtwdev, role_id, &r, state);
9343 }
9344
rtw89_btc_ntfy_radio_state(struct rtw89_dev * rtwdev,enum btc_rfctrl rf_state)9345 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state)
9346 {
9347 const struct rtw89_chip_info *chip = rtwdev->chip;
9348 struct rtw89_btc *btc = &rtwdev->btc;
9349 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9350 u32 val;
9351
9352 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
9353 __func__, rf_state);
9354 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
9355
9356 switch (rf_state) {
9357 case BTC_RFCTRL_WL_OFF:
9358 wl->status.map.rf_off = 1;
9359 wl->status.map.lps = BTC_LPS_OFF;
9360 wl->status.map.busy = 0;
9361 break;
9362 case BTC_RFCTRL_FW_CTRL:
9363 wl->status.map.rf_off = 0;
9364 wl->status.map.lps = BTC_LPS_RF_OFF;
9365 wl->status.map.busy = 0;
9366 break;
9367 case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */
9368 wl->status.map.rf_off = 0;
9369 wl->status.map.lps = BTC_LPS_RF_ON;
9370 wl->status.map.busy = 0;
9371 break;
9372 case BTC_RFCTRL_WL_ON:
9373 default:
9374 wl->status.map.rf_off = 0;
9375 wl->status.map.lps = BTC_LPS_OFF;
9376 break;
9377 }
9378
9379 if (rf_state == BTC_RFCTRL_WL_ON) {
9380 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG;
9381 _write_scbd(rtwdev, BTC_ALL_BT, val, true);
9382 chip->ops->btc_init_cfg(rtwdev);
9383 } else {
9384 if (rf_state == BTC_RFCTRL_FW_CTRL)
9385 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ACTIVE, false);
9386 else if (rf_state == BTC_RFCTRL_WL_OFF)
9387 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ALL, false);
9388 else
9389 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_ACTIVE, false);
9390 }
9391
9392 btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
9393 btc->dm.tdma_instant_excute = 1;
9394
9395 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
9396 wl->status.map.rf_off_pre = wl->status.map.rf_off;
9397 wl->status.map.lps_pre = wl->status.map.lps;
9398 }
9399
_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_path,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)9400 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path,
9401 enum btc_wl_rfk_type type,
9402 enum btc_wl_rfk_state state)
9403 {
9404 struct rtw89_btc *btc = &rtwdev->btc;
9405 struct rtw89_btc_cx *cx = &btc->cx;
9406 struct rtw89_btc_wl_info *wl = &cx->wl;
9407 bool result = BTC_WRFK_REJECT;
9408
9409 wl->rfk_info.type = type;
9410 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path);
9411 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path);
9412 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path);
9413
9414 rtw89_debug(rtwdev, RTW89_DBG_BTC,
9415 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
9416 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
9417 type, state);
9418
9419 switch (state) {
9420 case BTC_WRFK_START:
9421 result = BTC_WRFK_ALLOW;
9422 wl->rfk_info.state = BTC_WRFK_START;
9423
9424 btc->cx.wl.wcnt[BTC_WCNT_RFK_REQ]++;
9425 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
9426
9427 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLRFK, true);
9428 break;
9429 case BTC_WRFK_ONESHOT_START:
9430 case BTC_WRFK_ONESHOT_STOP:
9431 btc->cx.wl.wcnt[BTC_WCNT_RFK_GO]++;
9432 if (type != BTC_WRFKT_RXDCK)
9433 return BTC_WRFK_ALLOW;
9434 break;
9435 case BTC_WRFK_STOP:
9436 result = BTC_WRFK_ALLOW;
9437 wl->rfk_info.state = BTC_WRFK_STOP;
9438
9439 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLRFK, false);
9440 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_rfk_chk_work);
9441 break;
9442 default:
9443 rtw89_debug(rtwdev, RTW89_DBG_BTC,
9444 "[BTC], %s() warning state=%d\n", __func__, state);
9445 return result;
9446 }
9447
9448 if (result == BTC_WRFK_ALLOW) {
9449 if (wl->rfk_info.state == BTC_WRFK_START ||
9450 wl->rfk_info.state == BTC_WRFK_STOP)
9451 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK);
9452
9453 if (wl->rfk_info.state == BTC_WRFK_START)
9454 wiphy_delayed_work_queue(rtwdev->hw->wiphy,
9455 &rtwdev->coex_rfk_chk_work,
9456 RTW89_COEX_RFK_CHK_WORK_PERIOD);
9457 }
9458
9459 rtw89_debug(rtwdev, RTW89_DBG_BTC,
9460 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
9461 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
9462
9463 return result;
9464 }
9465
rtw89_btc_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_map,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)9466 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
9467 enum btc_wl_rfk_type type,
9468 enum btc_wl_rfk_state state)
9469 {
9470 u8 band;
9471 bool allow;
9472 int ret;
9473
9474 lockdep_assert_wiphy(rtwdev->hw->wiphy);
9475
9476 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map);
9477
9478 rtw89_debug(rtwdev, RTW89_DBG_RFK,
9479 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n",
9480 band == RTW89_BAND_2G ? "2G" :
9481 band == RTW89_BAND_5G ? "5G" : "6G",
9482 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)),
9483 type,
9484 FIELD_GET(BTC_RFK_PATH_MAP, phy_map),
9485 state == BTC_WRFK_STOP ? "RFK_STOP" :
9486 state == BTC_WRFK_START ? "RFK_START" :
9487 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" :
9488 "ONE-SHOT_STOP");
9489
9490 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) {
9491 _ntfy_wl_rfk(rtwdev, phy_map, type, state);
9492 return;
9493 }
9494
9495 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false,
9496 rtwdev, phy_map, type, state);
9497 if (ret) {
9498 rtw89_warn(rtwdev, "RFK notify timeout\n");
9499 rtwdev->is_bt_iqk_timeout = true;
9500 }
9501 }
9502 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk);
9503
9504 struct rtw89_btc_wl_sta_iter_data {
9505 struct rtw89_dev *rtwdev;
9506 u8 busy_all;
9507 u8 dir_all;
9508 u8 rssi_map_all;
9509 bool is_sta_change;
9510 bool is_traffic_change;
9511 };
9512
9513 static
__rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link * rtwvif_link,struct rtw89_sta_link * rtwsta_link,struct rtw89_btc_wl_sta_iter_data * iter_data)9514 void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link,
9515 struct rtw89_sta_link *rtwsta_link,
9516 struct rtw89_btc_wl_sta_iter_data *iter_data)
9517 {
9518 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
9519 struct rtw89_dev *rtwdev = iter_data->rtwdev;
9520 struct rtw89_btc *btc = &rtwdev->btc;
9521 struct rtw89_btc_dm *dm = &btc->dm;
9522 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9523 struct rtw89_btc_wl_link_info *link_info = NULL;
9524 struct rtw89_traffic_stats *link_info_t = NULL;
9525 struct rtw89_traffic_stats *stats = &rtwvif->stats;
9526 const struct rtw89_chip_info *chip = rtwdev->chip;
9527 struct rtw89_btc_wl_role_info *r;
9528 u32 last_tx_rate, last_rx_rate;
9529 u8 link = rtwvif_link->phy_idx;
9530 u16 last_tx_lvl, last_rx_lvl;
9531 u8 port = rtwvif_link->port;
9532 u8 rssi;
9533 u8 busy = 0;
9534 u8 dir = 0;
9535 u8 rssi_map = 0;
9536 u8 i = 0;
9537 bool is_sta_change = false, is_traffic_change = false;
9538
9539 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR;
9540 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
9541
9542 link_info = &wl->rlink_info[port][link];
9543
9544 link_info->stat.traffic = *stats;
9545 link_info_t = &link_info->stat.traffic;
9546
9547 if (link_info->connected == MLME_NO_LINK) {
9548 link_info->rx_rate_drop_cnt = 0;
9549 return;
9550 }
9551
9552 link_info->stat.rssi = rssi;
9553 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) {
9554 link_info->rssi_state[i] =
9555 _update_rssi_state(rtwdev,
9556 link_info->rssi_state[i],
9557 link_info->stat.rssi,
9558 chip->wl_rssi_thres[i]);
9559 if (BTC_RSSI_LOW(link_info->rssi_state[i]))
9560 rssi_map |= BIT(i);
9561
9562 if (btc->ant_type == BTC_ANT_DEDICATED &&
9563 BTC_RSSI_CHANGE(link_info->rssi_state[i]))
9564 is_sta_change = true;
9565 }
9566 iter_data->rssi_map_all |= rssi_map;
9567
9568 last_tx_rate = link_info_t->tx_rate;
9569 last_rx_rate = link_info_t->rx_rate;
9570 last_tx_lvl = (u16)link_info_t->tx_tfc_lv;
9571 last_rx_lvl = (u16)link_info_t->rx_tfc_lv;
9572
9573 if (stats->tx_tfc_lv != RTW89_TFC_IDLE ||
9574 stats->rx_tfc_lv != RTW89_TFC_IDLE)
9575 busy = 1;
9576
9577 if (stats->tx_tfc_lv > stats->rx_tfc_lv)
9578 dir = RTW89_TFC_UL;
9579 else
9580 dir = RTW89_TFC_DL;
9581
9582 if (link_info->busy != busy || link_info->dir != dir) {
9583 is_sta_change = true;
9584 link_info->busy = busy;
9585 link_info->dir = dir;
9586 }
9587
9588 iter_data->busy_all |= busy;
9589 iter_data->dir_all |= BIT(dir);
9590
9591 if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
9592 last_rx_rate > RTW89_HW_RATE_CCK2 &&
9593 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
9594 link_info->rx_rate_drop_cnt++;
9595
9596 if (last_tx_rate != rtwsta_link->ra_report.hw_rate ||
9597 last_rx_rate != rtwsta_link->rx_hw_rate ||
9598 last_tx_lvl != link_info_t->tx_tfc_lv ||
9599 last_rx_lvl != link_info_t->rx_tfc_lv)
9600 is_traffic_change = true;
9601
9602 link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate;
9603 link_info_t->rx_rate = rtwsta_link->rx_hw_rate;
9604
9605 if (link_info->role == RTW89_WIFI_ROLE_STATION ||
9606 link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) {
9607 dm->trx_info.tx_rate = link_info_t->tx_rate;
9608 dm->trx_info.rx_rate = link_info_t->rx_rate;
9609 }
9610
9611 r = &wl->role_info;
9612 r->rlink[port][link].tx_lvl = stats->tx_tfc_lv;
9613 r->rlink[port][link].rx_lvl = stats->rx_tfc_lv;
9614 r->rlink[port][link].tx_rate = rtwsta_link->ra_report.hw_rate;
9615 r->rlink[port][link].rx_rate = rtwsta_link->rx_hw_rate;
9616
9617 dm->trx_info.tx_lvl = stats->tx_tfc_lv;
9618 dm->trx_info.rx_lvl = stats->rx_tfc_lv;
9619 dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate;
9620 dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate;
9621 dm->trx_info.tx_tp = link_info_t->tx_throughput;
9622 dm->trx_info.rx_tp = link_info_t->rx_throughput;
9623
9624 /* Trigger coex-run if 0x10980 reg-value is diff with coex setup */
9625 if ((dm->wl_btg_rx_rb != dm->wl_btg_rx &&
9626 dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) ||
9627 (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
9628 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND))
9629 iter_data->is_sta_change = true;
9630
9631 if (is_sta_change)
9632 iter_data->is_sta_change = true;
9633
9634 if (is_traffic_change)
9635 iter_data->is_traffic_change = true;
9636 }
9637
rtw89_btc_ntfy_wl_sta_iter(void * data,struct ieee80211_sta * sta)9638 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
9639 {
9640 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
9641 struct rtw89_btc_wl_sta_iter_data *iter_data =
9642 (struct rtw89_btc_wl_sta_iter_data *)data;
9643 struct rtw89_vif_link *rtwvif_link;
9644 struct rtw89_sta_link *rtwsta_link;
9645 unsigned int link_id;
9646
9647 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
9648 rtwvif_link = rtwsta_link->rtwvif_link;
9649 __rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data);
9650 }
9651 }
9652
9653 #define BTC_NHM_CHK_INTVL 20
9654
rtw89_btc_ntfy_wl_sta(struct rtw89_dev * rtwdev)9655 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
9656 {
9657 struct rtw89_btc *btc = &rtwdev->btc;
9658 struct rtw89_btc_dm *dm = &btc->dm;
9659 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9660 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev};
9661 u8 i;
9662
9663 ieee80211_iterate_stations_atomic(rtwdev->hw,
9664 rtw89_btc_ntfy_wl_sta_iter,
9665 &data);
9666
9667 wl->rssi_level = 0;
9668 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++;
9669 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) {
9670 /* set RSSI level 4 ~ 0 if rssi bit map match */
9671 if (data.rssi_map_all & BIT(i - 1)) {
9672 wl->rssi_level = i;
9673 break;
9674 }
9675 }
9676
9677 if (dm->trx_info.wl_rssi != wl->rssi_level)
9678 dm->trx_info.wl_rssi = wl->rssi_level;
9679
9680 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n",
9681 __func__, !!wl->status.map.busy);
9682
9683 _write_scbd(rtwdev, BTC_ALL_BT, BTC_WSCB_WLBUSY, (!!wl->status.map.busy));
9684
9685 if (data.is_traffic_change)
9686 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
9687 if (data.is_sta_change) {
9688 wl->status.map.busy = data.busy_all;
9689 wl->status.map.traffic_dir = data.dir_all;
9690 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA);
9691 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >=
9692 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) {
9693 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
9694 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
9695 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] <
9696 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) {
9697 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
9698 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
9699 }
9700 }
9701
rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev * rtwdev,u8 func)9702 static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func)
9703 {
9704 struct rtw89_btc *btc = &rtwdev->btc;
9705 const struct rtw89_btc_ver *ver = btc->ver;
9706
9707 switch (func) {
9708 case BTF_EVNT_RPT:
9709 case BTF_EVNT_BT_INFO:
9710 case BTF_EVNT_BT_SCBD:
9711 case BTF_EVNT_BT_REG:
9712 case BTF_EVNT_CX_RUNINFO:
9713 case BTF_EVNT_BT_PSD:
9714 return func;
9715 case BTF_EVNT_BT_DEV_INFO:
9716 if (ver->fwc2hfunc == 0)
9717 return BTF_EVNT_BUF_OVERFLOW;
9718 else
9719 return BTF_EVNT_BT_DEV_INFO;
9720 case BTF_EVNT_BT_LEAUDIO_INFO:
9721 if (ver->fwc2hfunc == 0)
9722 return BTF_EVNT_C2H_LOOPBACK;
9723 else if (ver->fwc2hfunc == 1)
9724 return BTF_EVNT_BUF_OVERFLOW;
9725 else if (ver->fwc2hfunc == 2)
9726 return func;
9727 else if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4)
9728 return BTF_EVNT_BUF_OVERFLOW;
9729 else
9730 return BTF_EVNT_MAX;
9731 case BTF_EVNT_BUF_OVERFLOW:
9732 if (ver->fwc2hfunc == 0)
9733 return BTF_EVNT_MAX;
9734 else if (ver->fwc2hfunc == 1)
9735 return BTF_EVNT_C2H_LOOPBACK;
9736 else if (ver->fwc2hfunc == 2)
9737 return func;
9738 else if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4)
9739 return BTF_EVNT_C2H_LOOPBACK;
9740 else
9741 return BTF_EVNT_MAX;
9742 case BTF_EVNT_C2H_LOOPBACK:
9743 if (ver->fwc2hfunc == 2)
9744 return func;
9745 else if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4)
9746 return BTF_EVNT_BT_LEAUDIO_INFO;
9747 else
9748 return BTF_EVNT_MAX;
9749 case BTF_EVNT_BT_QUERY_TXPWR:
9750 if (ver->fwc2hfunc == 3 || ver->fwc2hfunc == 4)
9751 return func;
9752 else
9753 return BTF_EVNT_MAX;
9754 case BTF_EVNT_ZB_INFO:
9755 case BTF_EVNT_ZB_CH:
9756 case BTF_EVNT_ZB_QUERY_TXPWR:
9757 if (ver->fwc2hfunc == 4)
9758 return func;
9759 else
9760 return BTF_EVNT_MAX;
9761 case BTF_EVNT_MAX:
9762 default:
9763 return BTF_EVNT_MAX;
9764 }
9765 }
9766
rtw89_btc_c2h_handle(struct rtw89_dev * rtwdev,struct sk_buff * skb,u32 len,u8 class,u8 func)9767 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
9768 u32 len, u8 class, u8 func)
9769 {
9770 struct rtw89_btc *btc = &rtwdev->btc;
9771 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt0;
9772 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9773 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN];
9774 u8 bid = BTC_BT_1ST;
9775
9776 len -= RTW89_C2H_HEADER_LEN;
9777
9778 rtw89_debug(rtwdev, RTW89_DBG_BTC,
9779 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n",
9780 __func__, len, class, func);
9781
9782 if (class != BTFC_FW_EVENT)
9783 return;
9784
9785 if (func & BT_C2H_FUNC_BT2ND) {
9786 bid = BTC_BT_2ND;
9787 func &= ~BT_C2H_FUNC_BT2ND;
9788 bt = &btc->cx.bt1;
9789 }
9790
9791 func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func);
9792 pfwinfo->cnt_c2h++;
9793
9794 switch (func) {
9795 case BTF_EVNT_BUF_OVERFLOW:
9796 pfwinfo->event[func]++;
9797 break;
9798 case BTF_EVNT_RPT:
9799 pfwinfo->event[func]++;
9800 /* Don't need rtw89_leave_ps_mode() */
9801 btc_fw_event(rtwdev, func, buf, len);
9802 break;
9803 case BTF_EVNT_BT_INFO:
9804 rtw89_debug(rtwdev, RTW89_DBG_BTC,
9805 "[BTC], handle C2H BT INFO with data %8ph\n", buf);
9806 bt->bcnt[BTC_BCNT_INFOUPDATE]++;
9807 _update_bt_info(rtwdev, bid, buf, len);
9808 break;
9809 case BTF_EVNT_BT_SCBD:
9810 bt->bcnt[BTC_BCNT_SCBDUPDATE]++;
9811 bt->scbd_c2h = ((buf[3] << 24) | (buf[2] << 16) |
9812 (buf[1] << 8) | (buf[0]));
9813 bt->scbd_rb = bt->scbd_c2h;
9814 rtw89_debug(rtwdev, RTW89_DBG_BTC,
9815 "[BTC], handle C2H BT%d SCBD with data 0x%08x\n",
9816 bid, bt->scbd_c2h);
9817 _update_bt_scbd(rtwdev, bid);
9818 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
9819 break;
9820 case BTF_EVNT_BT_PSD:
9821 break;
9822 case BTF_EVNT_BT_REG:
9823 btc->dbg.rb_done = true;
9824 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf));
9825
9826 break;
9827 case BTF_EVNT_C2H_LOOPBACK:
9828 btc->dbg.rb_done = true;
9829 btc->dbg.rb_val = buf[0];
9830 break;
9831 case BTF_EVNT_CX_RUNINFO:
9832 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
9833 break;
9834 case BTF_EVNT_BT_LEAUDIO_INFO:
9835 bt->bcnt[BTC_BCNT_LEAUDIO_INFOUPDATE]++;
9836 if (buf[BTC_BTINFO_L0] == BTC_BTINFO_BISTDMA)
9837 _update_bt_bistdma_info(rtwdev, bid, buf, len);
9838 else
9839 _update_bt_leaudio_info(rtwdev, bid, buf, len);
9840 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_LEAUDINFO);
9841 break;
9842 case BTF_EVNT_BT_QUERY_TXPWR:
9843 bt->bcnt[BTC_BCNT_TXPWR_UPDATE]++;
9844 _update_bt_txpwr_info(rtwdev, buf, len);
9845 }
9846 }
9847
9848 #define BTC_CX_FW_OFFLOAD 0
9849
_show_cx_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9850 static int _show_cx_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9851 {
9852 struct rtw89_btc_module *md = &rtwdev->btc.mdinfo;
9853 const struct rtw89_chip_info *chip = rtwdev->chip;
9854 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
9855 struct rtw89_hal *hal = &rtwdev->hal;
9856 struct rtw89_btc *btc = &rtwdev->btc;
9857 struct rtw89_btc_dm *dm = &btc->dm;
9858 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
9859 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9860 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
9861 char *p = buf, *end = buf + bufsz;
9862
9863 if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
9864 return 0;
9865
9866 p += scnprintf(p, end - p,
9867 "\n========== [BTC COEX INFO (%s)] ==========\n",
9868 chip_id_str(chip->chip_id));
9869
9870 ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION);
9871 ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION);
9872 ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION);
9873 id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION);
9874 p += scnprintf(p, end - p, " %-15s : Coex:%d.%d.%d(branch:%d), ",
9875 "[coex_version]", ver_main, ver_sub, ver_hotfix,
9876 id_branch);
9877
9878 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
9879 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex);
9880 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex);
9881 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex);
9882 p += scnprintf(p, end - p, "WL_FW_coex:%d.%d.%d(branch:%d)",
9883 ver_main, ver_sub, ver_hotfix, id_branch);
9884
9885 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired);
9886 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired);
9887 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
9888 p += scnprintf(p, end - p, "(%s, desired:%d.%d.%d), ",
9889 (wl->ver_info.fw_coex >= chip->wlcx_desired ?
9890 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
9891
9892 p += scnprintf(p, end - p, "BT_FW_coex:%d(%s, desired:%d)\n",
9893 bt->ver_info.fw_coex,
9894 (bt->ver_info.fw_coex >= ver->bt_desired ?
9895 "Match" : "Mismatch"), ver->bt_desired);
9896
9897 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw);
9898 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw);
9899 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw);
9900 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw);
9901 p += scnprintf(p, end - p,
9902 " %-15s : WL_FW:%d.%d.%d.%d(built:%.12s-%.12s), BT_FW:0x%x(%s)\n",
9903 "[sub_module]",
9904 ver_main, ver_sub, ver_hotfix, id_branch,
9905 wl->ver_info.build_time, wl->ver_info.build_date,
9906 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM");
9907
9908 p += scnprintf(p, end - p,
9909 " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s",
9910 "[hw_info]",
9911 md->kt_ver, md->rfe_type, md->ant.isolation,
9912 md->ant.num, md->ant.num > 1 ? "" :
9913 md->ant.single_pos ? "1Ant_Pos:S1, " : "1Ant_Pos:S0, ");
9914
9915 p += scnprintf(p, end - p,
9916 "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n",
9917 btc->cx.bt_ext.func_type, rtwdev->dbcc_en, hal->tx_nss,
9918 hal->rx_nss);
9919
9920 return p - buf;
9921 }
9922
_show_wl_role_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9923 static int _show_wl_role_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9924 {
9925 struct rtw89_btc *btc = &rtwdev->btc;
9926 struct rtw89_btc_wl_link_info *plink = NULL;
9927 struct rtw89_traffic_stats *t;
9928 char *p = buf, *end = buf + bufsz;
9929 u8 i, j;
9930
9931 for (i = 0; i < btc->ver->max_role_num; i++) {
9932 for (j = 0; j < RTW89_MAC_NUM; j++) {
9933 plink = &btc->cx.wl.rlink_info[i][j];
9934
9935 if (!plink->active)
9936 continue;
9937
9938 p += scnprintf(p, end - p,
9939 " [port_%d] : role=%d(phy-%d), connect=%s(client_cnt=%d), mode=%d, center_ch=%d, bw=%d",
9940 plink->pid, plink->role, plink->phy,
9941 id_to_mlme_state(plink->connected),
9942 plink->client_cnt - 1, plink->mode,
9943 plink->ch, plink->bw);
9944
9945 if (plink->connected == MLME_NO_LINK) {
9946 p += scnprintf(p, end - p, "\n");
9947 continue;
9948 }
9949
9950 p += scnprintf(p, end - p,
9951 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n",
9952 plink->mac_id, plink->tx_time, plink->tx_retry);
9953
9954 p += scnprintf(p, end - p,
9955 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
9956 plink->pid, 110 - plink->stat.rssi,
9957 plink->stat.rssi, plink->busy,
9958 plink->dir == RTW89_TFC_UL ? "UL" : "DL");
9959
9960 t = &plink->stat.traffic;
9961
9962 p += scnprintf(p, end - p,
9963 "tx[rate:%d/busy_level:%d], ",
9964 t->tx_rate, t->tx_tfc_lv);
9965
9966 p += scnprintf(p, end - p,
9967 "rx[rate:%d/busy_level:%d/drop:%d]\n",
9968 t->rx_rate,
9969 t->rx_tfc_lv, plink->rx_rate_drop_cnt);
9970 }
9971 }
9972 return p - buf;
9973 }
9974
_show_wl_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9975 static int _show_wl_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9976 {
9977 struct rtw89_btc *btc = &rtwdev->btc;
9978 struct rtw89_btc_cx *cx = &btc->cx;
9979 struct rtw89_btc_wl_info *wl = &cx->wl;
9980 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
9981 char *p = buf, *end = buf + bufsz;
9982 u8 mode;
9983
9984 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
9985 return 0;
9986
9987 p += scnprintf(p, end - p, "========== [WL Status] ==========\n");
9988
9989 mode = wl_rinfo->link_mode;
9990
9991 p += scnprintf(p, end - p, " %-15s : link_mode:%s, ", "[status]",
9992 id_to_linkmode(mode));
9993
9994 p += scnprintf(p, end - p,
9995 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ",
9996 wl->status.map.rf_off, wl->status.map.lps,
9997 wl->status.map.scan ? "Y" : "N",
9998 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
9999
10000 p += scnprintf(p, end - p,
10001 "handshake:%s, roam:%s, 4way:%s, init_ok:%s\n",
10002 wl->status.map.handshake ? "Y" : "N",
10003 wl->status.map.roaming ? "Y" : "N",
10004 wl->status.map._4way ? "Y" : "N",
10005 wl->status.map.init_ok ? "Y" : "N");
10006
10007 p += _show_wl_role_info(rtwdev, p, end - p);
10008
10009 return p - buf;
10010 }
10011
10012 enum btc_bt_a2dp_type {
10013 BTC_A2DP_LEGACY = 0,
10014 BTC_A2DP_TWS_SNIFF = 1,
10015 BTC_A2DP_TWS_RELAY = 2,
10016 };
10017
_show_bt_profile_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz,u8 bid)10018 static int _show_bt_profile_info(struct rtw89_dev *rtwdev, char *buf,
10019 size_t bufsz, u8 bid)
10020 {
10021 struct rtw89_btc *btc = &rtwdev->btc;
10022 struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ?
10023 &btc->cx.bt0 : &btc->cx.bt1;
10024 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
10025 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
10026 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
10027 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
10028 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
10029 char *p = buf, *end = buf + bufsz;
10030
10031 if (hfp.exist) {
10032 p += scnprintf(p, end - p,
10033 " %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
10034 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"),
10035 bt_linfo->sut_pwr_level[0],
10036 bt_linfo->golden_rx_shift[0]);
10037 }
10038
10039 if (hid.exist) {
10040 p += scnprintf(p, end - p,
10041 "\n %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n",
10042 "[HID]",
10043 hid.type & BTC_HID_218 ? "2/18," : "",
10044 hid.type & BTC_HID_418 ? "4/18," : "",
10045 hid.type & BTC_HID_BLE ? "BLE," : "",
10046 hid.type & BTC_HID_RCU ? "RCU," : "",
10047 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "",
10048 hid.pair_cnt, bt_linfo->sut_pwr_level[1],
10049 bt_linfo->golden_rx_shift[1]);
10050 }
10051
10052 if (a2dp.exist) {
10053 p += scnprintf(p, end - p,
10054 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
10055 "[A2DP]",
10056 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS",
10057 a2dp.bitpool, a2dp.flush_time);
10058
10059 p += scnprintf(p, end - p,
10060 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n",
10061 a2dp.vendor_id, a2dp.device_name,
10062 bt_linfo->sut_pwr_level[2],
10063 bt_linfo->golden_rx_shift[2]);
10064 }
10065
10066 if (pan.exist) {
10067 p += scnprintf(p, end - p,
10068 " %-15s : sut_pwr:%d, golden-rx:%d\n",
10069 "[PAN]",
10070 bt_linfo->sut_pwr_level[3],
10071 bt_linfo->golden_rx_shift[3]);
10072 }
10073
10074 return p - buf;
10075 }
10076
_show_bt_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz,u8 bid)10077 static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz, u8 bid)
10078 {
10079 struct rtw89_btc *btc = &rtwdev->btc;
10080 const struct rtw89_btc_ver *ver = btc->ver;
10081 struct rtw89_btc_cx *cx = &btc->cx;
10082 struct rtw89_btc_bt_info *bt = (bid == BTC_BT_1ST) ? &cx->bt0 : &cx->bt1;
10083 struct rtw89_btc_wl_info *wl = &cx->wl;
10084 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
10085 struct rtw89_btc_module *md = &btc->mdinfo;
10086 u8 bt_pos = (bid == BTC_BT_1ST) ? md->bt0_pos : md->bt1_pos;
10087 s8 br_dbm = bt->link_info.bt_txpwr_desc.br_dbm;
10088 s8 le_dbm = bt->link_info.bt_txpwr_desc.le_dbm;
10089 u8 hw_band = wl->role_info.pta_req_band;
10090 struct rtw89_btc_wl_afh_info *wl_afh;
10091 char *p = buf, *end = buf + bufsz;
10092 u8 *afh = bt_linfo->afh_map;
10093 u8 *afh_le = bt_linfo->afh_map_le;
10094
10095 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
10096 return 0;
10097
10098 if (bid == BTC_BT_2ND) {
10099 if (!(rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT))
10100 return 0;
10101 if (!bt->enable.now)
10102 return 0;
10103 }
10104
10105 p += scnprintf(p, end - p, "========== [BT_%s Status] ==========\n",
10106 bid == BTC_BT_1ST ? "1ST" : "2ND");
10107
10108 p += scnprintf(p, end - p,
10109 " %-15s : enable:%s, btg:%s%s, connect:%s, ",
10110 "[status]", bt->enable.now ? "Y" : "N",
10111 bt->btg_type ? "Y" : "N",
10112 (bt->enable.now && (bt->btg_type != bt_pos) ?
10113 "(efuse-mismatch!!)" : ""),
10114 (bt_linfo->status.map.connect ? "Y" : "N"));
10115
10116 p += scnprintf(p, end - p,
10117 "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n",
10118 bt->igno_wl ? "Y" : "N",
10119 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val);
10120
10121 p += scnprintf(p, end - p, " %-15s : profile:%s%s%s%s%s ",
10122 "[profile]",
10123 (bt_linfo->link_cnt.now == 0) ? "None," : "",
10124 bt_linfo->hfp_desc.exist ? "HFP," : "",
10125 bt_linfo->hid_desc.exist ? "HID," : "",
10126 bt_linfo->a2dp_desc.exist ?
10127 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "",
10128 bt_linfo->pan_desc.exist ? "PAN," : "");
10129
10130 p += scnprintf(p, end - p,
10131 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n",
10132 bt_linfo->multi_link.now ? "Y" : "N",
10133 bt_linfo->slave_role ? "Slave" : "Master",
10134 bt_linfo->status.map.ble_connect ? "Y" : "N",
10135 bt_linfo->cqddr ? "Y" : "N",
10136 bt_linfo->a2dp_desc.active ? "Y" : "N",
10137 bt_linfo->pan_desc.active ? "Y" : "N");
10138
10139 p += scnprintf(p, end - p,
10140 " %-15s : rssi:%ddBm(lvl:%d), tx_rate:%dM, %s%s%s",
10141 "[link]", bt_linfo->rssi - 100,
10142 bt->rssi_level,
10143 bt_linfo->tx_3m ? 3 : 2,
10144 bt_linfo->status.map.inq_pag ? " inq-page!!" : "",
10145 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "",
10146 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : "");
10147
10148 p += scnprintf(p, end - p,
10149 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
10150 bt_linfo->relink.now ? " ReLink!!" : "",
10151 afh[0], afh[1], afh[2], afh[3], afh[4],
10152 afh[5], afh[6], afh[7], afh[8], afh[9]);
10153
10154 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
10155 p += scnprintf(p, end - p,
10156 "LE[%02x%02x_%02x_%02x%02x]",
10157 afh_le[0], afh_le[1], afh_le[2],
10158 afh_le[3], afh_le[4]);
10159
10160 wl_afh = &wl->afh_info[hw_band][RTW89_BAND_2G];
10161 p += scnprintf(p, end - p, "wl_ch_map[hwb:%d/en:%d/ch:%d/bw:%d/rf_band:%d]\n",
10162 hw_band, wl_afh->en, wl_afh->ch, wl_afh->bw, wl_afh->band);
10163
10164 p += scnprintf(p, end - p,
10165 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
10166 "[stat_cnt]", bt->bcnt[BTC_BCNT_RETRY],
10167 bt->bcnt[BTC_BCNT_RELINK],
10168 bt->bcnt[BTC_BCNT_RATECHG],
10169 bt->bcnt[BTC_BCNT_REINIT],
10170 bt->bcnt[BTC_BCNT_REENABLE]);
10171
10172 p += scnprintf(p, end - p,
10173 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n",
10174 bt->bcnt[BTC_BCNT_ROLESW], bt->bcnt[BTC_BCNT_AFH],
10175 bt->bcnt[BTC_BCNT_INQPAG], bt->bcnt[BTC_BCNT_INQ],
10176 bt->bcnt[BTC_BCNT_PAGE], bt->bcnt[BTC_BCNT_IGNOWL]);
10177
10178 p += _show_bt_profile_info(rtwdev, p, end - p, bid);
10179
10180 p += scnprintf(p, end - p,
10181 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n",
10182 "[bt_info]", bt->raw_info[2], bt->raw_info[3],
10183 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6],
10184 bt->raw_info[7],
10185 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
10186 bt->bcnt[BTC_BCNT_INFOUPDATE],
10187 bt->bcnt[BTC_BCNT_INFOSAME]);
10188
10189 p += scnprintf(p, end - p,
10190 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)",
10191 "[trx_req_cnt]", bt->bcnt[BTC_BCNT_HIPRI_RX],
10192 bt->bcnt[BTC_BCNT_HIPRI_TX],
10193 bt->bcnt[BTC_BCNT_LOPRI_RX],
10194 bt->bcnt[BTC_BCNT_LOPRI_TX],
10195 bt->bcnt[BTC_BCNT_POLLUTED]);
10196
10197 if (ver->fcxbtscan == 1) {
10198 p += scnprintf(p, end - p,
10199 "(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)",
10200 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win),
10201 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl),
10202 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win),
10203 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl),
10204 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win),
10205 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl),
10206 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win),
10207 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl));
10208 } else if (ver->fcxbtscan == 2) {
10209 p += scnprintf(p, end - p,
10210 "(BG:%d-%d/INIT:%d-%d/LE:%d-%d)",
10211 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win),
10212 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl),
10213 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win),
10214 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl),
10215 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win),
10216 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl));
10217 }
10218 p += scnprintf(p, end - p, "\n");
10219
10220 if (bt->bcnt[BTC_BCNT_TXPWR_UPDATE]) {
10221 p += scnprintf(p, end - p,
10222 " %-15s : br_index:0x%x, le_index:0x%x",
10223 "[bt_txpwr_lvl]",
10224 bt->link_info.bt_txpwr_desc.br_gain_index,
10225 bt->link_info.bt_txpwr_desc.le_gain_index);
10226 p += scnprintf(p, end - p, ", br_dbm:%d dBm", br_dbm);
10227 p += scnprintf(p, end - p, ", le_dbm:%d dBm", le_dbm);
10228 } else {
10229 p += scnprintf(p, end - p,
10230 " %-15s : br_index:NA, le_index:NA, br_dbm:%d dBm[def], le_dbm:%d dBm[def]",
10231 "[bt_txpwr_lvl]",
10232 bt->link_info.bt_txpwr_desc.br_dbm,
10233 bt->link_info.bt_txpwr_desc.le_dbm);
10234 }
10235 p += scnprintf(p, end - p, "\n");
10236
10237 return p - buf;
10238 }
10239
10240 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e
10241 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
10242 #define CASE_BTC_POLICY_STR(e) \
10243 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
10244 #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e
10245 #define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e
10246 #define CASE_BTC_INIT(e) case BTC_MODE_## e: return #e
10247 #define CASE_BTC_ANTPATH_STR(e) case BTC_ANT_##e: return #e
10248 #define CASE_BTC_POLUT_STR(e) case BTC_PLT_## e: return #e
10249 #define CASE_BTC_REGTYPE_STR(e) case REG_## e: return #e
10250 #define CASE_BTC_GDBG_STR(e) case BTC_DBG_## e: return #e
10251 #define CASE_BTC_H2CCMD(e) case SET_##e: return #e
10252
id_to_polut(u32 id)10253 static const char *id_to_polut(u32 id)
10254 {
10255 switch (id) {
10256 CASE_BTC_POLUT_STR(NONE);
10257 CASE_BTC_POLUT_STR(GNT_BT_TX);
10258 CASE_BTC_POLUT_STR(GNT_BT_RX);
10259 CASE_BTC_POLUT_STR(GNT_WL);
10260 CASE_BTC_POLUT_STR(BT);
10261 CASE_BTC_POLUT_STR(ALL);
10262 default:
10263 return "unknown";
10264 }
10265 }
10266
id_to_regtype(u32 id)10267 static const char *id_to_regtype(u32 id)
10268 {
10269 switch (id) {
10270 CASE_BTC_REGTYPE_STR(MAC);
10271 CASE_BTC_REGTYPE_STR(BB);
10272 CASE_BTC_REGTYPE_STR(RF);
10273 CASE_BTC_REGTYPE_STR(BT_RF);
10274 CASE_BTC_REGTYPE_STR(BT_MODEM);
10275 CASE_BTC_REGTYPE_STR(BT_BLUEWIZE);
10276 CASE_BTC_REGTYPE_STR(BT_VENDOR);
10277 CASE_BTC_REGTYPE_STR(BT_LE);
10278 default:
10279 return "unknown";
10280 }
10281 }
10282
id_to_gdbg(u32 id)10283 static const char *id_to_gdbg(u32 id)
10284 {
10285 switch (id) {
10286 CASE_BTC_GDBG_STR(GNT_BT);
10287 CASE_BTC_GDBG_STR(GNT_WL);
10288 CASE_BTC_GDBG_STR(GNT_BT1);
10289 CASE_BTC_GDBG_STR(GNT_WL1);
10290 CASE_BTC_GDBG_STR(BCN_EARLY);
10291 CASE_BTC_GDBG_STR(WL_NULL0);
10292 CASE_BTC_GDBG_STR(WL_NULL1);
10293 CASE_BTC_GDBG_STR(WL_RXISR);
10294 CASE_BTC_GDBG_STR(TDMA_ENTRY);
10295 CASE_BTC_GDBG_STR(A2DP_EMPTY);
10296 CASE_BTC_GDBG_STR(BT_RETRY);
10297 CASE_BTC_GDBG_STR(BT_RELINK);
10298 CASE_BTC_GDBG_STR(SLOT_WL);
10299 CASE_BTC_GDBG_STR(SLOT_BT);
10300 CASE_BTC_GDBG_STR(WL_ERR);
10301 CASE_BTC_GDBG_STR(WL_OK);
10302 CASE_BTC_GDBG_STR(SLOT_B2W);
10303 CASE_BTC_GDBG_STR(SLOT_W1);
10304 CASE_BTC_GDBG_STR(SLOT_W2);
10305 CASE_BTC_GDBG_STR(SLOT_W2B);
10306 CASE_BTC_GDBG_STR(SLOT_B1);
10307 CASE_BTC_GDBG_STR(SLOT_B2);
10308 CASE_BTC_GDBG_STR(SLOT_B3);
10309 CASE_BTC_GDBG_STR(SLOT_B4);
10310 CASE_BTC_GDBG_STR(SLOT_LK);
10311 CASE_BTC_GDBG_STR(SLOT_E2G);
10312 CASE_BTC_GDBG_STR(SLOT_E5G);
10313 CASE_BTC_GDBG_STR(SLOT_EBT);
10314 CASE_BTC_GDBG_STR(SLOT_WLK);
10315 CASE_BTC_GDBG_STR(SLOT_B1FDD);
10316 CASE_BTC_GDBG_STR(BT_CHANGE);
10317 CASE_BTC_GDBG_STR(WL_CCA);
10318 default:
10319 return "unknown";
10320 }
10321 }
10322
steps_to_str(u16 step)10323 static const char *steps_to_str(u16 step)
10324 {
10325 switch (step) {
10326 CASE_BTC_RSN_STR(NONE);
10327 CASE_BTC_RSN_STR(NTFY_INIT);
10328 CASE_BTC_RSN_STR(NTFY_SWBAND);
10329 CASE_BTC_RSN_STR(NTFY_WL_STA);
10330 CASE_BTC_RSN_STR(NTFY_RADIO_STATE);
10331 CASE_BTC_RSN_STR(UPDATE_BT_SCBD);
10332 CASE_BTC_RSN_STR(NTFY_WL_RFK);
10333 CASE_BTC_RSN_STR(UPDATE_BT_INFO);
10334 CASE_BTC_RSN_STR(NTFY_SCAN_START);
10335 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH);
10336 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET);
10337 CASE_BTC_RSN_STR(NTFY_POWEROFF);
10338 CASE_BTC_RSN_STR(NTFY_ROLE_INFO);
10339 CASE_BTC_RSN_STR(CMD_SET_COEX);
10340 CASE_BTC_RSN_STR(ACT1_WORK);
10341 CASE_BTC_RSN_STR(BT_DEVINFO_WORK);
10342 CASE_BTC_RSN_STR(RFK_CHK_WORK);
10343 CASE_BTC_RSN_STR(UPDATE_BT_LEAUDINFO);
10344
10345 CASE_BTC_ACT_STR(NONE);
10346 CASE_BTC_ACT_STR(WL_ONLY);
10347 CASE_BTC_ACT_STR(WL_5G);
10348 CASE_BTC_ACT_STR(WL_OTHER);
10349 CASE_BTC_ACT_STR(WL_IDLE);
10350 CASE_BTC_ACT_STR(WL_NC);
10351 CASE_BTC_ACT_STR(WL_RFK);
10352 CASE_BTC_ACT_STR(WL_INIT);
10353 CASE_BTC_ACT_STR(WL_OFF);
10354 CASE_BTC_ACT_STR(FREERUN);
10355 CASE_BTC_ACT_STR(BT_WHQL);
10356 CASE_BTC_ACT_STR(BT_RFK);
10357 CASE_BTC_ACT_STR(BT_OFF);
10358 CASE_BTC_ACT_STR(BT_IDLE);
10359 CASE_BTC_ACT_STR(BT_HFP);
10360 CASE_BTC_ACT_STR(BT_HID);
10361 CASE_BTC_ACT_STR(BT_A2DP);
10362 CASE_BTC_ACT_STR(BT_A2DPSINK);
10363 CASE_BTC_ACT_STR(BT_PAN);
10364 CASE_BTC_ACT_STR(BT_A2DP_HID);
10365 CASE_BTC_ACT_STR(BT_A2DP_PAN);
10366 CASE_BTC_ACT_STR(BT_PAN_HID);
10367 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID);
10368 CASE_BTC_ACT_STR(BT_BIS);
10369 CASE_BTC_ACT_STR(BT_CIS);
10370 CASE_BTC_ACT_STR(WL_25G_MCC);
10371 CASE_BTC_ACT_STR(WL_2G_MCC);
10372 CASE_BTC_ACT_STR(WL_2G_SCC);
10373 CASE_BTC_ACT_STR(WL_2G_AP);
10374 CASE_BTC_ACT_STR(WL_2G_GO);
10375 CASE_BTC_ACT_STR(WL_2G_GC);
10376 CASE_BTC_ACT_STR(WL_2G_NAN);
10377
10378 CASE_BTC_POLICY_STR(OFF_BT);
10379 CASE_BTC_POLICY_STR(OFF_WL);
10380 CASE_BTC_POLICY_STR(OFF_EQ0);
10381 CASE_BTC_POLICY_STR(OFF_EQ1);
10382 CASE_BTC_POLICY_STR(OFF_EQ2);
10383 CASE_BTC_POLICY_STR(OFF_EQ3);
10384 CASE_BTC_POLICY_STR(OFF_EQ4);
10385 CASE_BTC_POLICY_STR(OFF_EQ5);
10386 CASE_BTC_POLICY_STR(OFF_BWB0);
10387 CASE_BTC_POLICY_STR(OFF_BWB1);
10388 CASE_BTC_POLICY_STR(OFF_BWB2);
10389 CASE_BTC_POLICY_STR(OFF_BWB3);
10390 CASE_BTC_POLICY_STR(OFF_WL2);
10391 CASE_BTC_POLICY_STR(OFFB_BWB0);
10392 CASE_BTC_POLICY_STR(OFFE_DEF);
10393 CASE_BTC_POLICY_STR(OFFE_DEF2);
10394 CASE_BTC_POLICY_STR(OFFE_2GBWISOB);
10395 CASE_BTC_POLICY_STR(OFFE_2GISOB);
10396 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB);
10397 CASE_BTC_POLICY_STR(OFFE_WL);
10398 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2);
10399 CASE_BTC_POLICY_STR(FIX_TD3030);
10400 CASE_BTC_POLICY_STR(FIX_TD5050);
10401 CASE_BTC_POLICY_STR(FIX_TD2030);
10402 CASE_BTC_POLICY_STR(FIX_TD4010);
10403 CASE_BTC_POLICY_STR(FIX_TD7010);
10404 CASE_BTC_POLICY_STR(FIX_TD2060);
10405 CASE_BTC_POLICY_STR(FIX_TD3060);
10406 CASE_BTC_POLICY_STR(FIX_TD2080);
10407 CASE_BTC_POLICY_STR(FIX_TDW1B1);
10408 CASE_BTC_POLICY_STR(FIX_TD4010ISO);
10409 CASE_BTC_POLICY_STR(FIX_TD4010ISO_DL);
10410 CASE_BTC_POLICY_STR(FIX_TD4010ISO_UL);
10411 CASE_BTC_POLICY_STR(PFIX_TD3030);
10412 CASE_BTC_POLICY_STR(PFIX_TD5050);
10413 CASE_BTC_POLICY_STR(PFIX_TD2030);
10414 CASE_BTC_POLICY_STR(PFIX_TD2060);
10415 CASE_BTC_POLICY_STR(PFIX_TD3070);
10416 CASE_BTC_POLICY_STR(PFIX_TD2080);
10417 CASE_BTC_POLICY_STR(PFIX_TDW1B1);
10418 CASE_BTC_POLICY_STR(AUTO_TD50B1);
10419 CASE_BTC_POLICY_STR(AUTO_TD60B1);
10420 CASE_BTC_POLICY_STR(AUTO_TD20B1);
10421 CASE_BTC_POLICY_STR(AUTO_TDW1B1);
10422 CASE_BTC_POLICY_STR(PAUTO_TD50B1);
10423 CASE_BTC_POLICY_STR(PAUTO_TD60B1);
10424 CASE_BTC_POLICY_STR(PAUTO_TD20B1);
10425 CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
10426 CASE_BTC_POLICY_STR(AUTO2_TD3050);
10427 CASE_BTC_POLICY_STR(AUTO2_TD3070);
10428 CASE_BTC_POLICY_STR(AUTO2_TD5050);
10429 CASE_BTC_POLICY_STR(AUTO2_TD6060);
10430 CASE_BTC_POLICY_STR(AUTO2_TD2080);
10431 CASE_BTC_POLICY_STR(AUTO2_TDW1B4);
10432 CASE_BTC_POLICY_STR(PAUTO2_TD3050);
10433 CASE_BTC_POLICY_STR(PAUTO2_TD3070);
10434 CASE_BTC_POLICY_STR(PAUTO2_TD5050);
10435 CASE_BTC_POLICY_STR(PAUTO2_TD6060);
10436 CASE_BTC_POLICY_STR(PAUTO2_TD2080);
10437 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4);
10438 default:
10439 return "unknown step";
10440 }
10441 }
10442
id_to_slot(u32 id)10443 static const char *id_to_slot(u32 id)
10444 {
10445 switch (id) {
10446 CASE_BTC_SLOT_STR(OFF);
10447 CASE_BTC_SLOT_STR(B2W);
10448 CASE_BTC_SLOT_STR(W1);
10449 CASE_BTC_SLOT_STR(W2);
10450 CASE_BTC_SLOT_STR(W2B);
10451 CASE_BTC_SLOT_STR(B1);
10452 CASE_BTC_SLOT_STR(B2);
10453 CASE_BTC_SLOT_STR(B3);
10454 CASE_BTC_SLOT_STR(B4);
10455 CASE_BTC_SLOT_STR(LK);
10456 CASE_BTC_SLOT_STR(BLK);
10457 CASE_BTC_SLOT_STR(E2G);
10458 CASE_BTC_SLOT_STR(E5G);
10459 CASE_BTC_SLOT_STR(EBT);
10460 CASE_BTC_SLOT_STR(ENULL);
10461 CASE_BTC_SLOT_STR(WLK);
10462 CASE_BTC_SLOT_STR(W1FDD);
10463 CASE_BTC_SLOT_STR(B1FDD);
10464 default:
10465 return "unknown";
10466 }
10467 }
10468
id_to_evt(u32 id)10469 static const char *id_to_evt(u32 id)
10470 {
10471 switch (id) {
10472 CASE_BTC_EVT_STR(TDMA_ENTRY);
10473 CASE_BTC_EVT_STR(WL_TMR);
10474 CASE_BTC_EVT_STR(B1_TMR);
10475 CASE_BTC_EVT_STR(B2_TMR);
10476 CASE_BTC_EVT_STR(B3_TMR);
10477 CASE_BTC_EVT_STR(B4_TMR);
10478 CASE_BTC_EVT_STR(W2B_TMR);
10479 CASE_BTC_EVT_STR(B2W_TMR);
10480 CASE_BTC_EVT_STR(BCN_EARLY);
10481 CASE_BTC_EVT_STR(A2DP_EMPTY);
10482 CASE_BTC_EVT_STR(LK_END);
10483 CASE_BTC_EVT_STR(RX_ISR);
10484 CASE_BTC_EVT_STR(RX_FC0);
10485 CASE_BTC_EVT_STR(RX_FC1);
10486 CASE_BTC_EVT_STR(BT_RELINK);
10487 CASE_BTC_EVT_STR(BT_RETRY);
10488 CASE_BTC_EVT_STR(E2G);
10489 CASE_BTC_EVT_STR(E5G);
10490 CASE_BTC_EVT_STR(EBT);
10491 CASE_BTC_EVT_STR(ENULL);
10492 CASE_BTC_EVT_STR(DRV_WLK);
10493 CASE_BTC_EVT_STR(BCN_OK);
10494 CASE_BTC_EVT_STR(BT_CHANGE);
10495 CASE_BTC_EVT_STR(EBT_EXTEND);
10496 CASE_BTC_EVT_STR(E2G_NULL1);
10497 CASE_BTC_EVT_STR(B1FDD_TMR);
10498 default:
10499 return "unknown";
10500 }
10501 }
10502
id_to_mode(u8 id)10503 static const char *id_to_mode(u8 id)
10504 {
10505 switch (id) {
10506 CASE_BTC_INIT(NORMAL);
10507 CASE_BTC_INIT(WL);
10508 CASE_BTC_INIT(BT);
10509 CASE_BTC_INIT(WLOFF);
10510 default:
10511 return "unknown";
10512 }
10513 }
10514
id_to_ant(u32 id)10515 static const char *id_to_ant(u32 id)
10516 {
10517 switch (id) {
10518 CASE_BTC_ANTPATH_STR(WPOWERON);
10519 CASE_BTC_ANTPATH_STR(WINIT);
10520 CASE_BTC_ANTPATH_STR(WONLY);
10521 CASE_BTC_ANTPATH_STR(WOFF);
10522 CASE_BTC_ANTPATH_STR(W2G);
10523 CASE_BTC_ANTPATH_STR(FDD);
10524 CASE_BTC_ANTPATH_STR(W25G);
10525 CASE_BTC_ANTPATH_STR(FREERUN);
10526 CASE_BTC_ANTPATH_STR(WRFK);
10527 CASE_BTC_ANTPATH_STR(WRFK2);
10528 CASE_BTC_ANTPATH_STR(PTA);
10529 CASE_BTC_ANTPATH_STR(MAX);
10530 default:
10531 return "unknown";
10532 }
10533 }
10534
id_to_h2c(u32 id)10535 static const char *id_to_h2c(u32 id)
10536 {
10537 switch (id) {
10538 CASE_BTC_H2CCMD(REPORT_EN);
10539 CASE_BTC_H2CCMD(SLOT_TABLE);
10540 CASE_BTC_H2CCMD(MREG_TABLE);
10541 CASE_BTC_H2CCMD(CX_POLICY);
10542 CASE_BTC_H2CCMD(GPIO_DBG);
10543 CASE_BTC_H2CCMD(DRV_INFO);
10544 CASE_BTC_H2CCMD(DRV_EVENT);
10545 CASE_BTC_H2CCMD(BT_WREG_ADDR);
10546 CASE_BTC_H2CCMD(BT_WREG_VAL);
10547 CASE_BTC_H2CCMD(BT_RREG_ADDR);
10548 CASE_BTC_H2CCMD(BT_WL_CH_INFO);
10549 CASE_BTC_H2CCMD(BT_INFO_REPORT);
10550 CASE_BTC_H2CCMD(BT_IGNORE_WLAN_ACT);
10551 CASE_BTC_H2CCMD(BT_TX_PWR);
10552 CASE_BTC_H2CCMD(BT_LNA_CONSTRAIN);
10553 CASE_BTC_H2CCMD(BT_QUERY_DEV_LIST);
10554 CASE_BTC_H2CCMD(BT_QUERY_DEV_INFO);
10555 CASE_BTC_H2CCMD(BT_PSD_REPORT);
10556 CASE_BTC_H2CCMD(H2C_TEST);
10557 CASE_BTC_H2CCMD(IOFLD_RF);
10558 CASE_BTC_H2CCMD(IOFLD_BB);
10559 CASE_BTC_H2CCMD(IOFLD_MAC);
10560 CASE_BTC_H2CCMD(IOFLD_SCBD);
10561 CASE_BTC_H2CCMD(H2C_MACRO);
10562 default:
10563 return "unknown";
10564 }
10565 }
10566
10567 static
scnprintf_segment(char * buf,size_t bufsz,const char * prefix,const u16 * data,u8 len,u8 seg_len,u8 start_idx,u8 ring_len)10568 int scnprintf_segment(char *buf, size_t bufsz, const char *prefix, const u16 *data,
10569 u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
10570 {
10571 char *p = buf, *end = buf + bufsz;
10572 u8 cur_index;
10573 u8 i;
10574
10575 for (i = 0; i < len ; i++) {
10576 if ((i % seg_len) == 0)
10577 p += scnprintf(p, end - p, " %-15s : ", prefix);
10578 cur_index = (start_idx + i) % ring_len;
10579 if (i % 3 == 0)
10580 p += scnprintf(p, end - p, "-> %-20s",
10581 steps_to_str(*(data + cur_index)));
10582 else if (i % 3 == 1)
10583 p += scnprintf(p, end - p, "-> %-15s",
10584 steps_to_str(*(data + cur_index)));
10585 else
10586 p += scnprintf(p, end - p, "-> %-13s",
10587 steps_to_str(*(data + cur_index)));
10588 if (i == (len - 1) || (i % seg_len) == (seg_len - 1))
10589 p += scnprintf(p, end - p, "\n");
10590 }
10591
10592 return p - buf;
10593 }
10594
_show_dm_step(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10595 static int _show_dm_step(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10596 {
10597 struct rtw89_btc *btc = &rtwdev->btc;
10598 struct rtw89_btc_dm *dm = &btc->dm;
10599 char *p = buf, *end = buf + bufsz;
10600 u8 start_idx;
10601 u8 len;
10602
10603 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos;
10604 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0;
10605
10606 p += scnprintf_segment(p, end - p, "[dm_steps]", dm->dm_step.step, len,
10607 6, start_idx, ARRAY_SIZE(dm->dm_step.step));
10608
10609 return p - buf;
10610 }
10611
_show_dm_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10612 static int _show_dm_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10613 {
10614 struct rtw89_btc *btc = &rtwdev->btc;
10615 struct rtw89_btc_dm *dm = &btc->dm;
10616 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
10617 struct rtw89_btc_bt_info *bt = &btc->cx.bt0;
10618 char *p = buf, *end = buf + bufsz;
10619
10620 if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
10621 return 0;
10622
10623 p += scnprintf(p, end - p,
10624 "========== [Mechanism Status %s] ==========\n",
10625 (btc->manual_ctrl ? "(Manual)" : "(Auto)"));
10626
10627 p += scnprintf(p, end - p,
10628 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, init_mode:%s, run_cnt:%d\n",
10629 "[status]",
10630 btc->ant_type == BTC_ANT_SHARED ? "shared" : "dedicated",
10631 steps_to_str(dm->run_reason),
10632 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT),
10633 id_to_ant(FIELD_GET(GENMASK(7, 0), dm->set_ant_path)),
10634 id_to_mode(wl->coex_mode),
10635 dm->cnt_dm[BTC_DCNT_RUN]);
10636
10637 p += _show_dm_step(rtwdev, p, end - p);
10638
10639 p += scnprintf(p, end - p,
10640 " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ",
10641 "[dm_flag]", dm->wl_only, dm->bt_only, btc->ctrl.igno_bt,
10642 dm->freerun, btc->btc_ctrl_lps, dm->wl_mimo_ps);
10643
10644 p += scnprintf(p, end - p, "leak_ap:%d, fw_offload:%s%s\n",
10645 dm->leak_ap,
10646 (BTC_CX_FW_OFFLOAD ? "Y" : "N"),
10647 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
10648 "" : "(Mismatch!!)"));
10649
10650 p += scnprintf(p, end - p,
10651 " %-15s : wl[rssi_lvl:%d/para:%d/tx_pwr:[%d %d]/rx_lvl:[%d %d]/lna2:%d/stb_chg:%d]\n",
10652 "[dm_rf_ctrl]",
10653 wl->rssi_level, dm->trx_para_level,
10654 dm->rf_trx_para.wl_tx_power[RTW89_PHY_0],
10655 dm->rf_trx_para.wl_tx_power[RTW89_PHY_1],
10656 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_0],
10657 dm->rf_trx_para.wl_rx_gain[RTW89_PHY_1],
10658 dm->wl_lna2, dm->wl_stb_chg);
10659
10660 p += scnprintf(p, end - p,
10661 " %-15s : pre_agc:%d, btg_rx:%d\n",
10662 "[dm_bb_ctrl]", dm->wl_pre_agc, dm->wl_btg_rx);
10663
10664 p += scnprintf(p, end - p,
10665 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n",
10666 "[dm_ctrl]", dm->wl_tx_limit.enable,
10667 dm->wl_tx_limit.tx_time,
10668 dm->wl_tx_limit.tx_retry, btc->bt_req_len[RTW89_PHY_0],
10669 bt->scan_rx_low_pri);
10670
10671 return p - buf;
10672 }
10673
_show_error(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10674 static int _show_error(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10675 {
10676 struct rtw89_btc *btc = &rtwdev->btc;
10677 const struct rtw89_btc_ver *ver = btc->ver;
10678 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10679 union rtw89_btc_fbtc_cysta_info *pcysta;
10680 char *p = buf, *end = buf + bufsz;
10681 u32 except_cnt, exception_map;
10682
10683 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
10684 if (ver->fcxcysta == 2) {
10685 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
10686 except_cnt = le32_to_cpu(pcysta->v2.except_cnt);
10687 exception_map = le32_to_cpu(pcysta->v2.exception);
10688 } else if (ver->fcxcysta == 3) {
10689 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
10690 except_cnt = le32_to_cpu(pcysta->v3.except_cnt);
10691 exception_map = le32_to_cpu(pcysta->v3.except_map);
10692 } else if (ver->fcxcysta == 4) {
10693 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
10694 except_cnt = pcysta->v4.except_cnt;
10695 exception_map = le32_to_cpu(pcysta->v4.except_map);
10696 } else if (ver->fcxcysta == 5) {
10697 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
10698 except_cnt = pcysta->v5.except_cnt;
10699 exception_map = le32_to_cpu(pcysta->v5.except_map);
10700 } else if (ver->fcxcysta == 7) {
10701 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
10702 except_cnt = pcysta->v7.except_cnt;
10703 exception_map = le32_to_cpu(pcysta->v7.except_map);
10704 } else {
10705 return 0;
10706 }
10707
10708 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 &&
10709 !pfwinfo->len_mismch && !pfwinfo->fver_mismch)
10710 return 0;
10711
10712 p += scnprintf(p, end - p, " %-15s : ", "[error]");
10713
10714 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
10715 p += scnprintf(p, end - p,
10716 "overflow-cnt: %d, ",
10717 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
10718 }
10719
10720 if (pfwinfo->len_mismch) {
10721 p += scnprintf(p, end - p,
10722 "len-mismatch: 0x%x, ",
10723 pfwinfo->len_mismch);
10724 }
10725
10726 if (pfwinfo->fver_mismch) {
10727 p += scnprintf(p, end - p,
10728 "fver-mismatch: 0x%x, ",
10729 pfwinfo->fver_mismch);
10730 }
10731
10732 /* cycle statistics exceptions */
10733 if (exception_map || except_cnt) {
10734 p += scnprintf(p, end - p,
10735 "exception-type: 0x%x, exception-cnt = %d",
10736 exception_map, except_cnt);
10737 }
10738 p += scnprintf(p, end - p, "\n");
10739
10740 return p - buf;
10741 }
10742
_show_fbtc_tdma(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10743 static int _show_fbtc_tdma(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10744 {
10745 struct rtw89_btc *btc = &rtwdev->btc;
10746 const struct rtw89_btc_ver *ver = btc->ver;
10747 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10748 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10749 struct rtw89_btc_fbtc_tdma *t = NULL;
10750 char *p = buf, *end = buf + bufsz;
10751
10752 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
10753 if (!pcinfo->valid)
10754 return 0;
10755
10756 if (ver->fcxtdma == 1)
10757 t = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
10758 else
10759 t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma;
10760
10761 p += scnprintf(p, end - p,
10762 " %-15s : ", "[tdma_policy]");
10763 p += scnprintf(p, end - p,
10764 "type:%d, rx_flow_ctrl:%d, txflctrl:%d, ",
10765 (u32)t->type,
10766 t->rxflctrl, t->txflctrl);
10767
10768 p += scnprintf(p, end - p,
10769 "bind:%d, leak_n:%d, ext_ctrl:%d, ",
10770 t->bind, t->leak_n, t->ext_ctrl);
10771
10772 p += scnprintf(p, end - p,
10773 "policy_type:%d\n",
10774 (u32)btc->policy_type);
10775
10776 return p - buf;
10777 }
10778
_show_fbtc_slots(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10779 static int _show_fbtc_slots(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10780 {
10781 struct rtw89_btc *btc = &rtwdev->btc;
10782 const struct rtw89_btc_ver *ver = btc->ver;
10783 struct rtw89_btc_dm *dm = &btc->dm;
10784 char *p = buf, *end = buf + bufsz;
10785 u16 dur, cxtype;
10786 u32 tbl;
10787 u8 i = 0;
10788
10789 for (i = 0; i < CXST_MAX; i++) {
10790 if (ver->fcxslots == 1) {
10791 dur = le16_to_cpu(dm->slot_now.v1[i].dur);
10792 tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl);
10793 cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype);
10794 } else if (ver->fcxslots == 2 || ver->fcxslots == 7) {
10795 dur = le16_to_cpu(dm->slot_now.v7[i].dur);
10796 tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl);
10797 cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype);
10798 } else {
10799 return 0;
10800 }
10801
10802 if (i % 5 == 0)
10803 p += scnprintf(p, end - p,
10804 " %-15s : %5s[%03d/0x%x/%d]",
10805 "[slot_list]",
10806 id_to_slot((u32)i),
10807 dur, tbl, cxtype);
10808 else
10809 p += scnprintf(p, end - p,
10810 ", %5s[%03d/0x%x/%d]",
10811 id_to_slot((u32)i),
10812 dur, tbl, cxtype);
10813
10814 if (i % 5 == 4)
10815 p += scnprintf(p, end - p, "\n");
10816 }
10817
10818 return p - buf;
10819 }
10820
_show_fbtc_cysta_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10821 static int _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10822 {
10823 struct rtw89_btc *btc = &rtwdev->btc;
10824 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10825 struct rtw89_btc_dm *dm = &btc->dm;
10826 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc;
10827 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10828 struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL;
10829 union rtw89_btc_fbtc_rxflct r;
10830 u16 cycle, c_begin, c_end, store_index;
10831 char *p = buf, *end = buf + bufsz;
10832 u8 i, cnt = 0, slot_pair;
10833
10834 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10835 if (!pcinfo->valid)
10836 return 0;
10837
10838 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
10839 p += scnprintf(p, end - p,
10840 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
10841 "[cycle_cnt]",
10842 le16_to_cpu(pcysta_le32->cycles),
10843 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]),
10844 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]),
10845 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]),
10846 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK]));
10847
10848 for (i = 0; i < CXST_MAX; i++) {
10849 if (!le32_to_cpu(pcysta_le32->slot_cnt[i]))
10850 continue;
10851 p += scnprintf(p, end - p, ", %s:%d", id_to_slot((u32)i),
10852 le32_to_cpu(pcysta_le32->slot_cnt[i]));
10853 }
10854
10855 if (dm->tdma_now.rxflctrl) {
10856 p += scnprintf(p, end - p, ", leak_rx:%d",
10857 le32_to_cpu(pcysta_le32->leakrx_cnt));
10858 }
10859
10860 if (le32_to_cpu(pcysta_le32->collision_cnt)) {
10861 p += scnprintf(p, end - p, ", collision:%d",
10862 le32_to_cpu(pcysta_le32->collision_cnt));
10863 }
10864
10865 if (le32_to_cpu(pcysta_le32->skip_cnt)) {
10866 p += scnprintf(p, end - p, ", skip:%d",
10867 le32_to_cpu(pcysta_le32->skip_cnt));
10868 }
10869 p += scnprintf(p, end - p, "\n");
10870
10871 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
10872 "[cycle_time]",
10873 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]),
10874 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]),
10875 le16_to_cpu(pcysta_le32->tavg_lk) / 1000,
10876 le16_to_cpu(pcysta_le32->tavg_lk) % 1000);
10877 p += scnprintf(p, end - p, ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
10878 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]),
10879 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]),
10880 le16_to_cpu(pcysta_le32->tmax_lk) / 1000,
10881 le16_to_cpu(pcysta_le32->tmax_lk) % 1000);
10882 p += scnprintf(p, end - p, ", maxdiff_t[wl:%d/bt:%d]\n",
10883 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]),
10884 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT]));
10885
10886 if (le16_to_cpu(pcysta_le32->cycles) <= 1)
10887 goto out;
10888
10889 /* 1 cycle record 1 wl-slot and 1 bt-slot */
10890 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10891
10892 if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair)
10893 c_begin = 1;
10894 else
10895 c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1;
10896
10897 c_end = le16_to_cpu(pcysta_le32->cycles);
10898
10899 for (cycle = c_begin; cycle <= c_end; cycle++) {
10900 cnt++;
10901 store_index = ((cycle - 1) % slot_pair) * 2;
10902
10903 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1)
10904 p += scnprintf(p, end - p,
10905 " %-15s : ->b%02d->w%02d",
10906 "[cycle_step]",
10907 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
10908 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
10909 else
10910 p += scnprintf(p, end - p,
10911 "->b%02d->w%02d",
10912 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
10913 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
10914 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
10915 p += scnprintf(p, end - p, "\n");
10916 }
10917
10918 if (a2dp->exist) {
10919 p += scnprintf(p, end - p,
10920 " %-15s : a2dp_ept:%d, a2dp_late:%d",
10921 "[a2dp_t_sta]",
10922 le16_to_cpu(pcysta_le32->a2dpept),
10923 le16_to_cpu(pcysta_le32->a2dpeptto));
10924
10925 p += scnprintf(p, end - p,
10926 ", avg_t:%d, max_t:%d",
10927 le16_to_cpu(pcysta_le32->tavg_a2dpept),
10928 le16_to_cpu(pcysta_le32->tmax_a2dpept));
10929 r.val = dm->tdma_now.rxflctrl;
10930
10931 if (r.type && r.tgln_n) {
10932 p += scnprintf(p, end - p,
10933 ", cycle[PSTDMA:%d/TDMA:%d], ",
10934 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]),
10935 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF]));
10936
10937 p += scnprintf(p, end - p,
10938 "avg_t[PSTDMA:%d/TDMA:%d], ",
10939 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]),
10940 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF]));
10941
10942 p += scnprintf(p, end - p,
10943 "max_t[PSTDMA:%d/TDMA:%d]",
10944 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]),
10945 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF]));
10946 }
10947 p += scnprintf(p, end - p, "\n");
10948 }
10949
10950 out:
10951 return p - buf;
10952 }
10953
_show_fbtc_cysta_v3(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10954 static int _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10955 {
10956 struct rtw89_btc *btc = &rtwdev->btc;
10957 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc;
10958 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10959 struct rtw89_btc_dm *dm = &btc->dm;
10960 struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx;
10961 struct rtw89_btc_fbtc_cysta_v3 *pcysta;
10962 struct rtw89_btc_rpt_cmn_info *pcinfo;
10963 u8 i, cnt = 0, slot_pair, divide_cnt;
10964 u16 cycle, c_begin, c_end, store_index;
10965 char *p = buf, *end = buf + bufsz;
10966
10967 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10968 if (!pcinfo->valid)
10969 return 0;
10970
10971 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
10972 p += scnprintf(p, end - p,
10973 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
10974 "[cycle_cnt]",
10975 le16_to_cpu(pcysta->cycles),
10976 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
10977 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
10978 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
10979 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
10980
10981 for (i = 0; i < CXST_MAX; i++) {
10982 if (!le32_to_cpu(pcysta->slot_cnt[i]))
10983 continue;
10984
10985 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
10986 le32_to_cpu(pcysta->slot_cnt[i]));
10987 }
10988
10989 if (dm->tdma_now.rxflctrl)
10990 p += scnprintf(p, end - p, ", leak_rx:%d",
10991 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
10992
10993 if (le32_to_cpu(pcysta->collision_cnt))
10994 p += scnprintf(p, end - p, ", collision:%d",
10995 le32_to_cpu(pcysta->collision_cnt));
10996
10997 if (le32_to_cpu(pcysta->skip_cnt))
10998 p += scnprintf(p, end - p, ", skip:%d",
10999 le32_to_cpu(pcysta->skip_cnt));
11000
11001 p += scnprintf(p, end - p, "\n");
11002
11003 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
11004 "[cycle_time]",
11005 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
11006 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
11007 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
11008 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
11009 p += scnprintf(p, end - p,
11010 ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
11011 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
11012 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
11013 le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
11014 le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
11015 p += scnprintf(p, end - p,
11016 ", maxdiff_t[wl:%d/bt:%d]\n",
11017 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
11018 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
11019
11020 cycle = le16_to_cpu(pcysta->cycles);
11021 if (cycle <= 1)
11022 goto out;
11023
11024 /* 1 cycle record 1 wl-slot and 1 bt-slot */
11025 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
11026
11027 if (cycle <= slot_pair)
11028 c_begin = 1;
11029 else
11030 c_begin = cycle - slot_pair + 1;
11031
11032 c_end = cycle;
11033
11034 if (a2dp->exist)
11035 divide_cnt = 3;
11036 else
11037 divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
11038
11039 for (cycle = c_begin; cycle <= c_end; cycle++) {
11040 cnt++;
11041 store_index = ((cycle - 1) % slot_pair) * 2;
11042
11043 if (cnt % divide_cnt == 1)
11044 p += scnprintf(p, end - p, " %-15s : ",
11045 "[cycle_step]");
11046
11047 p += scnprintf(p, end - p, "->b%02d",
11048 le16_to_cpu(pcysta->slot_step_time[store_index]));
11049 if (a2dp->exist) {
11050 a2dp_trx = &pcysta->a2dp_trx[store_index];
11051 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11052 a2dp_trx->empty_cnt,
11053 a2dp_trx->retry_cnt,
11054 a2dp_trx->tx_rate ? 3 : 2,
11055 a2dp_trx->tx_cnt,
11056 a2dp_trx->ack_cnt,
11057 a2dp_trx->nack_cnt);
11058 }
11059 p += scnprintf(p, end - p, "->w%02d",
11060 le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
11061 if (a2dp->exist) {
11062 a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
11063 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11064 a2dp_trx->empty_cnt,
11065 a2dp_trx->retry_cnt,
11066 a2dp_trx->tx_rate ? 3 : 2,
11067 a2dp_trx->tx_cnt,
11068 a2dp_trx->ack_cnt,
11069 a2dp_trx->nack_cnt);
11070 }
11071 if (cnt % divide_cnt == 0 || cnt == c_end)
11072 p += scnprintf(p, end - p, "\n");
11073 }
11074
11075 if (a2dp->exist) {
11076 p += scnprintf(p, end - p,
11077 " %-15s : a2dp_ept:%d, a2dp_late:%d",
11078 "[a2dp_t_sta]",
11079 le16_to_cpu(pcysta->a2dp_ept.cnt),
11080 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
11081
11082 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n",
11083 le16_to_cpu(pcysta->a2dp_ept.tavg),
11084 le16_to_cpu(pcysta->a2dp_ept.tmax));
11085 }
11086
11087 out:
11088 return p - buf;
11089 }
11090
_show_fbtc_cysta_v4(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11091 static int _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11092 {
11093 struct rtw89_btc *btc = &rtwdev->btc;
11094 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc;
11095 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11096 struct rtw89_btc_dm *dm = &btc->dm;
11097 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
11098 struct rtw89_btc_fbtc_cysta_v4 *pcysta;
11099 struct rtw89_btc_rpt_cmn_info *pcinfo;
11100 u8 i, cnt = 0, slot_pair, divide_cnt;
11101 u16 cycle, c_begin, c_end, store_index;
11102 char *p = buf, *end = buf + bufsz;
11103
11104 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
11105 if (!pcinfo->valid)
11106 return 0;
11107
11108 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
11109 p += scnprintf(p, end - p,
11110 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
11111 "[cycle_cnt]",
11112 le16_to_cpu(pcysta->cycles),
11113 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
11114 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
11115 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
11116 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
11117
11118 for (i = 0; i < CXST_MAX; i++) {
11119 if (!le16_to_cpu(pcysta->slot_cnt[i]))
11120 continue;
11121
11122 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
11123 le16_to_cpu(pcysta->slot_cnt[i]));
11124 }
11125
11126 if (dm->tdma_now.rxflctrl)
11127 p += scnprintf(p, end - p, ", leak_rx:%d",
11128 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
11129
11130 if (pcysta->collision_cnt)
11131 p += scnprintf(p, end - p, ", collision:%d",
11132 pcysta->collision_cnt);
11133
11134 if (le16_to_cpu(pcysta->skip_cnt))
11135 p += scnprintf(p, end - p, ", skip:%d",
11136 le16_to_cpu(pcysta->skip_cnt));
11137
11138 p += scnprintf(p, end - p, "\n");
11139
11140 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
11141 "[cycle_time]",
11142 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
11143 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
11144 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
11145 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
11146 p += scnprintf(p, end - p,
11147 ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
11148 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
11149 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
11150 le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
11151 le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
11152 p += scnprintf(p, end - p,
11153 ", maxdiff_t[wl:%d/bt:%d]\n",
11154 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
11155 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
11156
11157 cycle = le16_to_cpu(pcysta->cycles);
11158 if (cycle <= 1)
11159 goto out;
11160
11161 /* 1 cycle record 1 wl-slot and 1 bt-slot */
11162 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
11163
11164 if (cycle <= slot_pair)
11165 c_begin = 1;
11166 else
11167 c_begin = cycle - slot_pair + 1;
11168
11169 c_end = cycle;
11170
11171 if (a2dp->exist)
11172 divide_cnt = 3;
11173 else
11174 divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
11175
11176 for (cycle = c_begin; cycle <= c_end; cycle++) {
11177 cnt++;
11178 store_index = ((cycle - 1) % slot_pair) * 2;
11179
11180 if (cnt % divide_cnt == 1)
11181 p += scnprintf(p, end - p, " %-15s : ",
11182 "[cycle_step]");
11183
11184 p += scnprintf(p, end - p, "->b%02d",
11185 le16_to_cpu(pcysta->slot_step_time[store_index]));
11186 if (a2dp->exist) {
11187 a2dp_trx = &pcysta->a2dp_trx[store_index];
11188 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11189 a2dp_trx->empty_cnt,
11190 a2dp_trx->retry_cnt,
11191 a2dp_trx->tx_rate ? 3 : 2,
11192 a2dp_trx->tx_cnt,
11193 a2dp_trx->ack_cnt,
11194 a2dp_trx->nack_cnt);
11195 }
11196 p += scnprintf(p, end - p, "->w%02d",
11197 le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
11198 if (a2dp->exist) {
11199 a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
11200 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11201 a2dp_trx->empty_cnt,
11202 a2dp_trx->retry_cnt,
11203 a2dp_trx->tx_rate ? 3 : 2,
11204 a2dp_trx->tx_cnt,
11205 a2dp_trx->ack_cnt,
11206 a2dp_trx->nack_cnt);
11207 }
11208 if (cnt % divide_cnt == 0 || cnt == c_end)
11209 p += scnprintf(p, end - p, "\n");
11210 }
11211
11212 if (a2dp->exist) {
11213 p += scnprintf(p, end - p,
11214 " %-15s : a2dp_ept:%d, a2dp_late:%d",
11215 "[a2dp_t_sta]",
11216 le16_to_cpu(pcysta->a2dp_ept.cnt),
11217 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
11218
11219 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n",
11220 le16_to_cpu(pcysta->a2dp_ept.tavg),
11221 le16_to_cpu(pcysta->a2dp_ept.tmax));
11222 }
11223
11224 out:
11225 return p - buf;
11226 }
11227
_show_fbtc_cysta_v5(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11228 static int _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11229 {
11230 struct rtw89_btc *btc = &rtwdev->btc;
11231 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc;
11232 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11233 struct rtw89_btc_dm *dm = &btc->dm;
11234 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
11235 struct rtw89_btc_fbtc_cysta_v5 *pcysta;
11236 struct rtw89_btc_rpt_cmn_info *pcinfo;
11237 u8 i, cnt = 0, slot_pair, divide_cnt;
11238 u16 cycle, c_begin, c_end, store_index;
11239 char *p = buf, *end = buf + bufsz;
11240
11241 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
11242 if (!pcinfo->valid)
11243 return 0;
11244
11245 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
11246 p += scnprintf(p, end - p,
11247 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
11248 "[cycle_cnt]",
11249 le16_to_cpu(pcysta->cycles),
11250 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
11251 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
11252 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
11253 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
11254
11255 for (i = 0; i < CXST_MAX; i++) {
11256 if (!le16_to_cpu(pcysta->slot_cnt[i]))
11257 continue;
11258
11259 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
11260 le16_to_cpu(pcysta->slot_cnt[i]));
11261 }
11262
11263 if (dm->tdma_now.rxflctrl)
11264 p += scnprintf(p, end - p, ", leak_rx:%d",
11265 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
11266
11267 if (pcysta->collision_cnt)
11268 p += scnprintf(p, end - p, ", collision:%d",
11269 pcysta->collision_cnt);
11270
11271 if (le16_to_cpu(pcysta->skip_cnt))
11272 p += scnprintf(p, end - p, ", skip:%d",
11273 le16_to_cpu(pcysta->skip_cnt));
11274
11275 p += scnprintf(p, end - p, "\n");
11276
11277 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
11278 "[cycle_time]",
11279 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
11280 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
11281 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
11282 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
11283 p += scnprintf(p, end - p,
11284 ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n",
11285 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
11286 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
11287 le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
11288 le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
11289
11290 cycle = le16_to_cpu(pcysta->cycles);
11291 if (cycle <= 1)
11292 goto out;
11293
11294 /* 1 cycle record 1 wl-slot and 1 bt-slot */
11295 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
11296
11297 if (cycle <= slot_pair)
11298 c_begin = 1;
11299 else
11300 c_begin = cycle - slot_pair + 1;
11301
11302 c_end = cycle;
11303
11304 if (a2dp->exist)
11305 divide_cnt = 3;
11306 else
11307 divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
11308
11309 if (c_begin > c_end)
11310 goto out;
11311
11312 for (cycle = c_begin; cycle <= c_end; cycle++) {
11313 cnt++;
11314 store_index = ((cycle - 1) % slot_pair) * 2;
11315
11316 if (cnt % divide_cnt == 1)
11317 p += scnprintf(p, end - p, " %-15s : ",
11318 "[cycle_step]");
11319
11320 p += scnprintf(p, end - p, "->b%02d",
11321 le16_to_cpu(pcysta->slot_step_time[store_index]));
11322 if (a2dp->exist) {
11323 a2dp_trx = &pcysta->a2dp_trx[store_index];
11324 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11325 a2dp_trx->empty_cnt,
11326 a2dp_trx->retry_cnt,
11327 a2dp_trx->tx_rate ? 3 : 2,
11328 a2dp_trx->tx_cnt,
11329 a2dp_trx->ack_cnt,
11330 a2dp_trx->nack_cnt);
11331 }
11332 p += scnprintf(p, end - p, "->w%02d",
11333 le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
11334 if (a2dp->exist) {
11335 a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
11336 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11337 a2dp_trx->empty_cnt,
11338 a2dp_trx->retry_cnt,
11339 a2dp_trx->tx_rate ? 3 : 2,
11340 a2dp_trx->tx_cnt,
11341 a2dp_trx->ack_cnt,
11342 a2dp_trx->nack_cnt);
11343 }
11344 if (cnt % divide_cnt == 0 || cnt == c_end)
11345 p += scnprintf(p, end - p, "\n");
11346 }
11347
11348 if (a2dp->exist) {
11349 p += scnprintf(p, end - p,
11350 " %-15s : a2dp_ept:%d, a2dp_late:%d",
11351 "[a2dp_t_sta]",
11352 le16_to_cpu(pcysta->a2dp_ept.cnt),
11353 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
11354
11355 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n",
11356 le16_to_cpu(pcysta->a2dp_ept.tavg),
11357 le16_to_cpu(pcysta->a2dp_ept.tmax));
11358 }
11359
11360 out:
11361 return p - buf;
11362 }
11363
_show_fbtc_cysta_v105(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11364 static int _show_fbtc_cysta_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11365 {
11366 struct rtw89_btc *btc = &rtwdev->btc;
11367 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt0.link_info.a2dp_desc;
11368 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11369 struct rtw89_btc_dm *dm = &btc->dm;
11370 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
11371 struct rtw89_btc_fbtc_cysta_v105 *pcysta;
11372 struct rtw89_btc_rpt_cmn_info *pcinfo;
11373 u8 i, cnt = 0, slot_pair, divide_cnt;
11374 u16 cycle, c_begin, c_end, store_index;
11375 char *p = buf, *end = buf + bufsz;
11376
11377 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
11378 if (!pcinfo->valid)
11379 return 0;
11380
11381 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v105;
11382 p += scnprintf(p, end - p,
11383 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
11384 "[cycle_cnt]",
11385 le16_to_cpu(pcysta->cycles),
11386 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
11387 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
11388 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
11389 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
11390
11391 for (i = 0; i < CXST_MAX; i++) {
11392 if (!le16_to_cpu(pcysta->slot_cnt[i]))
11393 continue;
11394
11395 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
11396 le16_to_cpu(pcysta->slot_cnt[i]));
11397 }
11398
11399 if (dm->tdma_now.rxflctrl)
11400 p += scnprintf(p, end - p, ", leak_rx:%d",
11401 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
11402
11403 if (pcysta->collision_cnt)
11404 p += scnprintf(p, end - p, ", collision:%d",
11405 pcysta->collision_cnt);
11406
11407 if (le16_to_cpu(pcysta->skip_cnt))
11408 p += scnprintf(p, end - p, ", skip:%d",
11409 le16_to_cpu(pcysta->skip_cnt));
11410
11411 p += scnprintf(p, end - p, "\n");
11412
11413 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
11414 "[cycle_time]",
11415 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
11416 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
11417 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
11418 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
11419 p += scnprintf(p, end - p,
11420 ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n",
11421 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
11422 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
11423 le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
11424 le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
11425
11426 cycle = le16_to_cpu(pcysta->cycles);
11427 if (cycle <= 1)
11428 goto out;
11429
11430 /* 1 cycle record 1 wl-slot and 1 bt-slot */
11431 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
11432
11433 if (cycle <= slot_pair)
11434 c_begin = 1;
11435 else
11436 c_begin = cycle - slot_pair + 1;
11437
11438 c_end = cycle;
11439
11440 if (a2dp->exist)
11441 divide_cnt = 3;
11442 else
11443 divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
11444
11445 if (c_begin > c_end)
11446 goto out;
11447
11448 for (cycle = c_begin; cycle <= c_end; cycle++) {
11449 cnt++;
11450 store_index = ((cycle - 1) % slot_pair) * 2;
11451
11452 if (cnt % divide_cnt == 1)
11453 p += scnprintf(p, end - p, " %-15s : ",
11454 "[cycle_step]");
11455
11456 p += scnprintf(p, end - p, "->b%02d",
11457 le16_to_cpu(pcysta->slot_step_time[store_index]));
11458 if (a2dp->exist) {
11459 a2dp_trx = &pcysta->a2dp_trx[store_index];
11460 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11461 a2dp_trx->empty_cnt,
11462 a2dp_trx->retry_cnt,
11463 a2dp_trx->tx_rate ? 3 : 2,
11464 a2dp_trx->tx_cnt,
11465 a2dp_trx->ack_cnt,
11466 a2dp_trx->nack_cnt);
11467 }
11468 p += scnprintf(p, end - p, "->w%02d",
11469 le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
11470 if (a2dp->exist) {
11471 a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
11472 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
11473 a2dp_trx->empty_cnt,
11474 a2dp_trx->retry_cnt,
11475 a2dp_trx->tx_rate ? 3 : 2,
11476 a2dp_trx->tx_cnt,
11477 a2dp_trx->ack_cnt,
11478 a2dp_trx->nack_cnt);
11479 }
11480 if (cnt % divide_cnt == 0 || cnt == c_end)
11481 p += scnprintf(p, end - p, "\n");
11482 }
11483
11484 if (a2dp->exist) {
11485 p += scnprintf(p, end - p,
11486 " %-15s : a2dp_ept:%d, a2dp_late:%d",
11487 "[a2dp_t_sta]",
11488 le16_to_cpu(pcysta->a2dp_ept.cnt),
11489 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
11490
11491 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d\n",
11492 le16_to_cpu(pcysta->a2dp_ept.tavg),
11493 le16_to_cpu(pcysta->a2dp_ept.tmax));
11494 }
11495
11496 out:
11497 return p - buf;
11498 }
11499
_show_fbtc_cysta_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11500 static int _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11501 {
11502 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt0;
11503 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc;
11504 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
11505 struct rtw89_btc_fbtc_cysta_v7 *pcysta = NULL;
11506 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
11507 struct rtw89_btc_rpt_cmn_info *pcinfo;
11508 char *p = buf, *end = buf + bufsz;
11509 u16 cycle, c_begin, c_end, s_id;
11510 u8 i, cnt = 0, divide_cnt;
11511 u8 slot_pair;
11512
11513 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
11514 if (!pcinfo->valid)
11515 return 0;
11516
11517 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
11518 p += scnprintf(p, end - p, "\n %-15s : cycle:%d", "[slot_stat]",
11519 le16_to_cpu(pcysta->cycles));
11520
11521 for (i = 0; i < CXST_MAX; i++) {
11522 if (!le16_to_cpu(pcysta->slot_cnt[i]))
11523 continue;
11524 p += scnprintf(p, end - p, ", %s:%d",
11525 id_to_slot(i),
11526 le16_to_cpu(pcysta->slot_cnt[i]));
11527 }
11528
11529 if (dm->tdma_now.rxflctrl)
11530 p += scnprintf(p, end - p, ", leak_rx:%d",
11531 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
11532
11533 if (pcysta->collision_cnt)
11534 p += scnprintf(p, end - p, ", collision:%d",
11535 pcysta->collision_cnt);
11536
11537 if (pcysta->skip_cnt)
11538 p += scnprintf(p, end - p, ", skip:%d",
11539 le16_to_cpu(pcysta->skip_cnt));
11540
11541 p += scnprintf(p, end - p,
11542 "\n %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
11543 "[cycle_stat]",
11544 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
11545 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
11546 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
11547 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
11548 p += scnprintf(p, end - p,
11549 ", max_t[wl:%d/bt:%d(>%dms:%d)/lk:%d.%03d]",
11550 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
11551 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
11552 dm->bt_slot_flood, dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD],
11553 le16_to_cpu(pcysta->leak_slot.tamx) / 1000,
11554 le16_to_cpu(pcysta->leak_slot.tamx) % 1000);
11555 p += scnprintf(p, end - p, ", bcn[all:%d/ok:%d/in_bt:%d/in_bt_ok:%d]",
11556 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
11557 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
11558 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
11559 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
11560
11561 if (a2dp->exist) {
11562 p += scnprintf(p, end - p,
11563 "\n %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)",
11564 "[a2dp_stat]",
11565 le16_to_cpu(pcysta->a2dp_ept.cnt),
11566 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout),
11567 a2dp->no_empty_streak_2s,
11568 a2dp->no_empty_streak_max);
11569
11570 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
11571 le16_to_cpu(pcysta->a2dp_ept.tavg),
11572 le16_to_cpu(pcysta->a2dp_ept.tmax));
11573 }
11574
11575 if (le16_to_cpu(pcysta->cycles) <= 1)
11576 goto out;
11577
11578 /* 1 cycle = 1 wl-slot + 1 bt-slot */
11579 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
11580
11581 if (le16_to_cpu(pcysta->cycles) <= slot_pair)
11582 c_begin = 1;
11583 else
11584 c_begin = le16_to_cpu(pcysta->cycles) - slot_pair + 1;
11585
11586 c_end = le16_to_cpu(pcysta->cycles);
11587
11588 if (a2dp->exist)
11589 divide_cnt = 2;
11590 else
11591 divide_cnt = 6;
11592
11593 if (c_begin > c_end)
11594 goto out;
11595
11596 for (cycle = c_begin; cycle <= c_end; cycle++) {
11597 cnt++;
11598 s_id = ((cycle - 1) % slot_pair) * 2;
11599
11600 if (cnt % divide_cnt == 1) {
11601 if (a2dp->exist)
11602 p += scnprintf(p, end - p, "\n %-15s : ",
11603 "[slotT_wermtan]");
11604 else
11605 p += scnprintf(p, end - p, "\n %-15s : ",
11606 "[slotT_rxerr]");
11607 }
11608
11609 p += scnprintf(p, end - p, "->b%d",
11610 le16_to_cpu(pcysta->slot_step_time[s_id]));
11611
11612 if (a2dp->exist)
11613 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)",
11614 pcysta->wl_rx_err_ratio[s_id],
11615 pcysta->a2dp_trx[s_id].empty_cnt,
11616 pcysta->a2dp_trx[s_id].retry_cnt,
11617 (pcysta->a2dp_trx[s_id].tx_rate ? 3 : 2),
11618 pcysta->a2dp_trx[s_id].tx_cnt,
11619 pcysta->a2dp_trx[s_id].ack_cnt,
11620 pcysta->a2dp_trx[s_id].nack_cnt);
11621 else
11622 p += scnprintf(p, end - p, "(%d)",
11623 pcysta->wl_rx_err_ratio[s_id]);
11624
11625 p += scnprintf(p, end - p, "->w%d",
11626 le16_to_cpu(pcysta->slot_step_time[s_id + 1]));
11627
11628 if (a2dp->exist)
11629 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)",
11630 pcysta->wl_rx_err_ratio[s_id + 1],
11631 pcysta->a2dp_trx[s_id + 1].empty_cnt,
11632 pcysta->a2dp_trx[s_id + 1].retry_cnt,
11633 (pcysta->a2dp_trx[s_id + 1].tx_rate ? 3 : 2),
11634 pcysta->a2dp_trx[s_id + 1].tx_cnt,
11635 pcysta->a2dp_trx[s_id + 1].ack_cnt,
11636 pcysta->a2dp_trx[s_id + 1].nack_cnt);
11637 else
11638 p += scnprintf(p, end - p, "(%d)",
11639 pcysta->wl_rx_err_ratio[s_id + 1]);
11640 }
11641
11642 out:
11643 return p - buf;
11644 }
11645
_show_fbtc_nullsta(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11646 static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11647 {
11648 struct rtw89_btc *btc = &rtwdev->btc;
11649 const struct rtw89_btc_ver *ver = btc->ver;
11650 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11651 struct rtw89_btc_rpt_cmn_info *pcinfo;
11652 union rtw89_btc_fbtc_cynullsta_info *ns;
11653 char *p = buf, *end = buf + bufsz;
11654 u8 i = 0;
11655
11656 if (!btc->dm.tdma_now.rxflctrl)
11657 return 0;
11658
11659 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
11660 if (!pcinfo->valid)
11661 return 0;
11662
11663 ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
11664 if (ver->fcxnullsta == 1) {
11665 for (i = 0; i < 2; i++) {
11666 p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]");
11667 p += scnprintf(p, end - p, "null-%d", i);
11668 p += scnprintf(p, end - p, "[ok:%d/",
11669 le32_to_cpu(ns->v1.result[i][1]));
11670 p += scnprintf(p, end - p, "fail:%d/",
11671 le32_to_cpu(ns->v1.result[i][0]));
11672 p += scnprintf(p, end - p, "on_time:%d/",
11673 le32_to_cpu(ns->v1.result[i][2]));
11674 p += scnprintf(p, end - p, "retry:%d/",
11675 le32_to_cpu(ns->v1.result[i][3]));
11676 p += scnprintf(p, end - p, "avg_t:%d.%03d/",
11677 le32_to_cpu(ns->v1.avg_t[i]) / 1000,
11678 le32_to_cpu(ns->v1.avg_t[i]) % 1000);
11679 p += scnprintf(p, end - p, "max_t:%d.%03d]",
11680 le32_to_cpu(ns->v1.max_t[i]) / 1000,
11681 le32_to_cpu(ns->v1.max_t[i]) % 1000);
11682 }
11683 } else if (ver->fcxnullsta == 7) {
11684 for (i = 0; i < 2; i++) {
11685 p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]");
11686 p += scnprintf(p, end - p, "null-%d", i);
11687 p += scnprintf(p, end - p, "[Tx:%d/",
11688 le32_to_cpu(ns->v7.result[i][4]));
11689 p += scnprintf(p, end - p, "[ok:%d/",
11690 le32_to_cpu(ns->v7.result[i][1]));
11691 p += scnprintf(p, end - p, "fail:%d/",
11692 le32_to_cpu(ns->v7.result[i][0]));
11693 p += scnprintf(p, end - p, "on_time:%d/",
11694 le32_to_cpu(ns->v7.result[i][2]));
11695 p += scnprintf(p, end - p, "retry:%d/",
11696 le32_to_cpu(ns->v7.result[i][3]));
11697 p += scnprintf(p, end - p, "avg_t:%d.%03d/",
11698 le32_to_cpu(ns->v7.tavg[i]) / 1000,
11699 le32_to_cpu(ns->v7.tavg[i]) % 1000);
11700 p += scnprintf(p, end - p, "max_t:%d.%03d]",
11701 le32_to_cpu(ns->v7.tmax[i]) / 1000,
11702 le32_to_cpu(ns->v7.tmax[i]) % 1000);
11703 }
11704 } else {
11705 for (i = 0; i < 2; i++) {
11706 p += scnprintf(p, end - p, "\n %-15s : ", "[NULL-STA]");
11707 p += scnprintf(p, end - p, "null-%d", i);
11708 p += scnprintf(p, end - p, "[Tx:%d/",
11709 le32_to_cpu(ns->v2.result[i][4]));
11710 p += scnprintf(p, end - p, "[ok:%d/",
11711 le32_to_cpu(ns->v2.result[i][1]));
11712 p += scnprintf(p, end - p, "fail:%d/",
11713 le32_to_cpu(ns->v2.result[i][0]));
11714 p += scnprintf(p, end - p, "on_time:%d/",
11715 le32_to_cpu(ns->v2.result[i][2]));
11716 p += scnprintf(p, end - p, "retry:%d/",
11717 le32_to_cpu(ns->v2.result[i][3]));
11718 p += scnprintf(p, end - p, "avg_t:%d.%03d/",
11719 le32_to_cpu(ns->v2.avg_t[i]) / 1000,
11720 le32_to_cpu(ns->v2.avg_t[i]) % 1000);
11721 p += scnprintf(p, end - p, "max_t:%d.%03d]",
11722 le32_to_cpu(ns->v2.max_t[i]) / 1000,
11723 le32_to_cpu(ns->v2.max_t[i]) % 1000);
11724 }
11725 }
11726
11727 return p - buf;
11728 }
11729
_show_fbtc_step_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11730 static int _show_fbtc_step_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11731 {
11732 struct rtw89_btc *btc = &rtwdev->btc;
11733 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11734 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11735 struct rtw89_btc_fbtc_steps_v2 *pstep = NULL;
11736 const struct rtw89_btc_ver *ver = btc->ver;
11737 char *p = buf, *end = buf + bufsz;
11738 u8 type, val, cnt = 0, state = 0;
11739 bool outloop = false;
11740 u16 i, diff_t, n_start = 0, n_stop = 0;
11741 u16 pos_old, pos_new, trace_step;
11742
11743 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
11744 if (!pcinfo->valid)
11745 return 0;
11746
11747 pstep = &pfwinfo->rpt_fbtc_step.finfo.v2;
11748 pos_old = le16_to_cpu(pstep->pos_old);
11749 pos_new = le16_to_cpu(pstep->pos_new);
11750
11751 if (pcinfo->req_fver != pstep->fver)
11752 return 0;
11753
11754 /* store step info by using ring instead of FIFO*/
11755 do {
11756 switch (state) {
11757 case 0:
11758 if (ver->fcxctrl == 7 || ver->fcxctrl == 1)
11759 trace_step = 50;
11760 else
11761 trace_step = btc->ctrl.trace_step;
11762
11763 n_start = pos_old;
11764 if (pos_new >= pos_old)
11765 n_stop = pos_new;
11766 else
11767 n_stop = trace_step - 1;
11768
11769 state = 1;
11770 break;
11771 case 1:
11772 for (i = n_start; i <= n_stop; i++) {
11773 type = pstep->step[i].type;
11774 val = pstep->step[i].val;
11775 diff_t = le16_to_cpu(pstep->step[i].difft);
11776
11777 if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
11778 continue;
11779
11780 if (cnt % 10 == 0)
11781 p += scnprintf(p, end - p,
11782 " %-15s : ", "[steps]");
11783
11784 p += scnprintf(p, end - p,
11785 "-> %s(%02d)(%02d)",
11786 (type == CXSTEP_SLOT ? "SLT" :
11787 "EVT"), (u32)val, diff_t);
11788 if (cnt % 10 == 9)
11789 p += scnprintf(p, end - p, "\n");
11790 cnt++;
11791 }
11792
11793 state = 2;
11794 break;
11795 case 2:
11796 if (pos_new < pos_old && n_start != 0) {
11797 n_start = 0;
11798 n_stop = pos_new;
11799 state = 1;
11800 } else {
11801 outloop = true;
11802 }
11803 break;
11804 }
11805 } while (!outloop);
11806
11807 return p - buf;
11808 }
11809
_show_fbtc_step_v3(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11810 static int _show_fbtc_step_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11811 {
11812 struct rtw89_btc *btc = &rtwdev->btc;
11813 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11814 struct rtw89_btc_rpt_cmn_info *pcinfo;
11815 struct rtw89_btc_fbtc_steps_v3 *pstep;
11816 u32 i, n_begin, n_end, array_idx, cnt = 0;
11817 char *p = buf, *end = buf + bufsz;
11818 u8 type, val;
11819 u16 diff_t;
11820
11821 if ((pfwinfo->rpt_en_map &
11822 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0)
11823 return 0;
11824
11825 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
11826 if (!pcinfo->valid)
11827 return 0;
11828
11829 pstep = &pfwinfo->rpt_fbtc_step.finfo.v3;
11830 if (pcinfo->req_fver != pstep->fver)
11831 return 0;
11832
11833 if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP)
11834 n_begin = 1;
11835 else
11836 n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1;
11837
11838 n_end = le32_to_cpu(pstep->cnt);
11839
11840 if (n_begin > n_end)
11841 return 0;
11842
11843 /* restore step info by using ring instead of FIFO */
11844 for (i = n_begin; i <= n_end; i++) {
11845 array_idx = (i - 1) % FCXDEF_STEP;
11846 type = pstep->step[array_idx].type;
11847 val = pstep->step[array_idx].val;
11848 diff_t = le16_to_cpu(pstep->step[array_idx].difft);
11849
11850 if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
11851 continue;
11852
11853 if (cnt % 10 == 0)
11854 p += scnprintf(p, end - p, " %-15s : ", "[steps]");
11855
11856 p += scnprintf(p, end - p, "-> %s(%02d)",
11857 (type == CXSTEP_SLOT ?
11858 id_to_slot((u32)val) :
11859 id_to_evt((u32)val)), diff_t);
11860
11861 if (cnt % 10 == 9)
11862 p += scnprintf(p, end - p, "\n");
11863
11864 cnt++;
11865 }
11866
11867 return p - buf;
11868 }
11869
_show_fw_dm_msg(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11870 static int _show_fw_dm_msg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11871 {
11872 struct rtw89_btc *btc = &rtwdev->btc;
11873 const struct rtw89_btc_ver *ver = btc->ver;
11874 char *p = buf, *end = buf + bufsz;
11875
11876 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
11877 goto out;
11878
11879 p += _show_error(rtwdev, p, end - p);
11880 p += _show_fbtc_tdma(rtwdev, p, end - p);
11881 p += _show_fbtc_slots(rtwdev, p, end - p);
11882
11883 if (ver->fcxcysta == 2)
11884 p += _show_fbtc_cysta_v2(rtwdev, p, end - p);
11885 else if (ver->fcxcysta == 3)
11886 p += _show_fbtc_cysta_v3(rtwdev, p, end - p);
11887 else if (ver->fcxcysta == 4)
11888 p += _show_fbtc_cysta_v4(rtwdev, p, end - p);
11889 else if (ver->fcxcysta == 5)
11890 p += _show_fbtc_cysta_v5(rtwdev, p, end - p);
11891 else if (ver->fcxcysta == 105)
11892 p += _show_fbtc_cysta_v105(rtwdev, p, end - p);
11893 else if (ver->fcxcysta == 7)
11894 p += _show_fbtc_cysta_v7(rtwdev, p, end - p);
11895
11896 p += _show_fbtc_nullsta(rtwdev, p, end - p);
11897
11898 if (ver->fcxstep == 2)
11899 p += _show_fbtc_step_v2(rtwdev, p, end - p);
11900 else if (ver->fcxstep == 3)
11901 p += _show_fbtc_step_v3(rtwdev, p, end - p);
11902
11903 out:
11904 return p - buf;
11905 }
11906
_get_gnt(struct rtw89_dev * rtwdev,struct rtw89_mac_ax_coex_gnt * gnt_cfg)11907 static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg)
11908 {
11909 const struct rtw89_chip_info *chip = rtwdev->chip;
11910 struct rtw89_mac_ax_wl_act *bt;
11911 struct rtw89_mac_ax_gnt *gnt;
11912 u32 val, status;
11913
11914 if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B ||
11915 chip->chip_id == RTL8851B || chip->chip_id == RTL8852BT) {
11916 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
11917 rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status);
11918
11919 gnt = &gnt_cfg->band[0];
11920 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL);
11921 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA);
11922 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL);
11923 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA);
11924
11925 gnt = &gnt_cfg->band[1];
11926 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL);
11927 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA);
11928 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL);
11929 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA);
11930 } else if (chip->chip_id == RTL8852C) {
11931 val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL);
11932 status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1);
11933
11934 gnt = &gnt_cfg->band[0];
11935 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL);
11936 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0);
11937 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL);
11938 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0);
11939
11940 gnt = &gnt_cfg->band[1];
11941 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL);
11942 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1);
11943 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL);
11944 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1);
11945
11946 bt = &gnt_cfg->bt[0];
11947 bt->wlan_act_en = !!(val & B_BE_WL_ACT_SWCTRL);
11948 bt->wlan_act = !!(status & B_BE_WL_ACT_VAL);
11949
11950 bt = &gnt_cfg->bt[1];
11951 bt->wlan_act_en = !!(val & B_BE_WL_ACT2_SWCTRL);
11952 bt->wlan_act = !!(status & B_BE_WL_ACT2_VAL);
11953 } else if (chip->chip_id == RTL8922A) {
11954 val = rtw89_read32(rtwdev, R_BE_GNT_SW_CTRL);
11955 status = rtw89_read32(rtwdev, R_BE_PTA_GNT_VAL);
11956
11957 gnt = &gnt_cfg->band[0];
11958 gnt->gnt_bt_sw_en = !!(val & B_BE_GNT_BT_BB0_SWCTRL);
11959 gnt->gnt_bt = !!(status & B_BE_GNT_BT_BB0_VAL);
11960 gnt->gnt_wl_sw_en = !!(val & B_BE_GNT_WL_BB0_SWCTRL);
11961 gnt->gnt_wl = !!(status & B_BE_GNT_WL_BB0_VAL);
11962
11963 gnt = &gnt_cfg->band[1];
11964 gnt->gnt_bt_sw_en = !!(val & B_BE_GNT_BT_BB1_SWCTRL);
11965 gnt->gnt_bt = !!(status & B_BE_GNT_BT_BB1_VAL);
11966 gnt->gnt_wl_sw_en = !!(val & B_BE_GNT_WL_BB1_SWCTRL);
11967 gnt->gnt_wl = !!(status & B_BE_GNT_WL_BB1_VAL);
11968
11969 bt = &gnt_cfg->bt[0];
11970 bt->wlan_act_en = !!(val & B_BE_WL_ACT_SWCTRL);
11971 bt->wlan_act = !!(status & B_BE_WL_ACT_VAL);
11972
11973 bt = &gnt_cfg->bt[1];
11974 bt->wlan_act_en = !!(val & B_BE_WL_ACT2_SWCTRL);
11975 bt->wlan_act = !!(status & B_BE_WL_ACT2_VAL);
11976 } else if (chip->chip_id == RTL8922D) {
11977 /* Get from firmware */
11978 return;
11979 }
11980 }
11981
_show_gpio_dbg(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11982 static int _show_gpio_dbg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11983 {
11984 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
11985 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
11986 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11987 union rtw89_btc_fbtc_gpio_dbg *gdbg = NULL;
11988 char *p = buf, *end = buf + bufsz;
11989 u32 en_map_raw, en_map;
11990 u8 *gpio_map, i, sig;
11991
11992 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
11993 gdbg = &rtwdev->btc.fwinfo.rpt_fbtc_gpio_dbg.finfo;
11994 if (!pcinfo->valid) {
11995 rtw89_debug(rtwdev, RTW89_DBG_BTC,
11996 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n",
11997 __func__);
11998 goto out;
11999 }
12000
12001 if (ver->fcxgpiodbg == 7 || ver->fcxgpiodbg == 8) {
12002 en_map_raw = le32_to_cpu(gdbg->v7.en_map);
12003 gpio_map = gdbg->v7.gpio_map;
12004 } else {
12005 en_map_raw = le32_to_cpu(gdbg->v1.en_map);
12006 gpio_map = gdbg->v1.gpio_map;
12007 }
12008
12009 en_map = _convert_gpio_enmap_from_ver(rtwdev, en_map_raw);
12010 if (!en_map)
12011 goto out;
12012
12013 p += scnprintf(p, end - p, "\n %-15s : enable_map:0x%08x",
12014 "[gpio_dbg]", en_map);
12015
12016 for (i = 0; i < BTC_DBG_NUM; i++) {
12017 if (!(en_map & BIT(i)))
12018 continue;
12019
12020 sig = ver->fcxgpiodbg >= 8 ? i : _get_gpiosig_for_ver(rtwdev, i);
12021 if (sig >= BTC_DBG_NUM)
12022 continue;
12023
12024 p += scnprintf(p, end - p, ", %s->GPIO%d", id_to_gdbg(i),
12025 gpio_map[sig]);
12026 }
12027
12028 out:
12029 return p - buf;
12030 }
12031
_show_mreg_v1(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12032 static int _show_mreg_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12033 {
12034 const struct rtw89_chip_info *chip = rtwdev->chip;
12035 struct rtw89_btc *btc = &rtwdev->btc;
12036 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
12037 struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL;
12038 struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0;
12039 struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1;
12040 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
12041 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
12042 struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
12043 struct rtw89_mac_ax_gnt gnt;
12044 char *p = buf, *end = buf + bufsz;
12045 u8 i = 0, type = 0, cnt = 0;
12046 u32 val, offset;
12047
12048 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
12049 return 0;
12050
12051 p += scnprintf(p, end - p, "========== [HW Status] ==========\n");
12052
12053 p += scnprintf(p, end - p,
12054 " %-15s : WL->BT0:0x%08x(cnt:%d), BT0->WL:0x%08x(total:%d, bt_update:%d)\n",
12055 "[scoreboard]", wl->scbd[BTC_BT_1ST],
12056 wl->wcnt[BTC_WCNT_SCBDUPDATE],
12057 bt0->scbd, bt0->bcnt[BTC_BCNT_SCBDREAD],
12058 bt0->bcnt[BTC_BCNT_SCBDUPDATE]);
12059
12060 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) {
12061 p += scnprintf(p, end - p,
12062 " %-15s : WL->BT1:0x%08x(cnt:%d), BT1->WL:0x%08x(total:%d, bt_update:%d)\n",
12063 "[scoreboard]", wl->scbd[BTC_BT_2ND],
12064 wl->wcnt[BTC_WCNT_SCBDUPDATE2],
12065 bt1->scbd, bt1->bcnt[BTC_BCNT_SCBDREAD],
12066 bt1->bcnt[BTC_BCNT_SCBDUPDATE]);
12067 }
12068
12069 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
12070 _get_gnt(rtwdev, &gnt_cfg);
12071
12072 gnt = gnt_cfg.band[0];
12073 p += scnprintf(p, end - p,
12074 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
12075 "[gnt_status]",
12076 chip->chip_id == RTL8852C ? "HW" :
12077 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
12078 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
12079 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt);
12080
12081 gnt = gnt_cfg.band[1];
12082 p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
12083 gnt.gnt_wl_sw_en ? "SW" : "HW",
12084 gnt.gnt_wl,
12085 gnt.gnt_bt_sw_en ? "SW" : "HW",
12086 gnt.gnt_bt);
12087
12088 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
12089 if (!pcinfo->valid) {
12090 rtw89_debug(rtwdev, RTW89_DBG_BTC,
12091 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
12092 __func__);
12093 goto out;
12094 }
12095
12096 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
12097 rtw89_debug(rtwdev, RTW89_DBG_BTC,
12098 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
12099 __func__, pmreg->reg_num);
12100
12101 for (i = 0; i < pmreg->reg_num; i++) {
12102 type = (u8)le16_to_cpu(chip->mon_reg[i].type);
12103 offset = le32_to_cpu(chip->mon_reg[i].offset);
12104 val = le32_to_cpu(pmreg->mreg_val[i]);
12105
12106 if (cnt % 6 == 0)
12107 p += scnprintf(p, end - p,
12108 " %-15s : %d_0x%04x=0x%08x",
12109 "[reg]", (u32)type, offset, val);
12110 else
12111 p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x",
12112 (u32)type,
12113 offset, val);
12114 if (cnt % 6 == 5)
12115 p += scnprintf(p, end - p, "\n");
12116 cnt++;
12117
12118 if (i >= pmreg->reg_num)
12119 p += scnprintf(p, end - p, "\n");
12120 }
12121
12122 out:
12123 return p - buf;
12124 }
12125
_show_mreg_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12126 static int _show_mreg_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12127 {
12128 const struct rtw89_chip_info *chip = rtwdev->chip;
12129 struct rtw89_btc *btc = &rtwdev->btc;
12130 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
12131 struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL;
12132 struct rtw89_btc_bt_info *bt0 = &btc->cx.bt0;
12133 struct rtw89_btc_bt_info *bt1 = &btc->cx.bt1;
12134 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
12135 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
12136 struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
12137 struct rtw89_mac_ax_gnt gnt;
12138 char *p = buf, *end = buf + bufsz;
12139 u8 i = 0, type = 0, cnt = 0;
12140 u32 val, offset;
12141
12142 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
12143 return 0;
12144
12145 p += scnprintf(p, end - p, "========== [HW Status] ==========\n");
12146
12147 p += scnprintf(p, end - p,
12148 " %-15s : WL->BT0:0x%08x(cnt:%d), BT0->WL:0x%08x(total:%d, bt_update:%d)\n",
12149 "[scoreboard]", wl->scbd[BTC_BT_1ST],
12150 wl->wcnt[BTC_WCNT_SCBDUPDATE],
12151 bt0->scbd, bt0->bcnt[BTC_BCNT_SCBDREAD],
12152 bt0->bcnt[BTC_BCNT_SCBDUPDATE]);
12153
12154 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) {
12155 p += scnprintf(p, end - p,
12156 " %-15s : WL->BT1:0x%08x(cnt:%d), BT1->WL:0x%08x(total:%d, bt_update:%d)\n",
12157 "[scoreboard]", wl->scbd[BTC_BT_2ND],
12158 wl->wcnt[BTC_WCNT_SCBDUPDATE2],
12159 bt1->scbd, bt1->bcnt[BTC_BCNT_SCBDREAD],
12160 bt1->bcnt[BTC_BCNT_SCBDUPDATE]);
12161 }
12162
12163 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
12164 _get_gnt(rtwdev, &gnt_cfg);
12165
12166 gnt = gnt_cfg.band[0];
12167 p += scnprintf(p, end - p,
12168 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], polut_type:%s",
12169 "[gnt_status]",
12170 chip->chip_id == RTL8852C ? "HW" :
12171 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
12172 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
12173 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt,
12174 id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
12175
12176 gnt = gnt_cfg.band[1];
12177 p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
12178 gnt.gnt_wl_sw_en ? "SW" : "HW",
12179 gnt.gnt_wl,
12180 gnt.gnt_bt_sw_en ? "SW" : "HW",
12181 gnt.gnt_bt);
12182
12183 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
12184 if (!pcinfo->valid) {
12185 rtw89_debug(rtwdev, RTW89_DBG_BTC,
12186 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
12187 __func__);
12188 goto out;
12189 }
12190
12191 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
12192 rtw89_debug(rtwdev, RTW89_DBG_BTC,
12193 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
12194 __func__, pmreg->reg_num);
12195
12196 for (i = 0; i < pmreg->reg_num; i++) {
12197 type = (u8)le16_to_cpu(chip->mon_reg[i].type);
12198 offset = le32_to_cpu(chip->mon_reg[i].offset);
12199 val = le32_to_cpu(pmreg->mreg_val[i]);
12200
12201 if (cnt % 6 == 0)
12202 p += scnprintf(p, end - p,
12203 " %-15s : %d_0x%04x=0x%08x",
12204 "[reg]", (u32)type, offset, val);
12205 else
12206 p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x",
12207 (u32)type,
12208 offset, val);
12209 if (cnt % 6 == 5)
12210 p += scnprintf(p, end - p, "\n");
12211 cnt++;
12212
12213 if (i >= pmreg->reg_num)
12214 p += scnprintf(p, end - p, "\n");
12215 }
12216
12217 out:
12218 return p - buf;
12219 }
12220
_show_mreg_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12221 static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12222 {
12223 struct rtw89_btc *btc = &rtwdev->btc;
12224 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
12225 struct rtw89_btc_fbtc_mreg_val_v7 *pmreg = NULL;
12226 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
12227 struct rtw89_btc_cx *cx = &btc->cx;
12228 struct rtw89_btc_bt_info *bt0 = &cx->bt0;
12229 struct rtw89_btc_bt_info *bt1 = &cx->bt1;
12230 struct rtw89_btc_wl_info *wl = &cx->wl;
12231 struct rtw89_btc_dm *dm = &btc->dm;
12232 char *p = buf, *end = buf + bufsz;
12233 u8 i, type, cnt = 0;
12234 u32 val, offset;
12235
12236 if (!(dm->coex_info_map & BTC_COEX_INFO_MREG))
12237 return 0;
12238
12239 p += scnprintf(p, end - p, "\n========== [HW Status] ==========\n");
12240
12241 p += scnprintf(p, end - p,
12242 " %-15s : WL->BT0:0x%08x(cnt:%d), BT0->WL:0x%08x(total:%d, bt_update:%d)\n",
12243 "[scoreboard]", wl->scbd[BTC_BT_1ST],
12244 wl->wcnt[BTC_WCNT_SCBDUPDATE],
12245 bt0->scbd, bt0->bcnt[BTC_BCNT_SCBDREAD],
12246 bt0->bcnt[BTC_BCNT_SCBDUPDATE]);
12247
12248 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT) {
12249 p += scnprintf(p, end - p,
12250 " %-15s : WL->BT1:0x%08x(cnt:%d), BT1->WL:0x%08x(total:%d, bt_update:%d)\n",
12251 "[scoreboard]", wl->scbd[BTC_BT_2ND],
12252 wl->wcnt[BTC_WCNT_SCBDUPDATE2],
12253 bt1->scbd, bt1->bcnt[BTC_BCNT_SCBDREAD],
12254 bt1->bcnt[BTC_BCNT_SCBDUPDATE]);
12255 }
12256
12257 /* To avoid I/O if WL LPS or power-off */
12258 dm->pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
12259
12260 p += scnprintf(p, end - p,
12261 " %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s\n",
12262 "[gnt_status]",
12263 rtwdev->chip->para_ver & BTC_FEAT_PTA_ONOFF_CTRL ? "HW" :
12264 dm->pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
12265 wl->pta_req_mac,
12266 id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
12267
12268 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)
12269 p += scnprintf(p, end - p,
12270 " %-15s : phy-0[gnt_wl:%s-%d/gnt_bt0:%s-%d/gnt_bt1:%s-%d]",
12271 "[gnt_status]",
12272 dm->gnt_set[RTW89_PHY_0].gnt_wl_sw_en ? "SW" : "HW",
12273 dm->gnt_set[RTW89_PHY_0].gnt_wl,
12274 dm->gnt_set[RTW89_PHY_0].gnt_bt0_sw_en ? "SW" : "HW",
12275 dm->gnt_set[RTW89_PHY_0].gnt_bt0,
12276 dm->gnt_set[RTW89_PHY_0].gnt_bt1_sw_en ? "SW" : "HW",
12277 dm->gnt_set[RTW89_PHY_0].gnt_bt1);
12278 else
12279 p += scnprintf(p, end - p,
12280 " %-15s : phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]",
12281 "[gnt_status]",
12282 dm->gnt_set[RTW89_PHY_0].gnt_wl_sw_en ? "SW" : "HW",
12283 dm->gnt_set[RTW89_PHY_0].gnt_wl,
12284 dm->gnt_set[RTW89_PHY_0].gnt_bt0_sw_en ? "SW" : "HW",
12285 dm->gnt_set[RTW89_PHY_0].gnt_bt0);
12286
12287 if (rtwdev->dbcc_en) {
12288 if (rtwdev->chip->para_ver & BTC_FEAT_DUAL_BT)
12289 p += scnprintf(p, end - p,
12290 ", phy-1[gnt_wl:%s-%d/gnt_bt0:%s-%d/gnt_bt1:%s-%d]",
12291 dm->gnt_set[RTW89_PHY_1].gnt_wl_sw_en ? "SW" : "HW",
12292 dm->gnt_set[RTW89_PHY_1].gnt_wl,
12293 dm->gnt_set[RTW89_PHY_1].gnt_bt0_sw_en ? "SW" : "HW",
12294 dm->gnt_set[RTW89_PHY_1].gnt_bt0,
12295 dm->gnt_set[RTW89_PHY_1].gnt_bt1_sw_en ? "SW" : "HW",
12296 dm->gnt_set[RTW89_PHY_1].gnt_bt1);
12297 else
12298 p += scnprintf(p, end - p,
12299 ", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]",
12300 dm->gnt_set[RTW89_PHY_1].gnt_wl_sw_en ? "SW" : "HW",
12301 dm->gnt_set[RTW89_PHY_1].gnt_wl,
12302 dm->gnt_set[RTW89_PHY_1].gnt_bt0_sw_en ? "SW" : "HW",
12303 dm->gnt_set[RTW89_PHY_1].gnt_bt0);
12304 }
12305
12306 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
12307 if (!pcinfo->valid)
12308 goto out;
12309
12310 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
12311
12312 for (i = 0; i < pmreg->reg_num; i++) {
12313 type = (u8)le16_to_cpu(rtwdev->chip->mon_reg[i].type);
12314 offset = le32_to_cpu(rtwdev->chip->mon_reg[i].offset);
12315 val = le32_to_cpu(pmreg->mreg_val[i]);
12316
12317 if (cnt % 6 == 0)
12318 p += scnprintf(p, end - p,
12319 "\n %-15s : %s_0x%x=0x%x", "[reg]",
12320 id_to_regtype(type), offset, val);
12321 else
12322 p += scnprintf(p, end - p, ", %s_0x%x=0x%x",
12323 id_to_regtype(type), offset, val);
12324 cnt++;
12325 }
12326
12327 out:
12328 return p - buf;
12329 }
12330
_show_summary_v1(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12331 static int _show_summary_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12332 {
12333 struct rtw89_btc *btc = &rtwdev->btc;
12334 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
12335 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
12336 struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL;
12337 struct rtw89_btc_cx *cx = &btc->cx;
12338 struct rtw89_btc_dm *dm = &btc->dm;
12339 struct rtw89_btc_wl_info *wl = &cx->wl;
12340 struct rtw89_btc_bt_info *bt = &cx->bt0;
12341 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
12342 char *p = buf, *end = buf + bufsz;
12343 u8 i;
12344
12345 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
12346 return 0;
12347
12348 p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
12349
12350 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
12351 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
12352 prptctrl = &pfwinfo->rpt_ctrl.finfo.v1;
12353
12354 p += scnprintf(p, end - p,
12355 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
12356 "[summary]", pfwinfo->cnt_h2c,
12357 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt,
12358 pfwinfo->cnt_c2h, prptctrl->c2h_cnt);
12359
12360 p += scnprintf(p, end - p,
12361 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
12362 pfwinfo->event[BTF_EVNT_RPT],
12363 prptctrl->rpt_cnt,
12364 prptctrl->rpt_enable, dm->error.val);
12365
12366 if (dm->error.map.wl_fw_hang)
12367 p += scnprintf(p, end - p, " (WL FW Hang!!)");
12368 p += scnprintf(p, end - p, "\n");
12369 p += scnprintf(p, end - p,
12370 " %-15s : send_ok:%d, send_fail:%d, recv:%d",
12371 "[mailbox]", prptctrl->mb_send_ok_cnt,
12372 prptctrl->mb_send_fail_cnt,
12373 prptctrl->mb_recv_cnt);
12374
12375 p += scnprintf(p, end - p,
12376 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n",
12377 prptctrl->mb_a2dp_empty_cnt,
12378 prptctrl->mb_a2dp_flct_cnt,
12379 prptctrl->mb_a2dp_full_cnt);
12380
12381 p += scnprintf(p, end - p,
12382 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
12383 "[RFK]", wl->wcnt[BTC_WCNT_RFK_REQ],
12384 wl->wcnt[BTC_WCNT_RFK_GO],
12385 wl->wcnt[BTC_WCNT_RFK_REJECT],
12386 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]);
12387
12388 p += scnprintf(p, end - p,
12389 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
12390 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
12391 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
12392 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
12393 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
12394 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
12395
12396 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
12397 bt->rfk_info.map.timeout = 1;
12398 else
12399 bt->rfk_info.map.timeout = 0;
12400
12401 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
12402 } else {
12403 p += scnprintf(p, end - p,
12404 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
12405 "[summary]", pfwinfo->cnt_h2c,
12406 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
12407 pfwinfo->event[BTF_EVNT_RPT],
12408 btc->fwinfo.rpt_en_map);
12409 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n");
12410 }
12411
12412 for (i = 0; i < BTC_NCNT_NUM; i++)
12413 cnt_sum += dm->cnt_notify[i];
12414
12415 p += scnprintf(p, end - p,
12416 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
12417 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
12418 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
12419
12420 p += scnprintf(p, end - p,
12421 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
12422 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
12423 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
12424 cnt[BTC_NCNT_WL_STA]);
12425
12426 p += scnprintf(p, end - p,
12427 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
12428 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
12429 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
12430 cnt[BTC_NCNT_SPECIAL_PACKET]);
12431
12432 p += scnprintf(p, end - p,
12433 "timer=%d, control=%d, customerize=%d\n",
12434 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
12435 cnt[BTC_NCNT_CUSTOMERIZE]);
12436
12437 return p - buf;
12438 }
12439
_show_summary_v4(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12440 static int _show_summary_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12441 {
12442 struct rtw89_btc *btc = &rtwdev->btc;
12443 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
12444 struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl;
12445 struct rtw89_btc_rpt_cmn_info *pcinfo;
12446 struct rtw89_btc_cx *cx = &btc->cx;
12447 struct rtw89_btc_dm *dm = &btc->dm;
12448 struct rtw89_btc_wl_info *wl = &cx->wl;
12449 struct rtw89_btc_bt_info *bt = &cx->bt0;
12450 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
12451 char *p = buf, *end = buf + bufsz;
12452 u8 i;
12453
12454 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
12455 return 0;
12456
12457 p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
12458
12459 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
12460 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
12461 prptctrl = &pfwinfo->rpt_ctrl.finfo.v4;
12462
12463 p += scnprintf(p, end - p,
12464 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
12465 "[summary]", pfwinfo->cnt_h2c,
12466 pfwinfo->cnt_h2c_fail,
12467 le32_to_cpu(prptctrl->rpt_info.cnt_h2c),
12468 pfwinfo->cnt_c2h,
12469 le32_to_cpu(prptctrl->rpt_info.cnt_c2h));
12470
12471 p += scnprintf(p, end - p,
12472 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
12473 pfwinfo->event[BTF_EVNT_RPT],
12474 le32_to_cpu(prptctrl->rpt_info.cnt),
12475 le32_to_cpu(prptctrl->rpt_info.en),
12476 dm->error.val);
12477
12478 if (dm->error.map.wl_fw_hang)
12479 p += scnprintf(p, end - p, " (WL FW Hang!!)");
12480 p += scnprintf(p, end - p, "\n");
12481 p += scnprintf(p, end - p,
12482 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
12483 "[mailbox]",
12484 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
12485 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
12486 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
12487
12488 p += scnprintf(p, end - p,
12489 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
12490 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
12491 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
12492 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
12493 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
12494 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
12495
12496 p += scnprintf(p, end - p,
12497 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
12498 "[RFK]", wl->wcnt[BTC_WCNT_RFK_REQ],
12499 wl->wcnt[BTC_WCNT_RFK_GO],
12500 wl->wcnt[BTC_WCNT_RFK_REJECT],
12501 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]);
12502
12503 p += scnprintf(p, end - p,
12504 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
12505 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]),
12506 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]),
12507 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]),
12508 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]),
12509 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL]));
12510
12511 if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
12512 bt->rfk_info.map.timeout = 1;
12513 else
12514 bt->rfk_info.map.timeout = 0;
12515
12516 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
12517 } else {
12518 p += scnprintf(p, end - p,
12519 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
12520 "[summary]", pfwinfo->cnt_h2c,
12521 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
12522 pfwinfo->event[BTF_EVNT_RPT],
12523 btc->fwinfo.rpt_en_map);
12524 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n");
12525 }
12526
12527 for (i = 0; i < BTC_NCNT_NUM; i++)
12528 cnt_sum += dm->cnt_notify[i];
12529
12530 p += scnprintf(p, end - p,
12531 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
12532 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
12533 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
12534
12535 p += scnprintf(p, end - p,
12536 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
12537 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
12538 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
12539 cnt[BTC_NCNT_WL_STA]);
12540
12541 p += scnprintf(p, end - p,
12542 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
12543 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
12544 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
12545 cnt[BTC_NCNT_SPECIAL_PACKET]);
12546
12547 p += scnprintf(p, end - p,
12548 "timer=%d, control=%d, customerize=%d\n",
12549 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
12550 cnt[BTC_NCNT_CUSTOMERIZE]);
12551
12552 return p - buf;
12553 }
12554
_show_summary_v5(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12555 static int _show_summary_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12556 {
12557 struct rtw89_btc *btc = &rtwdev->btc;
12558 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
12559 struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl;
12560 struct rtw89_btc_rpt_cmn_info *pcinfo;
12561 struct rtw89_btc_cx *cx = &btc->cx;
12562 struct rtw89_btc_dm *dm = &btc->dm;
12563 struct rtw89_btc_wl_info *wl = &cx->wl;
12564 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
12565 char *p = buf, *end = buf + bufsz;
12566 u8 i;
12567
12568 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
12569 return 0;
12570
12571 p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
12572
12573 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
12574 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
12575 prptctrl = &pfwinfo->rpt_ctrl.finfo.v5;
12576
12577 p += scnprintf(p, end - p,
12578 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
12579 "[summary]", pfwinfo->cnt_h2c,
12580 pfwinfo->cnt_h2c_fail,
12581 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
12582 pfwinfo->cnt_c2h,
12583 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
12584 le16_to_cpu(prptctrl->rpt_info.len_c2h));
12585
12586 p += scnprintf(p, end - p,
12587 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
12588 pfwinfo->event[BTF_EVNT_RPT],
12589 le16_to_cpu(prptctrl->rpt_info.cnt),
12590 le32_to_cpu(prptctrl->rpt_info.en));
12591
12592 if (dm->error.map.wl_fw_hang)
12593 p += scnprintf(p, end - p, " (WL FW Hang!!)");
12594 p += scnprintf(p, end - p, "\n");
12595 p += scnprintf(p, end - p,
12596 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
12597 "[mailbox]",
12598 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
12599 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
12600 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
12601
12602 p += scnprintf(p, end - p,
12603 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
12604 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
12605 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
12606 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
12607 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
12608 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
12609
12610 p += scnprintf(p, end - p,
12611 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
12612 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ],
12613 wl->wcnt[BTC_WCNT_RFK_GO],
12614 wl->wcnt[BTC_WCNT_RFK_REJECT],
12615 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]);
12616
12617 p += scnprintf(p, end - p,
12618 ", bt_rfk[req:%d]",
12619 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
12620
12621 p += scnprintf(p, end - p,
12622 ", AOAC[RF_on:%d/RF_off:%d]",
12623 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
12624 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
12625 } else {
12626 p += scnprintf(p, end - p,
12627 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
12628 "[summary]", pfwinfo->cnt_h2c,
12629 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
12630 }
12631
12632 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
12633 pfwinfo->err[BTFRE_EXCEPTION]) {
12634 p += scnprintf(p, end - p, "\n");
12635 p += scnprintf(p, end - p,
12636 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
12637 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
12638 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
12639 pfwinfo->fver_mismch,
12640 pfwinfo->err[BTFRE_EXCEPTION],
12641 wl->status.map.lps, wl->status.map.rf_off);
12642 }
12643
12644 for (i = 0; i < BTC_NCNT_NUM; i++)
12645 cnt_sum += dm->cnt_notify[i];
12646
12647 p += scnprintf(p, end - p, "\n");
12648 p += scnprintf(p, end - p,
12649 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
12650 "[notify_cnt]",
12651 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
12652 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
12653
12654 p += scnprintf(p, end - p,
12655 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
12656 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
12657 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
12658 cnt[BTC_NCNT_WL_STA]);
12659
12660 p += scnprintf(p, end - p,
12661 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
12662 "[notify_cnt]",
12663 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
12664 cnt[BTC_NCNT_SWITCH_BAND],
12665 cnt[BTC_NCNT_SPECIAL_PACKET]);
12666
12667 p += scnprintf(p, end - p,
12668 "timer=%d, control=%d, customerize=%d",
12669 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
12670 cnt[BTC_NCNT_CUSTOMERIZE]);
12671
12672 return p - buf;
12673 }
12674
_show_summary_v105(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12675 static int _show_summary_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12676 {
12677 struct rtw89_btc *btc = &rtwdev->btc;
12678 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
12679 struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl;
12680 struct rtw89_btc_rpt_cmn_info *pcinfo;
12681 struct rtw89_btc_cx *cx = &btc->cx;
12682 struct rtw89_btc_dm *dm = &btc->dm;
12683 struct rtw89_btc_wl_info *wl = &cx->wl;
12684 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
12685 char *p = buf, *end = buf + bufsz;
12686 u8 i;
12687
12688 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
12689 return 0;
12690
12691 p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
12692
12693 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
12694 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
12695 prptctrl = &pfwinfo->rpt_ctrl.finfo.v105;
12696
12697 p += scnprintf(p, end - p,
12698 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
12699 "[summary]", pfwinfo->cnt_h2c,
12700 pfwinfo->cnt_h2c_fail,
12701 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
12702 pfwinfo->cnt_c2h,
12703 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
12704 le16_to_cpu(prptctrl->rpt_info.len_c2h));
12705
12706 p += scnprintf(p, end - p,
12707 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
12708 pfwinfo->event[BTF_EVNT_RPT],
12709 le16_to_cpu(prptctrl->rpt_info.cnt),
12710 le32_to_cpu(prptctrl->rpt_info.en));
12711
12712 if (dm->error.map.wl_fw_hang)
12713 p += scnprintf(p, end - p, " (WL FW Hang!!)");
12714 p += scnprintf(p, end - p, "\n");
12715 p += scnprintf(p, end - p,
12716 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
12717 "[mailbox]",
12718 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
12719 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
12720 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
12721
12722 p += scnprintf(p, end - p,
12723 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
12724 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
12725 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
12726 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
12727 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
12728 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
12729
12730 p += scnprintf(p, end - p,
12731 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
12732 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ],
12733 wl->wcnt[BTC_WCNT_RFK_GO],
12734 wl->wcnt[BTC_WCNT_RFK_REJECT],
12735 wl->wcnt[BTC_WCNT_RFK_TIMEOUT]);
12736
12737 p += scnprintf(p, end - p,
12738 ", bt_rfk[req:%d]",
12739 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
12740
12741 p += scnprintf(p, end - p,
12742 ", AOAC[RF_on:%d/RF_off:%d]",
12743 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
12744 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
12745 } else {
12746 p += scnprintf(p, end - p,
12747 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
12748 "[summary]", pfwinfo->cnt_h2c,
12749 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
12750 }
12751
12752 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
12753 pfwinfo->err[BTFRE_EXCEPTION]) {
12754 p += scnprintf(p, end - p, "\n");
12755 p += scnprintf(p, end - p,
12756 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
12757 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
12758 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
12759 pfwinfo->fver_mismch,
12760 pfwinfo->err[BTFRE_EXCEPTION],
12761 wl->status.map.lps, wl->status.map.rf_off);
12762 }
12763
12764 for (i = 0; i < BTC_NCNT_NUM; i++)
12765 cnt_sum += dm->cnt_notify[i];
12766
12767 p += scnprintf(p, end - p, "\n");
12768 p += scnprintf(p, end - p,
12769 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
12770 "[notify_cnt]",
12771 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
12772 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
12773
12774 p += scnprintf(p, end - p,
12775 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
12776 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
12777 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
12778 cnt[BTC_NCNT_WL_STA]);
12779
12780 p += scnprintf(p, end - p,
12781 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
12782 "[notify_cnt]",
12783 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
12784 cnt[BTC_NCNT_SWITCH_BAND],
12785 cnt[BTC_NCNT_SPECIAL_PACKET]);
12786
12787 p += scnprintf(p, end - p,
12788 "timer=%d, control=%d, customerize=%d",
12789 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
12790 cnt[BTC_NCNT_CUSTOMERIZE]);
12791
12792 return p - buf;
12793 }
12794
_show_summary_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12795 static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12796 {
12797 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
12798 struct rtw89_btc_fbtc_rpt_ctrl_v7 *prptctrl = NULL;
12799 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
12800 struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
12801 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
12802 struct rtw89_btc_wl_info *wl = &cx->wl;
12803 u32 *cnt = rtwdev->btc.dm.cnt_notify;
12804 char *p = buf, *end = buf + bufsz;
12805 u32 cnt_sum = 0;
12806 u8 i;
12807
12808 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
12809 return 0;
12810
12811 p += scnprintf(p, end - p, "%s",
12812 "\n========== [Statistics] ==========\n");
12813
12814 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
12815 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
12816 !wl->status.map.rf_off) {
12817 prptctrl = &pfwinfo->rpt_ctrl.finfo.v7;
12818
12819 p += scnprintf(p, end - p,
12820 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d),"
12821 "c2h_cnt=%d(fw_send:%d, len:%d, max:%d), ",
12822 "[summary]", pfwinfo->cnt_h2c,
12823 pfwinfo->cnt_h2c_fail,
12824 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
12825 pfwinfo->cnt_c2h,
12826 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
12827 le16_to_cpu(prptctrl->rpt_info.len_c2h),
12828 rtwdev->btc.ver->info_buf);
12829
12830 p += scnprintf(p, end - p,
12831 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
12832 pfwinfo->event[BTF_EVNT_RPT],
12833 le16_to_cpu(prptctrl->rpt_info.cnt),
12834 le32_to_cpu(prptctrl->rpt_info.en));
12835
12836 if (dm->error.map.wl_fw_hang)
12837 p += scnprintf(p, end - p, " (WL FW Hang!!)");
12838 p += scnprintf(p, end - p, "\n");
12839
12840 p += scnprintf(p, end - p,
12841 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
12842 "[mailbox]",
12843 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
12844 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
12845 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
12846
12847 p += scnprintf(p, end - p,
12848 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n",
12849 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
12850 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
12851 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
12852 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
12853 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
12854
12855 p += scnprintf(p, end - p,
12856 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
12857 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ],
12858 wl->wcnt[BTC_WCNT_RFK_GO],
12859 wl->wcnt[BTC_WCNT_RFK_REJECT],
12860 wl->wcnt[BTC_WCNT_RFK_TIMEOUT],
12861 wl->rfk_info.proc_time);
12862
12863 p += scnprintf(p, end - p, ", bt_rfk[req:%d]",
12864 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
12865
12866 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n",
12867 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
12868 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
12869 } else {
12870 p += scnprintf(p, end - p,
12871 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n",
12872 "[summary]",
12873 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
12874 pfwinfo->cnt_c2h,
12875 wl->status.map.lps, wl->status.map.rf_off);
12876 }
12877
12878 for (i = 0; i < BTC_NCNT_NUM; i++)
12879 cnt_sum += dm->cnt_notify[i];
12880
12881 p += scnprintf(p, end - p,
12882 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
12883 "[notify_cnt]",
12884 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
12885 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
12886
12887 p += scnprintf(p, end - p,
12888 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
12889 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
12890 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
12891 cnt[BTC_NCNT_WL_STA]);
12892
12893 p += scnprintf(p, end - p,
12894 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
12895 "[notify_cnt]",
12896 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
12897 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
12898 cnt[BTC_NCNT_SPECIAL_PACKET]);
12899
12900 p += scnprintf(p, end - p,
12901 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
12902 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
12903 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
12904 cnt[BTC_NCNT_COUNTRYCODE]);
12905
12906 return p - buf;
12907 }
12908
_show_summary_v8(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)12909 static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
12910 {
12911 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
12912 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
12913 struct rtw89_btc_fbtc_rpt_ctrl_v8 *prptctrl = NULL;
12914 struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
12915 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
12916 struct rtw89_btc_wl_info *wl = &cx->wl;
12917 u32 *cnt = rtwdev->btc.dm.cnt_notify;
12918 char *p = buf, *end = buf + bufsz;
12919 u32 cnt_sum = 0;
12920 u8 i;
12921
12922 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
12923 return 0;
12924
12925 p += scnprintf(p, end - p, "%s",
12926 "\n========== [Statistics] ==========\n");
12927
12928 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
12929 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
12930 !wl->status.map.rf_off) {
12931 prptctrl = &pfwinfo->rpt_ctrl.finfo.v8;
12932
12933 p += scnprintf(p, end - p,
12934 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ",
12935 "[summary]", pfwinfo->cnt_h2c,
12936 pfwinfo->cnt_h2c_fail,
12937 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
12938 pfwinfo->cnt_c2h,
12939 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
12940 le16_to_cpu(prptctrl->rpt_info.len_c2h),
12941 (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l,
12942 rtwdev->btc.ver->info_buf);
12943
12944 p += scnprintf(p, end - p,
12945 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
12946 pfwinfo->event[BTF_EVNT_RPT],
12947 le16_to_cpu(prptctrl->rpt_info.cnt),
12948 le32_to_cpu(prptctrl->rpt_info.en));
12949
12950 if (dm->error.map.wl_fw_hang)
12951 p += scnprintf(p, end - p, " (WL FW Hang!!)");
12952 p += scnprintf(p, end - p, "\n");
12953
12954 p += scnprintf(p, end - p,
12955 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
12956 "[mailbox]",
12957 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
12958 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
12959 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
12960
12961 p += scnprintf(p, end - p,
12962 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n",
12963 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
12964 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
12965 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
12966 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
12967 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
12968
12969 p += scnprintf(p, end - p,
12970 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
12971 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ],
12972 wl->wcnt[BTC_WCNT_RFK_GO],
12973 wl->wcnt[BTC_WCNT_RFK_REJECT],
12974 wl->wcnt[BTC_WCNT_RFK_TIMEOUT],
12975 wl->rfk_info.proc_time);
12976
12977 p += scnprintf(p, end - p, ", bt_rfk[req:%d]",
12978 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
12979
12980 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n",
12981 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
12982 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
12983 } else {
12984 p += scnprintf(p, end - p,
12985 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n",
12986 "[summary]",
12987 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
12988 pfwinfo->cnt_c2h,
12989 wl->status.map.lps, wl->status.map.rf_off);
12990 }
12991
12992 for (i = 0; i < BTC_NCNT_NUM; i++)
12993 cnt_sum += dm->cnt_notify[i];
12994
12995 p += scnprintf(p, end - p,
12996 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
12997 "[notify_cnt]",
12998 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
12999 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
13000
13001 p += scnprintf(p, end - p,
13002 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
13003 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
13004 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
13005 cnt[BTC_NCNT_WL_STA]);
13006
13007 p += scnprintf(p, end - p,
13008 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
13009 "[notify_cnt]",
13010 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
13011 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
13012 cnt[BTC_NCNT_SPECIAL_PACKET]);
13013
13014 p += scnprintf(p, end - p,
13015 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
13016 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
13017 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
13018 cnt[BTC_NCNT_COUNTRYCODE]);
13019
13020 return p - buf;
13021 }
13022
_show_summary_v9(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)13023 static int _show_summary_v9(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
13024 {
13025 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
13026 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
13027 struct rtw89_btc_fbtc_rpt_ctrl_v9 *prptctrl = NULL;
13028 struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
13029 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
13030 struct rtw89_btc_wl_info *wl = &cx->wl;
13031 u32 *cnt = rtwdev->btc.dm.cnt_notify;
13032 char *p = buf, *end = buf + bufsz;
13033 u32 cnt_sum = 0;
13034 u8 i;
13035
13036 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
13037 return 0;
13038
13039 p += scnprintf(p, end - p, "%s",
13040 "\n========== [Statistics] ==========\n");
13041
13042 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
13043 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
13044 !wl->status.map.rf_off) {
13045 prptctrl = &pfwinfo->rpt_ctrl.finfo.v9;
13046
13047 p += scnprintf(p, end - p,
13048 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, ",
13049 "[summary]", pfwinfo->cnt_h2c,
13050 pfwinfo->cnt_h2c_fail,
13051 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
13052 pfwinfo->cnt_c2h,
13053 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
13054 le16_to_cpu(prptctrl->rpt_info.len_c2h));
13055
13056 p += scnprintf(p, end - p,
13057 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
13058 pfwinfo->event[BTF_EVNT_RPT],
13059 le16_to_cpu(prptctrl->rpt_info.cnt),
13060 le32_to_cpu(prptctrl->rpt_info.en));
13061
13062 if (dm->error.map.wl_fw_hang)
13063 p += scnprintf(p, end - p, " (WL FW Hang!!)");
13064 p += scnprintf(p, end - p, "\n");
13065
13066 p += scnprintf(p, end - p,
13067 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
13068 "[mailbox]",
13069 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
13070 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
13071 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
13072
13073 p += scnprintf(p, end - p,
13074 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n",
13075 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
13076 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
13077 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
13078 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
13079 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
13080
13081 p += scnprintf(p, end - p,
13082 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
13083 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ],
13084 wl->wcnt[BTC_WCNT_RFK_GO],
13085 wl->wcnt[BTC_WCNT_RFK_REJECT],
13086 wl->wcnt[BTC_WCNT_RFK_TIMEOUT],
13087 wl->rfk_info.proc_time);
13088
13089 p += scnprintf(p, end - p, ", bt_rfk[req:%d]",
13090 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
13091
13092 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n",
13093 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
13094 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
13095 } else {
13096 p += scnprintf(p, end - p,
13097 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n",
13098 "[summary]",
13099 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
13100 pfwinfo->cnt_c2h,
13101 wl->status.map.lps, wl->status.map.rf_off);
13102 }
13103
13104 for (i = 0; i < BTC_NCNT_NUM; i++)
13105 cnt_sum += dm->cnt_notify[i];
13106
13107 p += scnprintf(p, end - p,
13108 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
13109 "[notify_cnt]",
13110 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
13111 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
13112
13113 p += scnprintf(p, end - p,
13114 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
13115 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
13116 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
13117 cnt[BTC_NCNT_WL_STA]);
13118
13119 p += scnprintf(p, end - p,
13120 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
13121 "[notify_cnt]",
13122 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
13123 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
13124 cnt[BTC_NCNT_SPECIAL_PACKET]);
13125
13126 p += scnprintf(p, end - p,
13127 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
13128 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
13129 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
13130 cnt[BTC_NCNT_COUNTRYCODE]);
13131
13132 return p - buf;
13133 }
13134
_show_summary_v11(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)13135 static int _show_summary_v11(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
13136 {
13137 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
13138 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
13139 struct rtw89_btc_fbtc_rpt_ctrl_v11 *prptctrl = NULL;
13140 struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
13141 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
13142 struct rtw89_btc_wl_info *wl = &cx->wl;
13143 u32 *cnt = rtwdev->btc.dm.cnt_notify;
13144 char *p = buf, *end = buf + bufsz;
13145 u32 cnt_sum = 0;
13146 u8 i;
13147
13148 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
13149 return 0;
13150
13151 p += scnprintf(p, end - p, "%s",
13152 "\n========== [Statistics] ==========\n");
13153
13154 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
13155 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
13156 !wl->status.map.rf_off) {
13157 prptctrl = &pfwinfo->rpt_ctrl.finfo.v11;
13158
13159 p += scnprintf(p, end - p,
13160 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ",
13161 "[summary]", pfwinfo->cnt_h2c,
13162 pfwinfo->cnt_h2c_fail,
13163 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
13164 pfwinfo->cnt_c2h,
13165 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
13166 le16_to_cpu(prptctrl->rpt_info.len_c2h),
13167 (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l,
13168 rtwdev->btc.ver->info_buf);
13169
13170 p += scnprintf(p, end - p,
13171 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
13172 pfwinfo->event[BTF_EVNT_RPT],
13173 le16_to_cpu(prptctrl->rpt_info.cnt),
13174 le32_to_cpu(prptctrl->rpt_info.en));
13175
13176 if (dm->error.map.wl_fw_hang)
13177 p += scnprintf(p, end - p, " (WL FW Hang!!)");
13178 p += scnprintf(p, end - p, "\n");
13179
13180 p += scnprintf(p, end - p,
13181 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
13182 "[mailbox]",
13183 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
13184 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
13185 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
13186
13187 p += scnprintf(p, end - p,
13188 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)\n",
13189 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
13190 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
13191 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
13192 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
13193 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
13194
13195 p += scnprintf(p, end - p,
13196 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
13197 "[RFK/LPS]", wl->wcnt[BTC_WCNT_RFK_REQ],
13198 wl->wcnt[BTC_WCNT_RFK_GO],
13199 wl->wcnt[BTC_WCNT_RFK_REJECT],
13200 wl->wcnt[BTC_WCNT_RFK_TIMEOUT],
13201 wl->rfk_info.proc_time);
13202
13203 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]\n",
13204 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
13205 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
13206 } else {
13207 p += scnprintf(p, end - p,
13208 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)\n",
13209 "[summary]",
13210 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
13211 pfwinfo->cnt_c2h,
13212 wl->status.map.lps, wl->status.map.rf_off);
13213 }
13214
13215 for (i = 0; i < BTC_NCNT_NUM; i++)
13216 cnt_sum += dm->cnt_notify[i];
13217
13218 p += scnprintf(p, end - p,
13219 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
13220 "[notify_cnt]",
13221 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
13222 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
13223
13224 p += scnprintf(p, end - p,
13225 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
13226 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
13227 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
13228 cnt[BTC_NCNT_WL_STA]);
13229
13230 p += scnprintf(p, end - p,
13231 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
13232 "[notify_cnt]",
13233 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
13234 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
13235 cnt[BTC_NCNT_SPECIAL_PACKET]);
13236
13237 p += scnprintf(p, end - p,
13238 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
13239 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
13240 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
13241 cnt[BTC_NCNT_COUNTRYCODE]);
13242
13243 return p - buf;
13244 }
13245
rtw89_btc_dump_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)13246 ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
13247 {
13248 struct rtw89_btc *btc = &rtwdev->btc;
13249 struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver;
13250 const struct rtw89_btc_ver *ver = btc->ver;
13251 struct rtw89_btc_dm *dm = &btc->dm;
13252 char *p = buf, *end = buf + bufsz;
13253
13254 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
13255
13256 p += scnprintf(p, end - p,
13257 "\n\n\n** Page:%3d/RunCNT:%3d **",
13258 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO],
13259 dm->cnt_dm[BTC_DCNT_RUN]);
13260 p += scnprintf(p, end - p,
13261 "\n========== [BTC FEATURE SUB VER] ==========");
13262 p += scnprintf(p, end - p,
13263 "\n %-15s : fcxbtcrpt[%d/%d], fcxtdma[%d/%d], fcxslots[%d/%d], fcxcysta[%d/%d]",
13264 "[FW/DRV]", fwsubver->fcxbtcrpt, ver->fcxbtcrpt,
13265 fwsubver->fcxtdma, ver->fcxtdma, fwsubver->fcxslots,
13266 ver->fcxslots, fwsubver->fcxcysta, ver->fcxcysta);
13267 p += scnprintf(p, end - p,
13268 "\n %-15s : fcxstep[%d/%d], fcxnullsta[%d/%d], fcxmreg[%d/%d], fcxgpiodbg[%d/%d]",
13269 "[FW/DRV]", fwsubver->fcxstep, ver->fcxstep,
13270 fwsubver->fcxnullsta, ver->fcxnullsta, fwsubver->fcxmreg,
13271 ver->fcxmreg, fwsubver->fcxgpiodbg, ver->fcxgpiodbg);
13272 p += scnprintf(p, end - p,
13273 "\n %-15s : fcxbtver[%d/%d], fcxbtscan[%d/%d], fcxbtafh[%d/%d], fcxbtdevinfo[%d/%d]",
13274 "[FW/DRV]", fwsubver->fcxbtver, ver->fcxbtver,
13275 fwsubver->fcxbtscan, ver->fcxbtscan, fwsubver->fcxbtafh,
13276 ver->fcxbtafh, fwsubver->fcxbtdevinfo, ver->fcxbtdevinfo);
13277 p += scnprintf(p, end - p,
13278 "\n %-15s : fcxosi[%d/%d], fcxmlo[%d/%d],",
13279 "[FW/DRV]", fwsubver->fcxosi, ver->fcxosi,
13280 fwsubver->fcxmlo, ver->fcxmlo);
13281
13282 p += _show_cx_info(rtwdev, p, end - p);
13283 p += _show_wl_info(rtwdev, p, end - p);
13284 p += _show_bt_info(rtwdev, p, end - p, BTC_BT_1ST);
13285 p += _show_bt_info(rtwdev, p, end - p, BTC_BT_2ND);
13286 p += _show_dm_info(rtwdev, p, end - p);
13287 p += _show_fw_dm_msg(rtwdev, p, end - p);
13288
13289 if (ver->fcxmreg == 1)
13290 p += _show_mreg_v1(rtwdev, p, end - p);
13291 else if (ver->fcxmreg == 2)
13292 p += _show_mreg_v2(rtwdev, p, end - p);
13293 else if (ver->fcxmreg == 7)
13294 p += _show_mreg_v7(rtwdev, p, end - p);
13295
13296 p += _show_gpio_dbg(rtwdev, p, end - p);
13297
13298 if (ver->fcxbtcrpt == 1)
13299 p += _show_summary_v1(rtwdev, p, end - p);
13300 else if (ver->fcxbtcrpt == 4)
13301 p += _show_summary_v4(rtwdev, p, end - p);
13302 else if (ver->fcxbtcrpt == 5)
13303 p += _show_summary_v5(rtwdev, p, end - p);
13304 else if (ver->fcxbtcrpt == 105)
13305 p += _show_summary_v105(rtwdev, p, end - p);
13306 else if (ver->fcxbtcrpt == 7)
13307 p += _show_summary_v7(rtwdev, p, end - p);
13308 else if (ver->fcxbtcrpt == 8)
13309 p += _show_summary_v8(rtwdev, p, end - p);
13310 else if (ver->fcxbtcrpt == 9)
13311 p += _show_summary_v9(rtwdev, p, end - p);
13312 else if (ver->fcxbtcrpt == 11)
13313 p += _show_summary_v11(rtwdev, p, end - p);
13314
13315 p += scnprintf(p, end - p, "\n");
13316
13317 return p - buf;
13318 }
13319
rtw89_coex_recognize_ver(struct rtw89_dev * rtwdev)13320 void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev)
13321 {
13322 const struct rtw89_chip_info *chip = rtwdev->chip;
13323 struct rtw89_btc *btc = &rtwdev->btc;
13324 const struct rtw89_btc_ver *btc_ver_def;
13325 const struct rtw89_fw_suit *fw_suit;
13326 u32 suit_ver_code;
13327 int i;
13328
13329 fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL);
13330 suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit);
13331
13332 for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) {
13333 btc_ver_def = &rtw89_btc_ver_defs[i];
13334
13335 if (chip->chip_id != btc_ver_def->chip_id)
13336 continue;
13337
13338 if (suit_ver_code >= btc_ver_def->fw_ver_code) {
13339 btc->ver = btc_ver_def;
13340 goto out;
13341 }
13342 }
13343
13344 btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX];
13345
13346 out:
13347 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n",
13348 (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code);
13349 }
13350
rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev * rtwdev,u32 ms)13351 void rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev *rtwdev, u32 ms)
13352 {
13353 struct rtw89_btc_bt_link_info *bt_linfo = &rtwdev->btc.cx.bt0.link_info;
13354 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
13355
13356 if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags))
13357 return;
13358
13359 if (!a2dp.exist)
13360 return;
13361
13362 fsleep(ms * 1000);
13363 }
13364 EXPORT_SYMBOL(rtw89_btc_ntfy_preserve_bt_time);
13365
rtw89_btc_ntfy_conn_rfk(struct rtw89_dev * rtwdev,bool state)13366 void rtw89_btc_ntfy_conn_rfk(struct rtw89_dev *rtwdev, bool state)
13367 {
13368 rtwdev->btc.cx.wl.rfk_info.con_rfk = state;
13369 }
13370 EXPORT_SYMBOL(rtw89_btc_ntfy_conn_rfk);
13371