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 0x09000013
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, 0xaaaaaaaa, SLOT_ISO),
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 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 122, 0),
137 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
138 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
139 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
140 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
141 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
142 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
143 },
144 {RTL8852BT, RTW89_FW_VER_CODE(0, 29, 90, 0),
145 .fcxbtcrpt = 7, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
146 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
147 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
148 .fwlrole = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
149 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
150 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
151 },
152 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 71, 0),
153 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
154 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
155 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
156 .fwlrole = 8, .frptmap = 4, .fcxctrl = 7, .fcxinit = 7,
157 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_type = 2, .info_buf = 1800,
158 .max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9,
159 },
160 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 63, 0),
161 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
162 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
163 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
164 .fwlrole = 8, .frptmap = 4, .fcxctrl = 7, .fcxinit = 7,
165 .fwevntrptl = 1, .fwc2hfunc = 3, .drvinfo_type = 2, .info_buf = 1800,
166 .max_role_num = 6, .fcxosi = 1, .fcxmlo = 1, .bt_desired = 9,
167 },
168 {RTL8922A, RTW89_FW_VER_CODE(0, 35, 8, 0),
169 .fcxbtcrpt = 8, .fcxtdma = 7, .fcxslots = 7, .fcxcysta = 7,
170 .fcxstep = 7, .fcxnullsta = 7, .fcxmreg = 7, .fcxgpiodbg = 7,
171 .fcxbtver = 7, .fcxbtscan = 7, .fcxbtafh = 7, .fcxbtdevinfo = 7,
172 .fwlrole = 8, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
173 .fwevntrptl = 1, .fwc2hfunc = 1, .drvinfo_type = 1, .info_buf = 1800,
174 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
175 },
176 {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0),
177 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5,
178 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1,
179 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1,
180 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
181 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
182 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
183 },
184 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0),
185 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
186 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
187 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
188 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
189 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
190 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
191 },
192 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 42, 0),
193 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
194 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
195 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
196 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0,
197 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
198 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
199 },
200 {RTL8852C, RTW89_FW_VER_CODE(0, 27, 0, 0),
201 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
202 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
203 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
204 .fwlrole = 1, .frptmap = 2, .fcxctrl = 1, .fcxinit = 0,
205 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
206 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
207 },
208 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 122, 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 = 7, .frptmap = 3, .fcxctrl = 7, .fcxinit = 7,
213 .fwevntrptl = 1, .fwc2hfunc = 2, .drvinfo_type = 1, .info_buf = 1800,
214 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 8,
215 },
216 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 29, 0),
217 .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5,
218 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1,
219 .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1,
220 .fwlrole = 2, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
221 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
222 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
223 },
224 {RTL8852B, RTW89_FW_VER_CODE(0, 29, 14, 0),
225 .fcxbtcrpt = 5, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 4,
226 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
227 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
228 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
229 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1800,
230 .max_role_num = 6, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
231 },
232 {RTL8852B, RTW89_FW_VER_CODE(0, 27, 0, 0),
233 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
234 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
235 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
236 .fwlrole = 1, .frptmap = 1, .fcxctrl = 1, .fcxinit = 0,
237 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1280,
238 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
239 },
240 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 37, 0),
241 .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3,
242 .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1,
243 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 2, .fcxbtdevinfo = 1,
244 .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, .fcxinit = 0,
245 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1280,
246 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
247 },
248 {RTL8852A, RTW89_FW_VER_CODE(0, 13, 0, 0),
249 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2,
250 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1,
251 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
252 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0,
253 .fwevntrptl = 0, .fwc2hfunc = 0, .drvinfo_type = 0, .info_buf = 1024,
254 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
255 },
256
257 /* keep it to be the last as default entry */
258 {0, RTW89_FW_VER_CODE(0, 0, 0, 0),
259 .fcxbtcrpt = 1, .fcxtdma = 1, .fcxslots = 1, .fcxcysta = 2,
260 .fcxstep = 2, .fcxnullsta = 1, .fcxmreg = 1, .fcxgpiodbg = 1,
261 .fcxbtver = 1, .fcxbtscan = 1, .fcxbtafh = 1, .fcxbtdevinfo = 1,
262 .fwlrole = 0, .frptmap = 0, .fcxctrl = 0, .fcxinit = 0,
263 .fwevntrptl = 0, .fwc2hfunc = 1, .drvinfo_type = 0, .info_buf = 1024,
264 .max_role_num = 5, .fcxosi = 0, .fcxmlo = 0, .bt_desired = 7,
265 },
266 };
267
268 #define RTW89_DEFAULT_BTC_VER_IDX (ARRAY_SIZE(rtw89_btc_ver_defs) - 1)
269
270 static const union rtw89_btc_wl_state_map btc_scanning_map = {
271 .map = {
272 .scan = 1,
273 .connecting = 1,
274 .roaming = 1,
275 .dbccing = 1,
276 ._4way = 1,
277 },
278 };
279
chip_id_to_bt_rom_code_id(u32 id)280 static u32 chip_id_to_bt_rom_code_id(u32 id)
281 {
282 switch (id) {
283 case RTL8852A:
284 case RTL8852B:
285 case RTL8852C:
286 case RTL8852BT:
287 return 0x8852;
288 case RTL8851B:
289 return 0x8851;
290 case RTL8922A:
291 return 0x8922;
292 default:
293 return 0;
294 }
295 }
296
297 #define CASE_BTC_MLME_STATE(e) case MLME_##e: return #e
298
id_to_mlme_state(u32 id)299 static const char *id_to_mlme_state(u32 id)
300 {
301 switch (id) {
302 CASE_BTC_MLME_STATE(NO_LINK);
303 CASE_BTC_MLME_STATE(LINKING);
304 CASE_BTC_MLME_STATE(LINKED);
305 default:
306 return "unknown";
307 }
308 }
309
chip_id_str(u32 id)310 static char *chip_id_str(u32 id)
311 {
312 switch (id) {
313 case RTL8852A:
314 return "RTL8852A";
315 case RTL8852B:
316 return "RTL8852B";
317 case RTL8852C:
318 return "RTL8852C";
319 case RTL8852BT:
320 return "RTL8852BT";
321 case RTL8851B:
322 return "RTL8851B";
323 case RTL8922A:
324 return "RTL8922A";
325 default:
326 return "UNKNOWN";
327 }
328 }
329
330 struct rtw89_btc_btf_tlv {
331 u8 type;
332 u8 len;
333 u8 val[];
334 } __packed;
335
336 struct rtw89_btc_btf_tlv_v7 {
337 u8 type;
338 u8 ver;
339 u8 len;
340 u8 val[];
341 } __packed;
342
343 enum btc_btf_set_report_en {
344 RPT_EN_TDMA,
345 RPT_EN_CYCLE,
346 RPT_EN_MREG,
347 RPT_EN_BT_VER_INFO,
348 RPT_EN_BT_SCAN_INFO,
349 RPT_EN_BT_DEVICE_INFO,
350 RPT_EN_BT_AFH_MAP,
351 RPT_EN_BT_AFH_MAP_LE,
352 RPT_EN_BT_TX_PWR_LVL,
353 RPT_EN_FW_STEP_INFO,
354 RPT_EN_TEST,
355 RPT_EN_WL_ALL,
356 RPT_EN_BT_ALL,
357 RPT_EN_ALL,
358 RPT_EN_MONITER,
359 };
360
361 struct rtw89_btc_btf_set_report_v1 {
362 u8 fver;
363 __le32 enable;
364 __le32 para;
365 } __packed;
366
367 struct rtw89_btc_btf_set_report_v8 {
368 u8 type;
369 u8 fver;
370 u8 len;
371 __le32 map;
372 } __packed;
373
374 union rtw89_fbtc_rtp_ctrl {
375 struct rtw89_btc_btf_set_report_v1 v1;
376 struct rtw89_btc_btf_set_report_v8 v8;
377 };
378
379 #define BTF_SET_SLOT_TABLE_VER 1
380 struct rtw89_btc_btf_set_slot_table {
381 u8 fver;
382 u8 tbl_num;
383 struct rtw89_btc_fbtc_slot tbls[] __counted_by(tbl_num);
384 } __packed;
385
386 struct rtw89_btc_btf_set_slot_table_v7 {
387 u8 type;
388 u8 ver;
389 u8 len;
390 struct rtw89_btc_fbtc_slot_v7 v7[CXST_MAX];
391 } __packed;
392
393 struct rtw89_btc_btf_set_mon_reg_v1 {
394 u8 fver;
395 u8 reg_num;
396 struct rtw89_btc_fbtc_mreg regs[] __counted_by(reg_num);
397 } __packed;
398
399 struct rtw89_btc_btf_set_mon_reg_v7 {
400 u8 type;
401 u8 fver;
402 u8 len;
403 struct rtw89_btc_fbtc_mreg regs[] __counted_by(len);
404 } __packed;
405
406 union rtw89_fbtc_set_mon_reg {
407 struct rtw89_btc_btf_set_mon_reg_v1 v1;
408 struct rtw89_btc_btf_set_mon_reg_v7 v7;
409 } __packed;
410
411 struct _wl_rinfo_now {
412 u8 link_mode;
413 u32 dbcc_2g_phy: 2;
414 };
415
416 enum btc_btf_set_cx_policy {
417 CXPOLICY_TDMA = 0x0,
418 CXPOLICY_SLOT = 0x1,
419 CXPOLICY_TYPE = 0x2,
420 CXPOLICY_MAX,
421 };
422
423 enum btc_b2w_scoreboard {
424 BTC_BSCB_ACT = BIT(0),
425 BTC_BSCB_ON = BIT(1),
426 BTC_BSCB_WHQL = BIT(2),
427 BTC_BSCB_BT_S1 = BIT(3),
428 BTC_BSCB_A2DP_ACT = BIT(4),
429 BTC_BSCB_RFK_RUN = BIT(5),
430 BTC_BSCB_RFK_REQ = BIT(6),
431 BTC_BSCB_LPS = BIT(7),
432 BTC_BSCB_BT_LNAB0 = BIT(8),
433 BTC_BSCB_BT_LNAB1 = BIT(10),
434 BTC_BSCB_WLRFK = BIT(11),
435 BTC_BSCB_BT_HILNA = BIT(13),
436 BTC_BSCB_BT_CONNECT = BIT(16),
437 BTC_BSCB_PATCH_CODE = BIT(30),
438 BTC_BSCB_ALL = GENMASK(30, 0),
439 };
440
441 enum btc_phymap {
442 BTC_PHY_0 = BIT(0),
443 BTC_PHY_1 = BIT(1),
444 BTC_PHY_ALL = BIT(0) | BIT(1),
445 };
446
447 enum btc_cx_state_map {
448 BTC_WIDLE = 0,
449 BTC_WBUSY_BNOSCAN,
450 BTC_WBUSY_BSCAN,
451 BTC_WSCAN_BNOSCAN,
452 BTC_WSCAN_BSCAN,
453 BTC_WLINKING
454 };
455
456 enum btc_ant_phase {
457 BTC_ANT_WPOWERON = 0,
458 BTC_ANT_WINIT,
459 BTC_ANT_WONLY,
460 BTC_ANT_WOFF,
461 BTC_ANT_W2G,
462 BTC_ANT_W5G,
463 BTC_ANT_W25G,
464 BTC_ANT_FREERUN,
465 BTC_ANT_WRFK,
466 BTC_ANT_WRFK2,
467 BTC_ANT_BRFK,
468 BTC_ANT_MAX
469 };
470
471 enum btc_plt {
472 BTC_PLT_NONE = 0,
473 BTC_PLT_LTE_RX = BIT(0),
474 BTC_PLT_GNT_BT_TX = BIT(1),
475 BTC_PLT_GNT_BT_RX = BIT(2),
476 BTC_PLT_GNT_WL = BIT(3),
477 BTC_PLT_BT = BIT(1) | BIT(2),
478 BTC_PLT_ALL = 0xf
479 };
480
481 enum btc_cx_poicy_main_type {
482 BTC_CXP_OFF = 0,
483 BTC_CXP_OFFB,
484 BTC_CXP_OFFE,
485 BTC_CXP_FIX,
486 BTC_CXP_PFIX,
487 BTC_CXP_AUTO,
488 BTC_CXP_PAUTO,
489 BTC_CXP_AUTO2,
490 BTC_CXP_PAUTO2,
491 BTC_CXP_MANUAL,
492 BTC_CXP_USERDEF0,
493 BTC_CXP_MAIN_MAX
494 };
495
496 enum btc_cx_poicy_type {
497 /* TDMA off + pri: BT > WL */
498 BTC_CXP_OFF_BT = (BTC_CXP_OFF << 8) | 0,
499
500 /* TDMA off + pri: WL > BT */
501 BTC_CXP_OFF_WL = (BTC_CXP_OFF << 8) | 1,
502
503 /* TDMA off + pri: BT = WL */
504 BTC_CXP_OFF_EQ0 = (BTC_CXP_OFF << 8) | 2,
505
506 /* TDMA off + pri: BT = WL > BT_Lo */
507 BTC_CXP_OFF_EQ1 = (BTC_CXP_OFF << 8) | 3,
508
509 /* TDMA off + pri: WL = BT, BT_Rx > WL_Lo_Tx */
510 BTC_CXP_OFF_EQ2 = (BTC_CXP_OFF << 8) | 4,
511
512 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
513 BTC_CXP_OFF_EQ3 = (BTC_CXP_OFF << 8) | 5,
514
515 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
516 BTC_CXP_OFF_EQ4 = (BTC_CXP_OFF << 8) | 6,
517
518 /* TDMA off + pri: WL_Rx = BT, BT_HI > WL_Tx > BT_Lo */
519 BTC_CXP_OFF_EQ5 = (BTC_CXP_OFF << 8) | 7,
520
521 /* TDMA off + pri: BT_Hi > WL > BT_Lo */
522 BTC_CXP_OFF_BWB0 = (BTC_CXP_OFF << 8) | 8,
523
524 /* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
525 BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 9,
526
527 /* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
528 BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 10,
529
530 /* TDMA off + pri: WL_Hi-Tx = BT */
531 BTC_CXP_OFF_BWB3 = (BTC_CXP_OFF << 8) | 11,
532
533 /* TDMA off + pri: WL > BT, Block-BT*/
534 BTC_CXP_OFF_WL2 = (BTC_CXP_OFF << 8) | 12,
535
536 /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/
537 BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
538
539 /* TDMA off + Ext-Ctrl + pri: default */
540 BTC_CXP_OFFE_DEF = (BTC_CXP_OFFE << 8) | 0,
541
542 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
543 BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1,
544
545 /* TDMA off + Ext-Ctrl + pri: default */
546 BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2,
547
548 /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
549 BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3,
550
551 /* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */
552 BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4,
553
554 /* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */
555 BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5,
556
557 /* TDMA off + Ext-Ctrl + pri: default */
558 BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6,
559
560 /* TDMA Fix slot-0: W1:B1 = 30:30 */
561 BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0,
562
563 /* TDMA Fix slot-1: W1:B1 = 50:50 */
564 BTC_CXP_FIX_TD5050 = (BTC_CXP_FIX << 8) | 1,
565
566 /* TDMA Fix slot-2: W1:B1 = 20:30 */
567 BTC_CXP_FIX_TD2030 = (BTC_CXP_FIX << 8) | 2,
568
569 /* TDMA Fix slot-3: W1:B1 = 40:10 */
570 BTC_CXP_FIX_TD4010 = (BTC_CXP_FIX << 8) | 3,
571
572 /* TDMA Fix slot-4: W1:B1 = 70:10 */
573 BTC_CXP_FIX_TD7010 = (BTC_CXP_FIX << 8) | 4,
574
575 /* TDMA Fix slot-5: W1:B1 = 20:60 */
576 BTC_CXP_FIX_TD2060 = (BTC_CXP_FIX << 8) | 5,
577
578 /* TDMA Fix slot-6: W1:B1 = 30:60 */
579 BTC_CXP_FIX_TD3060 = (BTC_CXP_FIX << 8) | 6,
580
581 /* TDMA Fix slot-7: W1:B1 = 20:80 */
582 BTC_CXP_FIX_TD2080 = (BTC_CXP_FIX << 8) | 7,
583
584 /* TDMA Fix slot-8: W1:B1 = user-define */
585 BTC_CXP_FIX_TDW1B1 = (BTC_CXP_FIX << 8) | 8,
586
587 /* TDMA Fix slot-9: W1:B1 = 40:10 */
588 BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 9,
589
590 /* TDMA Fix slot-10: W1:B1 = 40:10 */
591 BTC_CXP_FIX_TD4010ISO_DL = (BTC_CXP_FIX << 8) | 10,
592
593 /* TDMA Fix slot-11: W1:B1 = 40:10 */
594 BTC_CXP_FIX_TD4010ISO_UL = (BTC_CXP_FIX << 8) | 11,
595
596 /* PS-TDMA Fix slot-0: W1:B1 = 30:30 */
597 BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0,
598
599 /* PS-TDMA Fix slot-1: W1:B1 = 50:50 */
600 BTC_CXP_PFIX_TD5050 = (BTC_CXP_PFIX << 8) | 1,
601
602 /* PS-TDMA Fix slot-2: W1:B1 = 20:30 */
603 BTC_CXP_PFIX_TD2030 = (BTC_CXP_PFIX << 8) | 2,
604
605 /* PS-TDMA Fix slot-3: W1:B1 = 20:60 */
606 BTC_CXP_PFIX_TD2060 = (BTC_CXP_PFIX << 8) | 3,
607
608 /* PS-TDMA Fix slot-4: W1:B1 = 30:70 */
609 BTC_CXP_PFIX_TD3070 = (BTC_CXP_PFIX << 8) | 4,
610
611 /* PS-TDMA Fix slot-5: W1:B1 = 20:80 */
612 BTC_CXP_PFIX_TD2080 = (BTC_CXP_PFIX << 8) | 5,
613
614 /* PS-TDMA Fix slot-6: W1:B1 = user-define */
615 BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6,
616
617 /* TDMA Auto slot-0: W1:B1 = 50:200 */
618 BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0,
619
620 /* TDMA Auto slot-1: W1:B1 = 60:200 */
621 BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1,
622
623 /* TDMA Auto slot-2: W1:B1 = 20:200 */
624 BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2,
625
626 /* TDMA Auto slot-3: W1:B1 = user-define */
627 BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3,
628
629 /* PS-TDMA Auto slot-0: W1:B1 = 50:200 */
630 BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0,
631
632 /* PS-TDMA Auto slot-1: W1:B1 = 60:200 */
633 BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1,
634
635 /* PS-TDMA Auto slot-2: W1:B1 = 20:200 */
636 BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2,
637
638 /* PS-TDMA Auto slot-3: W1:B1 = user-define */
639 BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3,
640
641 /* TDMA Auto slot2-0: W1:B4 = 30:50 */
642 BTC_CXP_AUTO2_TD3050 = (BTC_CXP_AUTO2 << 8) | 0,
643
644 /* TDMA Auto slot2-1: W1:B4 = 30:70 */
645 BTC_CXP_AUTO2_TD3070 = (BTC_CXP_AUTO2 << 8) | 1,
646
647 /* TDMA Auto slot2-2: W1:B4 = 50:50 */
648 BTC_CXP_AUTO2_TD5050 = (BTC_CXP_AUTO2 << 8) | 2,
649
650 /* TDMA Auto slot2-3: W1:B4 = 60:60 */
651 BTC_CXP_AUTO2_TD6060 = (BTC_CXP_AUTO2 << 8) | 3,
652
653 /* TDMA Auto slot2-4: W1:B4 = 20:80 */
654 BTC_CXP_AUTO2_TD2080 = (BTC_CXP_AUTO2 << 8) | 4,
655
656 /* TDMA Auto slot2-5: W1:B4 = user-define */
657 BTC_CXP_AUTO2_TDW1B4 = (BTC_CXP_AUTO2 << 8) | 5,
658
659 /* PS-TDMA Auto slot2-0: W1:B4 = 30:50 */
660 BTC_CXP_PAUTO2_TD3050 = (BTC_CXP_PAUTO2 << 8) | 0,
661
662 /* PS-TDMA Auto slot2-1: W1:B4 = 30:70 */
663 BTC_CXP_PAUTO2_TD3070 = (BTC_CXP_PAUTO2 << 8) | 1,
664
665 /* PS-TDMA Auto slot2-2: W1:B4 = 50:50 */
666 BTC_CXP_PAUTO2_TD5050 = (BTC_CXP_PAUTO2 << 8) | 2,
667
668 /* PS-TDMA Auto slot2-3: W1:B4 = 60:60 */
669 BTC_CXP_PAUTO2_TD6060 = (BTC_CXP_PAUTO2 << 8) | 3,
670
671 /* PS-TDMA Auto slot2-4: W1:B4 = 20:80 */
672 BTC_CXP_PAUTO2_TD2080 = (BTC_CXP_PAUTO2 << 8) | 4,
673
674 /* PS-TDMA Auto slot2-5: W1:B4 = user-define */
675 BTC_CXP_PAUTO2_TDW1B4 = (BTC_CXP_PAUTO2 << 8) | 5,
676
677 BTC_CXP_MAX = 0xffff
678 };
679
680 enum btc_wl_rfk_result {
681 BTC_WRFK_REJECT = 0,
682 BTC_WRFK_ALLOW = 1,
683 };
684
685 enum btc_coex_info_map_en {
686 BTC_COEX_INFO_CX = BIT(0),
687 BTC_COEX_INFO_WL = BIT(1),
688 BTC_COEX_INFO_BT = BIT(2),
689 BTC_COEX_INFO_DM = BIT(3),
690 BTC_COEX_INFO_MREG = BIT(4),
691 BTC_COEX_INFO_SUMMARY = BIT(5),
692 BTC_COEX_INFO_ALL = GENMASK(7, 0),
693 };
694
695 #define BTC_CXP_MASK GENMASK(15, 8)
696
697 enum btc_w2b_scoreboard {
698 BTC_WSCB_ACTIVE = BIT(0),
699 BTC_WSCB_ON = BIT(1),
700 BTC_WSCB_SCAN = BIT(2),
701 BTC_WSCB_UNDERTEST = BIT(3),
702 BTC_WSCB_RXGAIN = BIT(4),
703 BTC_WSCB_WLBUSY = BIT(7),
704 BTC_WSCB_EXTFEM = BIT(8),
705 BTC_WSCB_TDMA = BIT(9),
706 BTC_WSCB_FIX2M = BIT(10),
707 BTC_WSCB_WLRFK = BIT(11),
708 BTC_WSCB_RXSCAN_PRI = BIT(12),
709 BTC_WSCB_BT_HILNA = BIT(13),
710 BTC_WSCB_BTLOG = BIT(14),
711 BTC_WSCB_ALL = GENMASK(23, 0),
712 };
713
714 enum btc_wl_link_mode {
715 BTC_WLINK_NOLINK = 0x0,
716 BTC_WLINK_2G_STA,
717 BTC_WLINK_2G_AP,
718 BTC_WLINK_2G_GO,
719 BTC_WLINK_2G_GC,
720 BTC_WLINK_2G_SCC,
721 BTC_WLINK_2G_MCC,
722 BTC_WLINK_25G_MCC,
723 BTC_WLINK_25G_DBCC,
724 BTC_WLINK_5G,
725 BTC_WLINK_2G_NAN,
726 BTC_WLINK_OTHER,
727 BTC_WLINK_MAX
728 };
729
730 #define CASE_BTC_WL_LINK_MODE(e) case BTC_WLINK_## e: return #e
731
id_to_linkmode(u8 id)732 static const char *id_to_linkmode(u8 id)
733 {
734 switch (id) {
735 CASE_BTC_WL_LINK_MODE(NOLINK);
736 CASE_BTC_WL_LINK_MODE(2G_STA);
737 CASE_BTC_WL_LINK_MODE(2G_AP);
738 CASE_BTC_WL_LINK_MODE(2G_GO);
739 CASE_BTC_WL_LINK_MODE(2G_GC);
740 CASE_BTC_WL_LINK_MODE(2G_SCC);
741 CASE_BTC_WL_LINK_MODE(2G_MCC);
742 CASE_BTC_WL_LINK_MODE(25G_MCC);
743 CASE_BTC_WL_LINK_MODE(25G_DBCC);
744 CASE_BTC_WL_LINK_MODE(5G);
745 CASE_BTC_WL_LINK_MODE(OTHER);
746 default:
747 return "unknown";
748 }
749 }
750
751 enum btc_wl_mrole_type {
752 BTC_WLMROLE_NONE = 0x0,
753 BTC_WLMROLE_STA_GC,
754 BTC_WLMROLE_STA_GC_NOA,
755 BTC_WLMROLE_STA_GO,
756 BTC_WLMROLE_STA_GO_NOA,
757 BTC_WLMROLE_STA_STA,
758 BTC_WLMROLE_MAX
759 };
760
761 enum btc_bt_hid_type {
762 BTC_HID_218 = BIT(0),
763 BTC_HID_418 = BIT(1),
764 BTC_HID_BLE = BIT(2),
765 BTC_HID_RCU = BIT(3),
766 BTC_HID_RCU_VOICE = BIT(4),
767 BTC_HID_OTHER_LEGACY = BIT(5)
768 };
769
770 enum btc_reset_module {
771 BTC_RESET_CX = BIT(0),
772 BTC_RESET_DM = BIT(1),
773 BTC_RESET_CTRL = BIT(2),
774 BTC_RESET_CXDM = BIT(0) | BIT(1),
775 BTC_RESET_BTINFO = BIT(3),
776 BTC_RESET_MDINFO = BIT(4),
777 BTC_RESET_ALL = GENMASK(7, 0),
778 };
779
780 enum btc_gnt_state {
781 BTC_GNT_HW = 0,
782 BTC_GNT_SW_LO,
783 BTC_GNT_SW_HI,
784 BTC_GNT_MAX
785 };
786
787 enum btc_ctr_path {
788 BTC_CTRL_BY_BT = 0,
789 BTC_CTRL_BY_WL
790 };
791
792 enum btc_wlact_state {
793 BTC_WLACT_HW = 0,
794 BTC_WLACT_SW_LO,
795 BTC_WLACT_SW_HI,
796 BTC_WLACT_MAX,
797 };
798
799 enum btc_wl_max_tx_time {
800 BTC_MAX_TX_TIME_L1 = 500,
801 BTC_MAX_TX_TIME_L2 = 1000,
802 BTC_MAX_TX_TIME_L3 = 2000,
803 BTC_MAX_TX_TIME_DEF = 5280
804 };
805
806 enum btc_wl_max_tx_retry {
807 BTC_MAX_TX_RETRY_L1 = 7,
808 BTC_MAX_TX_RETRY_L2 = 15,
809 BTC_MAX_TX_RETRY_DEF = 31,
810 };
811
812 enum btc_reason_and_action {
813 BTC_RSN_NONE,
814 BTC_RSN_NTFY_INIT,
815 BTC_RSN_NTFY_SWBAND,
816 BTC_RSN_NTFY_WL_STA,
817 BTC_RSN_NTFY_RADIO_STATE,
818 BTC_RSN_UPDATE_BT_SCBD,
819 BTC_RSN_NTFY_WL_RFK,
820 BTC_RSN_UPDATE_BT_INFO,
821 BTC_RSN_NTFY_SCAN_START,
822 BTC_RSN_NTFY_SCAN_FINISH,
823 BTC_RSN_NTFY_SPECIFIC_PACKET,
824 BTC_RSN_NTFY_POWEROFF,
825 BTC_RSN_NTFY_ROLE_INFO,
826 BTC_RSN_CMD_SET_COEX,
827 BTC_RSN_ACT1_WORK,
828 BTC_RSN_BT_DEVINFO_WORK,
829 BTC_RSN_RFK_CHK_WORK,
830 BTC_RSN_NUM,
831 BTC_ACT_NONE = 100,
832 BTC_ACT_WL_ONLY,
833 BTC_ACT_WL_5G,
834 BTC_ACT_WL_OTHER,
835 BTC_ACT_WL_IDLE,
836 BTC_ACT_WL_NC,
837 BTC_ACT_WL_RFK,
838 BTC_ACT_WL_INIT,
839 BTC_ACT_WL_OFF,
840 BTC_ACT_FREERUN,
841 BTC_ACT_BT_WHQL,
842 BTC_ACT_BT_RFK,
843 BTC_ACT_BT_OFF,
844 BTC_ACT_BT_IDLE,
845 BTC_ACT_BT_HFP,
846 BTC_ACT_BT_HID,
847 BTC_ACT_BT_A2DP,
848 BTC_ACT_BT_A2DPSINK,
849 BTC_ACT_BT_PAN,
850 BTC_ACT_BT_A2DP_HID,
851 BTC_ACT_BT_A2DP_PAN,
852 BTC_ACT_BT_PAN_HID,
853 BTC_ACT_BT_A2DP_PAN_HID,
854 BTC_ACT_WL_25G_MCC,
855 BTC_ACT_WL_2G_MCC,
856 BTC_ACT_WL_2G_SCC,
857 BTC_ACT_WL_2G_AP,
858 BTC_ACT_WL_2G_GO,
859 BTC_ACT_WL_2G_GC,
860 BTC_ACT_WL_2G_NAN,
861 BTC_ACT_LAST,
862 BTC_ACT_NUM = BTC_ACT_LAST - BTC_ACT_NONE,
863 BTC_ACT_EXT_BIT = BIT(14),
864 BTC_POLICY_EXT_BIT = BIT(15),
865 };
866
867 #define BTC_FREERUN_ANTISO_MIN 30
868 #define BTC_TDMA_BTHID_MAX 2
869 #define BTC_BLINK_NOCONNECT 0
870 #define BTC_B1_MAX 250 /* unit ms */
871
872 static void _run_coex(struct rtw89_dev *rtwdev,
873 enum btc_reason_and_action reason);
874 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state);
875 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update);
876
_send_fw_cmd(struct rtw89_dev * rtwdev,u8 h2c_class,u8 h2c_func,void * param,u16 len)877 static int _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func,
878 void *param, u16 len)
879 {
880 struct rtw89_btc *btc = &rtwdev->btc;
881 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
882 struct rtw89_btc_cx *cx = &btc->cx;
883 struct rtw89_btc_wl_info *wl = &cx->wl;
884 struct rtw89_btc_dm *dm = &btc->dm;
885 int ret;
886
887 if (len > BTC_H2C_MAXLEN || len == 0) {
888 btc->fwinfo.cnt_h2c_fail++;
889 dm->error.map.h2c_buffer_over = true;
890 return -EINVAL;
891 } else if (!wl->status.map.init_ok) {
892 rtw89_debug(rtwdev, RTW89_DBG_BTC,
893 "[BTC], %s(): return by btc not init!!\n", __func__);
894 pfwinfo->cnt_h2c_fail++;
895 return -EINVAL;
896 } else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF &&
897 wl->status.map.rf_off == BTC_LPS_RF_OFF) ||
898 (wl->status.map.lps_pre == BTC_LPS_RF_OFF &&
899 wl->status.map.lps == BTC_LPS_RF_OFF)) {
900 rtw89_debug(rtwdev, RTW89_DBG_BTC,
901 "[BTC], %s(): return by wl off!!\n", __func__);
902 pfwinfo->cnt_h2c_fail++;
903 return -EINVAL;
904 }
905
906 ret = rtw89_fw_h2c_raw_with_hdr(rtwdev, h2c_class, h2c_func, param, len,
907 false, true);
908 if (ret)
909 pfwinfo->cnt_h2c_fail++;
910 else
911 pfwinfo->cnt_h2c++;
912
913 return ret;
914 }
915
916 #define BTC_BT_DEF_BR_TX_PWR 4
917 #define BTC_BT_DEF_LE_TX_PWR 4
918
_reset_btc_var(struct rtw89_dev * rtwdev,u8 type)919 static void _reset_btc_var(struct rtw89_dev *rtwdev, u8 type)
920 {
921 struct rtw89_btc *btc = &rtwdev->btc;
922 const struct rtw89_btc_ver *ver = btc->ver;
923 struct rtw89_btc_cx *cx = &btc->cx;
924 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
925 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
926 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
927 struct rtw89_btc_wl_link_info *wl_linfo;
928 u8 i;
929
930 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
931
932 if (type & BTC_RESET_CX)
933 memset(cx, 0, sizeof(*cx));
934
935 if (type & BTC_RESET_BTINFO) /* only for BT enable */
936 memset(bt, 0, sizeof(*bt));
937
938 if (type & BTC_RESET_CTRL) {
939 memset(&btc->ctrl, 0, sizeof(btc->ctrl));
940 btc->manual_ctrl = false;
941 if (ver->fcxctrl != 7)
942 btc->ctrl.ctrl.trace_step = FCXDEF_STEP;
943 }
944
945 /* Init Coex variables that are not zero */
946 if (type & BTC_RESET_DM) {
947 memset(&btc->dm, 0, sizeof(btc->dm));
948 memset(bt_linfo->rssi_state, 0, sizeof(bt_linfo->rssi_state));
949 for (i = 0; i < RTW89_PORT_NUM; i++) {
950 if (btc->ver->fwlrole == 8)
951 wl_linfo = &wl->rlink_info[i][0];
952 else
953 wl_linfo = &wl->link_info[i];
954 memset(wl_linfo->rssi_state, 0, sizeof(wl_linfo->rssi_state));
955 }
956
957 /* set the slot_now table to original */
958 btc->dm.tdma_now = t_def[CXTD_OFF];
959 btc->dm.tdma = t_def[CXTD_OFF];
960 if (ver->fcxslots >= 7) {
961 for (i = 0; i < ARRAY_SIZE(s_def); i++) {
962 btc->dm.slot.v7[i].dur = s_def[i].dur;
963 btc->dm.slot.v7[i].cxtype = s_def[i].cxtype;
964 btc->dm.slot.v7[i].cxtbl = s_def[i].cxtbl;
965 }
966 memcpy(&btc->dm.slot_now.v7, &btc->dm.slot.v7,
967 sizeof(btc->dm.slot_now.v7));
968 } else {
969 memcpy(&btc->dm.slot_now.v1, s_def,
970 sizeof(btc->dm.slot_now.v1));
971 memcpy(&btc->dm.slot.v1, s_def,
972 sizeof(btc->dm.slot.v1));
973 }
974
975 btc->policy_len = 0;
976 btc->bt_req_len = 0;
977
978 btc->dm.coex_info_map = BTC_COEX_INFO_ALL;
979 btc->dm.wl_tx_limit.tx_time = BTC_MAX_TX_TIME_DEF;
980 btc->dm.wl_tx_limit.tx_retry = BTC_MAX_TX_RETRY_DEF;
981 btc->dm.wl_pre_agc_rb = BTC_PREAGC_NOTFOUND;
982 btc->dm.wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_NOTFOUND;
983 }
984
985 if (type & BTC_RESET_MDINFO)
986 memset(&btc->mdinfo, 0, sizeof(btc->mdinfo));
987
988 bt->link_info.bt_txpwr_desc.br_dbm = BTC_BT_DEF_BR_TX_PWR;
989 bt->link_info.bt_txpwr_desc.le_dbm = BTC_BT_DEF_LE_TX_PWR;
990 }
991
_search_reg_index(struct rtw89_dev * rtwdev,u8 mreg_num,u16 reg_type,u32 target)992 static u8 _search_reg_index(struct rtw89_dev *rtwdev, u8 mreg_num, u16 reg_type, u32 target)
993 {
994 const struct rtw89_chip_info *chip = rtwdev->chip;
995 u8 i;
996
997 for (i = 0; i < mreg_num; i++)
998 if (le16_to_cpu(chip->mon_reg[i].type) == reg_type &&
999 le32_to_cpu(chip->mon_reg[i].offset) == target) {
1000 return i;
1001 }
1002 return BTC_REG_NOTFOUND;
1003 }
1004
_get_reg_status(struct rtw89_dev * rtwdev,u8 type,u8 * val)1005 static void _get_reg_status(struct rtw89_dev *rtwdev, u8 type, u8 *val)
1006 {
1007 struct rtw89_btc *btc = &rtwdev->btc;
1008 const struct rtw89_btc_ver *ver = btc->ver;
1009 union rtw89_btc_module_info *md = &btc->mdinfo;
1010 union rtw89_btc_fbtc_mreg_val *pmreg;
1011 u32 pre_agc_addr = R_BTC_BB_PRE_AGC_S1;
1012 u32 reg_val;
1013 u8 idx, switch_type;
1014
1015 if (ver->fcxinit == 7)
1016 switch_type = md->md_v7.switch_type;
1017 else
1018 switch_type = md->md.switch_type;
1019
1020 if (btc->btg_pos == RF_PATH_A)
1021 pre_agc_addr = R_BTC_BB_PRE_AGC_S0;
1022
1023 switch (type) {
1024 case BTC_CSTATUS_TXDIV_POS:
1025 if (switch_type == BTC_SWITCH_INTERNAL)
1026 *val = BTC_ANT_DIV_MAIN;
1027 break;
1028 case BTC_CSTATUS_RXDIV_POS:
1029 if (switch_type == BTC_SWITCH_INTERNAL)
1030 *val = BTC_ANT_DIV_MAIN;
1031 break;
1032 case BTC_CSTATUS_BB_GNT_MUX:
1033 reg_val = rtw89_phy_read32(rtwdev, R_BTC_BB_BTG_RX);
1034 *val = !(reg_val & B_BTC_BB_GNT_MUX);
1035 break;
1036 case BTC_CSTATUS_BB_GNT_MUX_MON:
1037 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
1038 return;
1039
1040 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
1041 if (ver->fcxmreg == 1) {
1042 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
1043 REG_BB, R_BTC_BB_BTG_RX);
1044 if (idx == BTC_REG_NOTFOUND) {
1045 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
1046 } else {
1047 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]);
1048 *val = !(reg_val & B_BTC_BB_GNT_MUX);
1049 }
1050 } else if (ver->fcxmreg == 2) {
1051 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
1052 REG_BB, R_BTC_BB_BTG_RX);
1053 if (idx == BTC_REG_NOTFOUND) {
1054 *val = BTC_BTGCTRL_BB_GNT_NOTFOUND;
1055 } else {
1056 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]);
1057 *val = !(reg_val & B_BTC_BB_GNT_MUX);
1058 }
1059 }
1060 break;
1061 case BTC_CSTATUS_BB_PRE_AGC:
1062 reg_val = rtw89_phy_read32(rtwdev, pre_agc_addr);
1063 reg_val &= B_BTC_BB_PRE_AGC_MASK;
1064 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1065 break;
1066 case BTC_CSTATUS_BB_PRE_AGC_MON:
1067 if (!btc->fwinfo.rpt_fbtc_mregval.cinfo.valid)
1068 return;
1069
1070 pmreg = &btc->fwinfo.rpt_fbtc_mregval.finfo;
1071 if (ver->fcxmreg == 1) {
1072 idx = _search_reg_index(rtwdev, pmreg->v1.reg_num,
1073 REG_BB, pre_agc_addr);
1074 if (idx == BTC_REG_NOTFOUND) {
1075 *val = BTC_PREAGC_NOTFOUND;
1076 } else {
1077 reg_val = le32_to_cpu(pmreg->v1.mreg_val[idx]) &
1078 B_BTC_BB_PRE_AGC_MASK;
1079 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1080 }
1081 } else if (ver->fcxmreg == 2) {
1082 idx = _search_reg_index(rtwdev, pmreg->v2.reg_num,
1083 REG_BB, pre_agc_addr);
1084 if (idx == BTC_REG_NOTFOUND) {
1085 *val = BTC_PREAGC_NOTFOUND;
1086 } else {
1087 reg_val = le32_to_cpu(pmreg->v2.mreg_val[idx]) &
1088 B_BTC_BB_PRE_AGC_MASK;
1089 *val = (reg_val == B_BTC_BB_PRE_AGC_VAL);
1090 }
1091 }
1092 break;
1093 default:
1094 break;
1095 }
1096 }
1097
1098 #define BTC_RPT_HDR_SIZE 3
1099 #define BTC_CHK_WLSLOT_DRIFT_MAX 15
1100 #define BTC_CHK_BTSLOT_DRIFT_MAX 15
1101 #define BTC_CHK_HANG_MAX 3
1102
_chk_btc_err(struct rtw89_dev * rtwdev,u8 type,u32 cnt)1103 static void _chk_btc_err(struct rtw89_dev *rtwdev, u8 type, u32 cnt)
1104 {
1105 struct rtw89_btc *btc = &rtwdev->btc;
1106 struct rtw89_btc_cx *cx = &btc->cx;
1107 struct rtw89_btc_bt_info *bt = &cx->bt;
1108 struct rtw89_btc_wl_info *wl = &cx->wl;
1109 struct rtw89_btc_dm *dm = &btc->dm;
1110
1111 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1112 "[BTC], %s(): type:%d cnt:%d\n",
1113 __func__, type, cnt);
1114
1115 switch (type) {
1116 case BTC_DCNT_WL_FW_VER_MATCH:
1117 if ((wl->ver_info.fw_coex & 0xffff0000) !=
1118 rtwdev->chip->wlcx_desired) {
1119 wl->fw_ver_mismatch = true;
1120 dm->error.map.wl_ver_mismatch = true;
1121 } else {
1122 wl->fw_ver_mismatch = false;
1123 dm->error.map.wl_ver_mismatch = false;
1124 }
1125 break;
1126 case BTC_DCNT_RPT_HANG:
1127 if (dm->cnt_dm[BTC_DCNT_RPT] == cnt && btc->fwinfo.rpt_en_map)
1128 dm->cnt_dm[BTC_DCNT_RPT_HANG]++;
1129 else
1130 dm->cnt_dm[BTC_DCNT_RPT_HANG] = 0;
1131
1132 if (dm->cnt_dm[BTC_DCNT_RPT_HANG] >= BTC_CHK_HANG_MAX)
1133 dm->error.map.wl_fw_hang = true;
1134 else
1135 dm->error.map.wl_fw_hang = false;
1136
1137 dm->cnt_dm[BTC_DCNT_RPT] = cnt;
1138 break;
1139 case BTC_DCNT_CYCLE_HANG:
1140 if (dm->cnt_dm[BTC_DCNT_CYCLE] == cnt &&
1141 (dm->tdma_now.type != CXTDMA_OFF ||
1142 dm->tdma_now.ext_ctrl == CXECTL_EXT))
1143 dm->cnt_dm[BTC_DCNT_CYCLE_HANG]++;
1144 else
1145 dm->cnt_dm[BTC_DCNT_CYCLE_HANG] = 0;
1146
1147 if (dm->cnt_dm[BTC_DCNT_CYCLE_HANG] >= BTC_CHK_HANG_MAX)
1148 dm->error.map.cycle_hang = true;
1149 else
1150 dm->error.map.cycle_hang = false;
1151
1152 dm->cnt_dm[BTC_DCNT_CYCLE] = cnt;
1153 break;
1154 case BTC_DCNT_W1_HANG:
1155 if (dm->cnt_dm[BTC_DCNT_W1] == cnt &&
1156 dm->tdma_now.type != CXTDMA_OFF)
1157 dm->cnt_dm[BTC_DCNT_W1_HANG]++;
1158 else
1159 dm->cnt_dm[BTC_DCNT_W1_HANG] = 0;
1160
1161 if (dm->cnt_dm[BTC_DCNT_W1_HANG] >= BTC_CHK_HANG_MAX)
1162 dm->error.map.w1_hang = true;
1163 else
1164 dm->error.map.w1_hang = false;
1165
1166 dm->cnt_dm[BTC_DCNT_W1] = cnt;
1167 break;
1168 case BTC_DCNT_B1_HANG:
1169 if (dm->cnt_dm[BTC_DCNT_B1] == cnt &&
1170 dm->tdma_now.type != CXTDMA_OFF)
1171 dm->cnt_dm[BTC_DCNT_B1_HANG]++;
1172 else
1173 dm->cnt_dm[BTC_DCNT_B1_HANG] = 0;
1174
1175 if (dm->cnt_dm[BTC_DCNT_B1_HANG] >= BTC_CHK_HANG_MAX)
1176 dm->error.map.b1_hang = true;
1177 else
1178 dm->error.map.b1_hang = false;
1179
1180 dm->cnt_dm[BTC_DCNT_B1] = cnt;
1181 break;
1182 case BTC_DCNT_E2G_HANG:
1183 if (dm->cnt_dm[BTC_DCNT_E2G] == cnt &&
1184 dm->tdma_now.ext_ctrl == CXECTL_EXT)
1185 dm->cnt_dm[BTC_DCNT_E2G_HANG]++;
1186 else
1187 dm->cnt_dm[BTC_DCNT_E2G_HANG] = 0;
1188
1189 if (dm->cnt_dm[BTC_DCNT_E2G_HANG] >= BTC_CHK_HANG_MAX)
1190 dm->error.map.wl_e2g_hang = true;
1191 else
1192 dm->error.map.wl_e2g_hang = false;
1193
1194 dm->cnt_dm[BTC_DCNT_E2G] = cnt;
1195 break;
1196 case BTC_DCNT_TDMA_NONSYNC:
1197 if (cnt != 0) /* if tdma not sync between drv/fw */
1198 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC]++;
1199 else
1200 dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] = 0;
1201
1202 if (dm->cnt_dm[BTC_DCNT_TDMA_NONSYNC] >= BTC_CHK_HANG_MAX)
1203 dm->error.map.tdma_no_sync = true;
1204 else
1205 dm->error.map.tdma_no_sync = false;
1206 break;
1207 case BTC_DCNT_SLOT_NONSYNC:
1208 if (cnt != 0) /* if slot not sync between drv/fw */
1209 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC]++;
1210 else
1211 dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] = 0;
1212
1213 if (dm->cnt_dm[BTC_DCNT_SLOT_NONSYNC] >= BTC_CHK_HANG_MAX)
1214 dm->error.map.slot_no_sync = true;
1215 else
1216 dm->error.map.slot_no_sync = false;
1217 break;
1218 case BTC_DCNT_BTTX_HANG:
1219 cnt = cx->cnt_bt[BTC_BCNT_LOPRI_TX];
1220
1221 if (cnt == 0 && bt->link_info.slave_role)
1222 dm->cnt_dm[BTC_DCNT_BTTX_HANG]++;
1223 else
1224 dm->cnt_dm[BTC_DCNT_BTTX_HANG] = 0;
1225
1226 if (dm->cnt_dm[BTC_DCNT_BTTX_HANG] >= BTC_CHK_HANG_MAX)
1227 dm->error.map.bt_tx_hang = true;
1228 else
1229 dm->error.map.bt_tx_hang = false;
1230 break;
1231 case BTC_DCNT_BTCNT_HANG:
1232 cnt = cx->cnt_bt[BTC_BCNT_HIPRI_RX] +
1233 cx->cnt_bt[BTC_BCNT_HIPRI_TX] +
1234 cx->cnt_bt[BTC_BCNT_LOPRI_RX] +
1235 cx->cnt_bt[BTC_BCNT_LOPRI_TX];
1236
1237 if (cnt == 0)
1238 dm->cnt_dm[BTC_DCNT_BTCNT_HANG]++;
1239 else
1240 dm->cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
1241
1242 if ((dm->cnt_dm[BTC_DCNT_BTCNT_HANG] >= BTC_CHK_HANG_MAX &&
1243 bt->enable.now) || (!dm->cnt_dm[BTC_DCNT_BTCNT_HANG] &&
1244 !bt->enable.now))
1245 _update_bt_scbd(rtwdev, false);
1246 break;
1247 case BTC_DCNT_WL_SLOT_DRIFT:
1248 if (cnt >= BTC_CHK_WLSLOT_DRIFT_MAX)
1249 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT]++;
1250 else
1251 dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] = 0;
1252
1253 if (dm->cnt_dm[BTC_DCNT_WL_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1254 dm->error.map.wl_slot_drift = true;
1255 else
1256 dm->error.map.wl_slot_drift = false;
1257 break;
1258 case BTC_DCNT_BT_SLOT_DRIFT:
1259 if (cnt >= BTC_CHK_BTSLOT_DRIFT_MAX)
1260 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT]++;
1261 else
1262 dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] = 0;
1263
1264 if (dm->cnt_dm[BTC_DCNT_BT_SLOT_DRIFT] >= BTC_CHK_HANG_MAX)
1265 dm->error.map.bt_slot_drift = true;
1266 else
1267 dm->error.map.bt_slot_drift = false;
1268
1269 break;
1270 }
1271 }
1272
_update_bt_report(struct rtw89_dev * rtwdev,u8 rpt_type,u8 * pfinfo)1273 static void _update_bt_report(struct rtw89_dev *rtwdev, u8 rpt_type, u8 *pfinfo)
1274 {
1275 struct rtw89_btc *btc = &rtwdev->btc;
1276 const struct rtw89_btc_ver *ver = btc->ver;
1277 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1278 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
1279 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt_linfo->a2dp_desc;
1280 union rtw89_btc_fbtc_btver *pver = &btc->fwinfo.rpt_fbtc_btver.finfo;
1281 struct rtw89_btc_fbtc_btafh_v2 *pafh_v2 = NULL;
1282 struct rtw89_btc_fbtc_btafh_v7 *pafh_v7 = NULL;
1283 struct rtw89_btc_fbtc_btdevinfo *pdev = NULL;
1284 struct rtw89_btc_fbtc_btafh *pafh_v1 = NULL;
1285 struct rtw89_btc_fbtc_btscan_v1 *pscan_v1;
1286 struct rtw89_btc_fbtc_btscan_v2 *pscan_v2;
1287 struct rtw89_btc_fbtc_btscan_v7 *pscan_v7;
1288 bool scan_update = true;
1289 int i;
1290
1291 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1292 "[BTC], %s(): rpt_type:%d\n",
1293 __func__, rpt_type);
1294
1295 switch (rpt_type) {
1296 case BTC_RPT_TYPE_BT_VER:
1297 if (ver->fcxbtver == 7) {
1298 pver->v7 = *(struct rtw89_btc_fbtc_btver_v7 *)pfinfo;
1299 bt->ver_info.fw = le32_to_cpu(pver->v7.fw_ver);
1300 bt->ver_info.fw_coex = le32_get_bits(pver->v7.coex_ver,
1301 GENMASK(7, 0));
1302 bt->feature = le32_to_cpu(pver->v7.feature);
1303 } else {
1304 pver->v1 = *(struct rtw89_btc_fbtc_btver_v1 *)pfinfo;
1305 bt->ver_info.fw = le32_to_cpu(pver->v1.fw_ver);
1306 bt->ver_info.fw_coex = le32_get_bits(pver->v1.coex_ver,
1307 GENMASK(7, 0));
1308 bt->feature = le32_to_cpu(pver->v1.feature);
1309 }
1310 break;
1311 case BTC_RPT_TYPE_BT_SCAN:
1312 if (ver->fcxbtscan == 1) {
1313 pscan_v1 = (struct rtw89_btc_fbtc_btscan_v1 *)pfinfo;
1314 for (i = 0; i < BTC_SCAN_MAX1; i++) {
1315 bt->scan_info_v1[i] = pscan_v1->scan[i];
1316 if (bt->scan_info_v1[i].win == 0 &&
1317 bt->scan_info_v1[i].intvl == 0)
1318 scan_update = false;
1319 }
1320 } else if (ver->fcxbtscan == 2) {
1321 pscan_v2 = (struct rtw89_btc_fbtc_btscan_v2 *)pfinfo;
1322 for (i = 0; i < CXSCAN_MAX; i++) {
1323 bt->scan_info_v2[i] = pscan_v2->para[i];
1324 if ((pscan_v2->type & BIT(i)) &&
1325 pscan_v2->para[i].win == 0 &&
1326 pscan_v2->para[i].intvl == 0)
1327 scan_update = false;
1328 }
1329 } else if (ver->fcxbtscan == 7) {
1330 pscan_v7 = (struct rtw89_btc_fbtc_btscan_v7 *)pfinfo;
1331 for (i = 0; i < CXSCAN_MAX; i++) {
1332 bt->scan_info_v2[i] = pscan_v7->para[i];
1333 if ((pscan_v7->type & BIT(i)) &&
1334 pscan_v7->para[i].win == 0 &&
1335 pscan_v7->para[i].intvl == 0)
1336 scan_update = false;
1337 }
1338 }
1339 if (scan_update)
1340 bt->scan_info_update = 1;
1341 break;
1342 case BTC_RPT_TYPE_BT_AFH:
1343 if (ver->fcxbtafh == 2) {
1344 pafh_v2 = (struct rtw89_btc_fbtc_btafh_v2 *)pfinfo;
1345 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1346 memcpy(&bt_linfo->afh_map[0], pafh_v2->afh_l, 4);
1347 memcpy(&bt_linfo->afh_map[4], pafh_v2->afh_m, 4);
1348 memcpy(&bt_linfo->afh_map[8], pafh_v2->afh_h, 2);
1349 }
1350 if (pafh_v2->map_type & RPT_BT_AFH_SEQ_LE) {
1351 memcpy(&bt_linfo->afh_map_le[0], pafh_v2->afh_le_a, 4);
1352 memcpy(&bt_linfo->afh_map_le[4], pafh_v2->afh_le_b, 1);
1353 }
1354 } else if (ver->fcxbtafh == 7) {
1355 pafh_v7 = (struct rtw89_btc_fbtc_btafh_v7 *)pfinfo;
1356 if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LEGACY) {
1357 memcpy(&bt_linfo->afh_map[0], pafh_v7->afh_l, 4);
1358 memcpy(&bt_linfo->afh_map[4], pafh_v7->afh_m, 4);
1359 memcpy(&bt_linfo->afh_map[8], pafh_v7->afh_h, 2);
1360 }
1361 if (pafh_v7->map_type & RPT_BT_AFH_SEQ_LE) {
1362 memcpy(&bt_linfo->afh_map_le[0], pafh_v7->afh_le_a, 4);
1363 memcpy(&bt_linfo->afh_map_le[4], pafh_v7->afh_le_b, 1);
1364 }
1365 } else if (ver->fcxbtafh == 1) {
1366 pafh_v1 = (struct rtw89_btc_fbtc_btafh *)pfinfo;
1367 memcpy(&bt_linfo->afh_map[0], pafh_v1->afh_l, 4);
1368 memcpy(&bt_linfo->afh_map[4], pafh_v1->afh_m, 4);
1369 memcpy(&bt_linfo->afh_map[8], pafh_v1->afh_h, 2);
1370 }
1371 break;
1372 case BTC_RPT_TYPE_BT_DEVICE:
1373 pdev = (struct rtw89_btc_fbtc_btdevinfo *)pfinfo;
1374 a2dp->device_name = le32_to_cpu(pdev->dev_name);
1375 a2dp->vendor_id = le16_to_cpu(pdev->vendor_id);
1376 a2dp->flush_time = le32_to_cpu(pdev->flush_time);
1377 break;
1378 default:
1379 break;
1380 }
1381 }
1382
rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev * rtwdev,u8 * index)1383 static void rtw89_btc_fw_rpt_evnt_ver(struct rtw89_dev *rtwdev, u8 *index)
1384 {
1385 struct rtw89_btc *btc = &rtwdev->btc;
1386 const struct rtw89_btc_ver *ver = btc->ver;
1387
1388 if (ver->fwevntrptl == 1)
1389 return;
1390
1391 if (*index <= __BTC_RPT_TYPE_V0_SAME)
1392 return;
1393 else if (*index <= __BTC_RPT_TYPE_V0_MAX)
1394 (*index)++;
1395 else
1396 *index = BTC_RPT_TYPE_MAX;
1397 }
1398
1399 #define BTC_LEAK_AP_TH 10
1400 #define BTC_CYSTA_CHK_PERIOD 100
1401
1402 struct rtw89_btc_prpt {
1403 u8 type;
1404 __le16 len;
1405 u8 content[];
1406 } __packed;
1407
_chk_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * prptbuf,u32 index)1408 static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
1409 struct rtw89_btc_btf_fwinfo *pfwinfo,
1410 u8 *prptbuf, u32 index)
1411 {
1412 struct rtw89_btc *btc = &rtwdev->btc;
1413 struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver;
1414 const struct rtw89_btc_ver *ver = btc->ver;
1415 struct rtw89_btc_dm *dm = &btc->dm;
1416 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
1417 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
1418 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
1419 union rtw89_btc_fbtc_rpt_ctrl_ver_info *prpt = NULL;
1420 union rtw89_btc_fbtc_cysta_info *pcysta = NULL;
1421 struct rtw89_btc_prpt *btc_prpt = NULL;
1422 void *rpt_content = NULL, *pfinfo = NULL;
1423 u8 rpt_type = 0;
1424 u16 wl_slot_set = 0, wl_slot_real = 0, val16;
1425 u32 trace_step = 0, rpt_len = 0, diff_t = 0;
1426 u32 cnt_leak_slot, bt_slot_real, bt_slot_set, cnt_rx_imr;
1427 u8 i, val = 0, val1, val2;
1428
1429 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1430 "[BTC], %s(): index:%d\n",
1431 __func__, index);
1432
1433 if (!prptbuf) {
1434 pfwinfo->err[BTFRE_INVALID_INPUT]++;
1435 return 0;
1436 }
1437
1438 btc_prpt = (struct rtw89_btc_prpt *)&prptbuf[index];
1439 rpt_type = btc_prpt->type;
1440 rpt_len = le16_to_cpu(btc_prpt->len);
1441 rpt_content = btc_prpt->content;
1442
1443 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1444 "[BTC], %s(): rpt_type:%d\n",
1445 __func__, rpt_type);
1446
1447 rtw89_btc_fw_rpt_evnt_ver(rtwdev, &rpt_type);
1448
1449 switch (rpt_type) {
1450 case BTC_RPT_TYPE_CTRL:
1451 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
1452 prpt = &pfwinfo->rpt_ctrl.finfo;
1453 if (ver->fcxbtcrpt == 1) {
1454 pfinfo = &pfwinfo->rpt_ctrl.finfo.v1;
1455 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v1);
1456 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v1.fver;
1457 } else if (ver->fcxbtcrpt == 4) {
1458 pfinfo = &pfwinfo->rpt_ctrl.finfo.v4;
1459 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v4);
1460 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v4.fver;
1461 } else if (ver->fcxbtcrpt == 5) {
1462 pfinfo = &pfwinfo->rpt_ctrl.finfo.v5;
1463 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v5);
1464 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v5.fver;
1465 } else if (ver->fcxbtcrpt == 105) {
1466 pfinfo = &pfwinfo->rpt_ctrl.finfo.v105;
1467 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v105);
1468 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v105.fver;
1469 pcinfo->req_fver = 5;
1470 break;
1471 } else if (ver->fcxbtcrpt == 8) {
1472 pfinfo = &pfwinfo->rpt_ctrl.finfo.v8;
1473 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v8);
1474 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v8.fver;
1475 } else if (ver->fcxbtcrpt == 7) {
1476 pfinfo = &pfwinfo->rpt_ctrl.finfo.v7;
1477 pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo.v7);
1478 fwsubver->fcxbtcrpt = pfwinfo->rpt_ctrl.finfo.v7.fver;
1479 } else {
1480 goto err;
1481 }
1482 pcinfo->req_fver = ver->fcxbtcrpt;
1483 break;
1484 case BTC_RPT_TYPE_TDMA:
1485 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
1486 if (ver->fcxtdma == 1) {
1487 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
1488 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v1);
1489 fwsubver->fcxtdma = 0;
1490 } else if (ver->fcxtdma == 3 || ver->fcxtdma == 7) {
1491 pfinfo = &pfwinfo->rpt_fbtc_tdma.finfo.v3;
1492 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo.v3);
1493 fwsubver->fcxtdma = pfwinfo->rpt_fbtc_tdma.finfo.v3.fver;
1494 } else {
1495 goto err;
1496 }
1497 pcinfo->req_fver = ver->fcxtdma;
1498 break;
1499 case BTC_RPT_TYPE_SLOT:
1500 pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
1501 if (ver->fcxslots == 1) {
1502 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v1;
1503 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v1);
1504 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v1.fver;
1505 } else if (ver->fcxslots == 7) {
1506 pfinfo = &pfwinfo->rpt_fbtc_slots.finfo.v7;
1507 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo.v7);
1508 fwsubver->fcxslots = pfwinfo->rpt_fbtc_slots.finfo.v7.fver;
1509 } else {
1510 goto err;
1511 }
1512 pcinfo->req_fver = ver->fcxslots;
1513 break;
1514 case BTC_RPT_TYPE_CYSTA:
1515 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
1516 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
1517 if (ver->fcxcysta == 2) {
1518 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
1519 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
1520 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v2);
1521 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v2.fver;
1522 } else if (ver->fcxcysta == 3) {
1523 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
1524 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
1525 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v3);
1526 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v3.fver;
1527 } else if (ver->fcxcysta == 4) {
1528 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
1529 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
1530 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v4);
1531 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v4.fver;
1532 } else if (ver->fcxcysta == 5) {
1533 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
1534 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
1535 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v5);
1536 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v5.fver;
1537 } else if (ver->fcxcysta == 7) {
1538 pfinfo = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
1539 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
1540 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo.v7);
1541 fwsubver->fcxcysta = pfwinfo->rpt_fbtc_cysta.finfo.v7.fver;
1542 } else {
1543 goto err;
1544 }
1545 pcinfo->req_fver = ver->fcxcysta;
1546 break;
1547 case BTC_RPT_TYPE_STEP:
1548 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
1549 if (ver->fcxctrl != 7)
1550 trace_step = btc->ctrl.ctrl.trace_step;
1551
1552 if (ver->fcxstep == 2) {
1553 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v2;
1554 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v2.step[0]) *
1555 trace_step +
1556 offsetof(struct rtw89_btc_fbtc_steps_v2, step);
1557 fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v2.fver;
1558 } else if (ver->fcxstep == 3) {
1559 pfinfo = &pfwinfo->rpt_fbtc_step.finfo.v3;
1560 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.v3.step[0]) *
1561 trace_step +
1562 offsetof(struct rtw89_btc_fbtc_steps_v3, step);
1563 fwsubver->fcxstep = pfwinfo->rpt_fbtc_step.finfo.v3.fver;
1564 } else {
1565 goto err;
1566 }
1567 pcinfo->req_fver = ver->fcxstep;
1568 break;
1569 case BTC_RPT_TYPE_NULLSTA:
1570 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
1571 if (ver->fcxnullsta == 1) {
1572 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v1;
1573 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v1);
1574 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v1.fver;
1575 } else if (ver->fcxnullsta == 2) {
1576 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v2;
1577 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v2);
1578 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v2.fver;
1579 } else if (ver->fcxnullsta == 7) {
1580 pfinfo = &pfwinfo->rpt_fbtc_nullsta.finfo.v7;
1581 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo.v7);
1582 fwsubver->fcxnullsta = pfwinfo->rpt_fbtc_nullsta.finfo.v7.fver;
1583 } else {
1584 goto err;
1585 }
1586 pcinfo->req_fver = ver->fcxnullsta;
1587 break;
1588 case BTC_RPT_TYPE_MREG:
1589 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
1590 if (ver->fcxmreg == 1) {
1591 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
1592 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v1);
1593 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v1.fver;
1594 } else if (ver->fcxmreg == 2) {
1595 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
1596 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v2);
1597 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v2.fver;
1598 } else if (ver->fcxmreg == 7) {
1599 pfinfo = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
1600 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo.v7);
1601 fwsubver->fcxmreg = pfwinfo->rpt_fbtc_mregval.finfo.v7.fver;
1602 } else {
1603 goto err;
1604 }
1605 pcinfo->req_fver = ver->fcxmreg;
1606 break;
1607 case BTC_RPT_TYPE_GPIO_DBG:
1608 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
1609 if (ver->fcxgpiodbg == 7) {
1610 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7;
1611 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7);
1612 fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v7.fver;
1613 } else {
1614 pfinfo = &pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1;
1615 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1);
1616 fwsubver->fcxgpiodbg = pfwinfo->rpt_fbtc_gpio_dbg.finfo.v1.fver;
1617 }
1618 pcinfo->req_fver = ver->fcxgpiodbg;
1619 break;
1620 case BTC_RPT_TYPE_BT_VER:
1621 pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
1622 if (ver->fcxbtver == 1) {
1623 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v1;
1624 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v1);
1625 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v1.fver;
1626 } else if (ver->fcxbtver == 7) {
1627 pfinfo = &pfwinfo->rpt_fbtc_btver.finfo.v7;
1628 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo.v7);
1629 fwsubver->fcxbtver = pfwinfo->rpt_fbtc_btver.finfo.v7.fver;
1630 }
1631 pcinfo->req_fver = ver->fcxbtver;
1632 break;
1633 case BTC_RPT_TYPE_BT_SCAN:
1634 pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
1635 if (ver->fcxbtscan == 1) {
1636 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v1;
1637 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v1);
1638 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v1.fver;
1639 } else if (ver->fcxbtscan == 2) {
1640 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v2;
1641 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v2);
1642 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v2.fver;
1643 } else if (ver->fcxbtscan == 7) {
1644 pfinfo = &pfwinfo->rpt_fbtc_btscan.finfo.v7;
1645 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo.v7);
1646 fwsubver->fcxbtscan = pfwinfo->rpt_fbtc_btscan.finfo.v7.fver;
1647 } else {
1648 goto err;
1649 }
1650 pcinfo->req_fver = ver->fcxbtscan;
1651 break;
1652 case BTC_RPT_TYPE_BT_AFH:
1653 pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
1654 if (ver->fcxbtafh == 1) {
1655 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v1;
1656 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v1);
1657 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v1.fver;
1658 } else if (ver->fcxbtafh == 2) {
1659 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v2;
1660 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v2);
1661 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v2.fver;
1662 } else if (ver->fcxbtafh == 7) {
1663 pfinfo = &pfwinfo->rpt_fbtc_btafh.finfo.v7;
1664 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo.v7);
1665 fwsubver->fcxbtafh = pfwinfo->rpt_fbtc_btafh.finfo.v7.fver;
1666 } else {
1667 goto err;
1668 }
1669 pcinfo->req_fver = ver->fcxbtafh;
1670 break;
1671 case BTC_RPT_TYPE_BT_DEVICE:
1672 pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
1673 pfinfo = &pfwinfo->rpt_fbtc_btdev.finfo;
1674 pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo);
1675 fwsubver->fcxbtdevinfo = pfwinfo->rpt_fbtc_btdev.finfo.fver;
1676 pcinfo->req_fver = ver->fcxbtdevinfo;
1677 break;
1678 default:
1679 pfwinfo->err[BTFRE_UNDEF_TYPE]++;
1680 return 0;
1681 }
1682
1683 pcinfo->rx_len = rpt_len;
1684 pcinfo->rx_cnt++;
1685
1686 if (rpt_len != pcinfo->req_len) {
1687 if (rpt_type < BTC_RPT_TYPE_MAX)
1688 pfwinfo->len_mismch |= (0x1 << rpt_type);
1689 else
1690 pfwinfo->len_mismch |= BIT(31);
1691 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1692 "[BTC], %s(): %d rpt_len:%d!=req_len:%d\n",
1693 __func__, rpt_type, rpt_len, pcinfo->req_len);
1694
1695 pcinfo->valid = 0;
1696 return 0;
1697 } else if (!pfinfo || !rpt_content || !pcinfo->req_len) {
1698 pfwinfo->err[BTFRE_EXCEPTION]++;
1699 pcinfo->valid = 0;
1700 return 0;
1701 }
1702
1703 memcpy(pfinfo, rpt_content, pcinfo->req_len);
1704 pcinfo->valid = 1;
1705
1706 switch (rpt_type) {
1707 case BTC_RPT_TYPE_CTRL:
1708 if (ver->fcxbtcrpt == 1) {
1709 prpt->v1 = pfwinfo->rpt_ctrl.finfo.v1;
1710 btc->fwinfo.rpt_en_map = prpt->v1.rpt_enable;
1711 wl->ver_info.fw_coex = prpt->v1.wl_fw_coex_ver;
1712 wl->ver_info.fw = prpt->v1.wl_fw_ver;
1713 dm->wl_fw_cx_offload = !!prpt->v1.wl_fw_cx_offload;
1714
1715 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1716 pfwinfo->event[BTF_EVNT_RPT]);
1717
1718 /* To avoid I/O if WL LPS or power-off */
1719 if (wl->status.map.lps != BTC_LPS_RF_OFF &&
1720 !wl->status.map.rf_off) {
1721 rtwdev->chip->ops->btc_update_bt_cnt(rtwdev);
1722 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1723
1724 btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1725 rtw89_mac_get_plt_cnt(rtwdev,
1726 RTW89_MAC_0);
1727 }
1728 } else if (ver->fcxbtcrpt == 4) {
1729 prpt->v4 = pfwinfo->rpt_ctrl.finfo.v4;
1730 btc->fwinfo.rpt_en_map = le32_to_cpu(prpt->v4.rpt_info.en);
1731 wl->ver_info.fw_coex = le32_to_cpu(prpt->v4.wl_fw_info.cx_ver);
1732 wl->ver_info.fw = le32_to_cpu(prpt->v4.wl_fw_info.fw_ver);
1733 dm->wl_fw_cx_offload = !!le32_to_cpu(prpt->v4.wl_fw_info.cx_offload);
1734
1735 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1736 memcpy(&dm->gnt.band[i], &prpt->v4.gnt_val[i],
1737 sizeof(dm->gnt.band[i]));
1738
1739 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1740 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_TX]);
1741 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1742 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_HI_RX]);
1743 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1744 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_TX]);
1745 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1746 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_LO_RX]);
1747 btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1748 le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_POLLUTED]);
1749
1750 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1751 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1752 pfwinfo->event[BTF_EVNT_RPT]);
1753
1754 if (le32_to_cpu(prpt->v4.bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
1755 bt->rfk_info.map.timeout = 1;
1756 else
1757 bt->rfk_info.map.timeout = 0;
1758
1759 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1760 } else if (ver->fcxbtcrpt == 5) {
1761 prpt->v5 = pfwinfo->rpt_ctrl.finfo.v5;
1762 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v5.rpt_info.en);
1763 wl->ver_info.fw_coex = le32_to_cpu(prpt->v5.rpt_info.cx_ver);
1764 wl->ver_info.fw = le32_to_cpu(prpt->v5.rpt_info.fw_ver);
1765 dm->wl_fw_cx_offload = 0;
1766
1767 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1768 memcpy(&dm->gnt.band[i], &prpt->v5.gnt_val[i][0],
1769 sizeof(dm->gnt.band[i]));
1770
1771 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1772 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_TX]);
1773 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1774 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_HI_RX]);
1775 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1776 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_TX]);
1777 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1778 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_LO_RX]);
1779 btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1780 le16_to_cpu(prpt->v5.bt_cnt[BTC_BCNT_POLLUTED]);
1781
1782 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1783 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1784 pfwinfo->event[BTF_EVNT_RPT]);
1785
1786 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1787 } else if (ver->fcxbtcrpt == 105) {
1788 prpt->v105 = pfwinfo->rpt_ctrl.finfo.v105;
1789 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v105.rpt_info.en);
1790 wl->ver_info.fw_coex = le32_to_cpu(prpt->v105.rpt_info.cx_ver);
1791 wl->ver_info.fw = le32_to_cpu(prpt->v105.rpt_info.fw_ver);
1792 dm->wl_fw_cx_offload = 0;
1793
1794 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1795 memcpy(&dm->gnt.band[i], &prpt->v105.gnt_val[i][0],
1796 sizeof(dm->gnt.band[i]));
1797
1798 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1799 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_TX_V105]);
1800 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1801 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_HI_RX_V105]);
1802 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1803 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_TX_V105]);
1804 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1805 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_LO_RX_V105]);
1806 btc->cx.cnt_bt[BTC_BCNT_POLUT] =
1807 le16_to_cpu(prpt->v105.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1808
1809 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1810 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG,
1811 pfwinfo->event[BTF_EVNT_RPT]);
1812
1813 dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
1814 } else if (ver->fcxbtcrpt == 7) {
1815 prpt->v7 = pfwinfo->rpt_ctrl.finfo.v7;
1816 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v7.rpt_info.en);
1817 wl->ver_info.fw_coex = le32_to_cpu(prpt->v7.rpt_info.cx_ver);
1818 wl->ver_info.fw = le32_to_cpu(prpt->v7.rpt_info.fw_ver);
1819
1820 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1821 memcpy(&dm->gnt.band[i], &prpt->v7.gnt_val[i][0],
1822 sizeof(dm->gnt.band[i]));
1823
1824 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1825 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_TX_V105]);
1826 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1827 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_HI_RX_V105]);
1828 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1829 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_TX_V105]);
1830 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1831 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_LO_RX_V105]);
1832
1833 val1 = le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1834 if (val1 > btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW])
1835 val1 -= btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]; /* diff */
1836
1837 btc->cx.cnt_bt[BTC_BCNT_POLUT_DIFF] = val1;
1838 btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW] =
1839 le16_to_cpu(prpt->v7.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1840
1841 val1 = pfwinfo->event[BTF_EVNT_RPT];
1842 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1843 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
1844 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
1845 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
1846 } else if (ver->fcxbtcrpt == 8) {
1847 prpt->v8 = pfwinfo->rpt_ctrl.finfo.v8;
1848 pfwinfo->rpt_en_map = le32_to_cpu(prpt->v8.rpt_info.en);
1849 wl->ver_info.fw_coex = le32_to_cpu(prpt->v8.rpt_info.cx_ver);
1850 wl->ver_info.fw = le32_to_cpu(prpt->v8.rpt_info.fw_ver);
1851
1852 for (i = RTW89_PHY_0; i < RTW89_PHY_NUM; i++)
1853 memcpy(&dm->gnt.band[i], &prpt->v8.gnt_val[i][0],
1854 sizeof(dm->gnt.band[i]));
1855
1856 btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] =
1857 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_TX_V105]);
1858 btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] =
1859 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_HI_RX_V105]);
1860 btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] =
1861 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_TX_V105]);
1862 btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] =
1863 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_LO_RX_V105]);
1864
1865 val1 = le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1866 if (val1 > btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW])
1867 val1 -= btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW]; /* diff */
1868
1869 btc->cx.cnt_bt[BTC_BCNT_POLUT_DIFF] = val1;
1870 btc->cx.cnt_bt[BTC_BCNT_POLUT_NOW] =
1871 le16_to_cpu(prpt->v8.bt_cnt[BTC_BCNT_POLLUTED_V105]);
1872
1873 val1 = pfwinfo->event[BTF_EVNT_RPT];
1874 if (((prpt->v8.rpt_len_max_h << 8) +
1875 prpt->v8.rpt_len_max_l) != ver->info_buf)
1876 dm->error.map.h2c_c2h_buffer_mismatch = true;
1877 else
1878 dm->error.map.h2c_c2h_buffer_mismatch = false;
1879
1880 _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_HANG, 0);
1881 _chk_btc_err(rtwdev, BTC_DCNT_RPT_HANG, val1);
1882 _chk_btc_err(rtwdev, BTC_DCNT_WL_FW_VER_MATCH, 0);
1883 _chk_btc_err(rtwdev, BTC_DCNT_BTTX_HANG, 0);
1884 } else {
1885 goto err;
1886 }
1887 break;
1888 case BTC_RPT_TYPE_TDMA:
1889 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1890 "[BTC], %s(): check %d %zu\n", __func__,
1891 BTC_DCNT_TDMA_NONSYNC,
1892 sizeof(dm->tdma_now));
1893 if (ver->fcxtdma == 1)
1894 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
1895 memcmp(&dm->tdma_now,
1896 &pfwinfo->rpt_fbtc_tdma.finfo.v1,
1897 sizeof(dm->tdma_now)));
1898 else if (ver->fcxtdma == 3 || ver->fcxtdma == 7)
1899 _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
1900 memcmp(&dm->tdma_now,
1901 &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma,
1902 sizeof(dm->tdma_now)));
1903 else
1904 goto err;
1905 break;
1906 case BTC_RPT_TYPE_SLOT:
1907 if (ver->fcxslots == 7) {
1908 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1909 "[BTC], %s(): check %d %zu\n",
1910 __func__, BTC_DCNT_SLOT_NONSYNC,
1911 sizeof(dm->slot_now.v7));
1912 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
1913 memcmp(dm->slot_now.v7,
1914 pfwinfo->rpt_fbtc_slots.finfo.v7.slot,
1915 sizeof(dm->slot_now.v7)));
1916 } else if (ver->fcxslots == 1) {
1917 rtw89_debug(rtwdev, RTW89_DBG_BTC,
1918 "[BTC], %s(): check %d %zu\n",
1919 __func__, BTC_DCNT_SLOT_NONSYNC,
1920 sizeof(dm->slot_now.v1));
1921 _chk_btc_err(rtwdev, BTC_DCNT_SLOT_NONSYNC,
1922 memcmp(dm->slot_now.v1,
1923 pfwinfo->rpt_fbtc_slots.finfo.v1.slot,
1924 sizeof(dm->slot_now.v1)));
1925 }
1926 break;
1927 case BTC_RPT_TYPE_CYSTA:
1928 if (ver->fcxcysta == 2) {
1929 if (le16_to_cpu(pcysta->v2.cycles) < BTC_CYSTA_CHK_PERIOD)
1930 break;
1931 /* Check Leak-AP */
1932 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) != 0 &&
1933 le32_to_cpu(pcysta->v2.leakrx_cnt) != 0 && dm->tdma_now.rxflctrl) {
1934 if (le32_to_cpu(pcysta->v2.slot_cnt[CXST_LK]) <
1935 BTC_LEAK_AP_TH * le32_to_cpu(pcysta->v2.leakrx_cnt))
1936 dm->leak_ap = 1;
1937 }
1938
1939 /* Check diff time between WL slot and W1/E2G slot */
1940 if (dm->tdma_now.type == CXTDMA_OFF &&
1941 dm->tdma_now.ext_ctrl == CXECTL_EXT) {
1942 if (ver->fcxslots == 1)
1943 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_E2G].dur);
1944 else if (ver->fcxslots == 7)
1945 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_E2G].dur);
1946 } else {
1947 if (ver->fcxslots == 1)
1948 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1949 else if (ver->fcxslots == 7)
1950 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1951 }
1952
1953 if (le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) > wl_slot_set) {
1954 diff_t = le16_to_cpu(pcysta->v2.tavg_cycle[CXT_WL]) - wl_slot_set;
1955 _chk_btc_err(rtwdev,
1956 BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1957 }
1958
1959 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1960 le32_to_cpu(pcysta->v2.slot_cnt[CXST_W1]));
1961 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
1962 le32_to_cpu(pcysta->v2.slot_cnt[CXST_B1]));
1963 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
1964 le16_to_cpu(pcysta->v2.cycles));
1965 } else if (ver->fcxcysta == 3) {
1966 if (le16_to_cpu(pcysta->v3.cycles) < BTC_CYSTA_CHK_PERIOD)
1967 break;
1968
1969 cnt_leak_slot = le32_to_cpu(pcysta->v3.slot_cnt[CXST_LK]);
1970 cnt_rx_imr = le32_to_cpu(pcysta->v3.leak_slot.cnt_rximr);
1971
1972 /* Check Leak-AP */
1973 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
1974 dm->tdma_now.rxflctrl) {
1975 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
1976 dm->leak_ap = 1;
1977 }
1978
1979 /* Check diff time between real WL slot and W1 slot */
1980 if (dm->tdma_now.type == CXTDMA_OFF) {
1981 if (ver->fcxslots == 1)
1982 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
1983 else if (ver->fcxslots == 7)
1984 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
1985 wl_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_WL]);
1986 if (wl_slot_real > wl_slot_set) {
1987 diff_t = wl_slot_real - wl_slot_set;
1988 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
1989 }
1990 }
1991
1992 /* Check diff time between real BT slot and EBT/E5G slot */
1993 if (dm->tdma_now.type == CXTDMA_OFF &&
1994 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
1995 btc->bt_req_len != 0) {
1996 bt_slot_real = le16_to_cpu(pcysta->v3.cycle_time.tavg[CXT_BT]);
1997 if (btc->bt_req_len > bt_slot_real) {
1998 diff_t = btc->bt_req_len - bt_slot_real;
1999 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2000 }
2001 }
2002
2003 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2004 le32_to_cpu(pcysta->v3.slot_cnt[CXST_W1]));
2005 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2006 le32_to_cpu(pcysta->v3.slot_cnt[CXST_B1]));
2007 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2008 le16_to_cpu(pcysta->v3.cycles));
2009 } else if (ver->fcxcysta == 4) {
2010 if (le16_to_cpu(pcysta->v4.cycles) < BTC_CYSTA_CHK_PERIOD)
2011 break;
2012
2013 cnt_leak_slot = le16_to_cpu(pcysta->v4.slot_cnt[CXST_LK]);
2014 cnt_rx_imr = le32_to_cpu(pcysta->v4.leak_slot.cnt_rximr);
2015
2016 /* Check Leak-AP */
2017 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
2018 dm->tdma_now.rxflctrl) {
2019 if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
2020 dm->leak_ap = 1;
2021 }
2022
2023 /* Check diff time between real WL slot and W1 slot */
2024 if (dm->tdma_now.type == CXTDMA_OFF) {
2025 if (ver->fcxslots == 1)
2026 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2027 else if (ver->fcxslots == 7)
2028 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2029 wl_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_WL]);
2030 if (wl_slot_real > wl_slot_set) {
2031 diff_t = wl_slot_real - wl_slot_set;
2032 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2033 }
2034 }
2035
2036 /* Check diff time between real BT slot and EBT/E5G slot */
2037 if (dm->tdma_now.type == CXTDMA_OFF &&
2038 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
2039 btc->bt_req_len != 0) {
2040 bt_slot_real = le16_to_cpu(pcysta->v4.cycle_time.tavg[CXT_BT]);
2041
2042 if (btc->bt_req_len > bt_slot_real) {
2043 diff_t = btc->bt_req_len - bt_slot_real;
2044 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2045 }
2046 }
2047
2048 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2049 le16_to_cpu(pcysta->v4.slot_cnt[CXST_W1]));
2050 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2051 le16_to_cpu(pcysta->v4.slot_cnt[CXST_B1]));
2052 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2053 le16_to_cpu(pcysta->v4.cycles));
2054 } else if (ver->fcxcysta == 5) {
2055 if (dm->fddt_train == BTC_FDDT_ENABLE)
2056 break;
2057 cnt_leak_slot = le16_to_cpu(pcysta->v5.slot_cnt[CXST_LK]);
2058 cnt_rx_imr = le32_to_cpu(pcysta->v5.leak_slot.cnt_rximr);
2059
2060 /* Check Leak-AP */
2061 if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
2062 dm->tdma_now.rxflctrl) {
2063 if (le16_to_cpu(pcysta->v5.cycles) >= BTC_CYSTA_CHK_PERIOD &&
2064 cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
2065 dm->leak_ap = 1;
2066 }
2067
2068 /* Check diff time between real WL slot and W1 slot */
2069 if (dm->tdma_now.type == CXTDMA_OFF) {
2070 if (ver->fcxslots == 1)
2071 wl_slot_set = le16_to_cpu(dm->slot_now.v1[CXST_W1].dur);
2072 else if (ver->fcxslots == 7)
2073 wl_slot_set = le16_to_cpu(dm->slot_now.v7[CXST_W1].dur);
2074 wl_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_WL]);
2075
2076 if (wl_slot_real > wl_slot_set)
2077 diff_t = wl_slot_real - wl_slot_set;
2078 else
2079 diff_t = wl_slot_set - wl_slot_real;
2080 }
2081 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
2082
2083 /* Check diff time between real BT slot and EBT/E5G slot */
2084 bt_slot_set = btc->bt_req_len;
2085 bt_slot_real = le16_to_cpu(pcysta->v5.cycle_time.tavg[CXT_BT]);
2086 diff_t = 0;
2087 if (dm->tdma_now.type == CXTDMA_OFF &&
2088 dm->tdma_now.ext_ctrl == CXECTL_EXT &&
2089 bt_slot_set != 0) {
2090 if (bt_slot_set > bt_slot_real)
2091 diff_t = bt_slot_set - bt_slot_real;
2092 else
2093 diff_t = bt_slot_real - bt_slot_set;
2094 }
2095
2096 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
2097 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
2098 le16_to_cpu(pcysta->v5.slot_cnt[CXST_E2G]));
2099 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2100 le16_to_cpu(pcysta->v5.slot_cnt[CXST_W1]));
2101 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2102 le16_to_cpu(pcysta->v5.slot_cnt[CXST_B1]));
2103 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2104 le16_to_cpu(pcysta->v5.cycles));
2105 } else if (ver->fcxcysta == 7) {
2106 if (dm->fddt_train == BTC_FDDT_ENABLE)
2107 break;
2108
2109 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
2110
2111 if (dm->tdma_now.type != CXTDMA_OFF) {
2112 /* Check diff time between real WL slot and W1 slot */
2113 val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_WL]);
2114 _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, val16);
2115
2116 /* Check Leak-AP */
2117 val1 = le32_to_cpu(pcysta->v7.leak_slot.cnt_rximr) *
2118 BTC_LEAK_AP_TH;
2119 val2 = le16_to_cpu(pcysta->v7.slot_cnt[CXST_LK]);
2120
2121 val16 = le16_to_cpu(pcysta->v7.cycles);
2122 if (dm->tdma_now.rxflctrl &&
2123 val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
2124 dm->leak_ap = 1;
2125 } else if (dm->tdma_now.ext_ctrl == CXECTL_EXT) {
2126 val16 = le16_to_cpu(pcysta->v7.cycle_time.tavg[CXT_BT]);
2127 /* Check diff between real BT slot and EBT/E5G slot */
2128 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, val16);
2129
2130 /* Check bt slot length for P2P mode*/
2131 val1 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt_timeout) *
2132 BTC_SLOT_REQ_TH;
2133 val2 = le16_to_cpu(pcysta->v7.a2dp_ept.cnt);
2134
2135 val16 = le16_to_cpu(pcysta->v7.cycles);
2136 if (val16 >= BTC_CYSTA_CHK_PERIOD && val1 > val2)
2137 dm->slot_req_more = 1;
2138 else if (bt->link_info.status.map.connect == 0)
2139 dm->slot_req_more = 0;
2140 }
2141
2142 _chk_btc_err(rtwdev, BTC_DCNT_E2G_HANG,
2143 le16_to_cpu(pcysta->v7.slot_cnt[CXST_E2G]));
2144 _chk_btc_err(rtwdev, BTC_DCNT_W1_HANG,
2145 le16_to_cpu(pcysta->v7.slot_cnt[CXST_W1]));
2146 _chk_btc_err(rtwdev, BTC_DCNT_B1_HANG,
2147 le16_to_cpu(pcysta->v7.slot_cnt[CXST_B1]));
2148
2149 /* "BT_SLOT_FLOOD" error-check MUST before "CYCLE_HANG" */
2150 _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_FLOOD,
2151 le16_to_cpu(pcysta->v7.cycles));
2152 _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_HANG,
2153 le16_to_cpu(pcysta->v7.cycles));
2154 } else {
2155 goto err;
2156 }
2157 break;
2158 case BTC_RPT_TYPE_MREG:
2159 if (ver->fcxmreg == 7)
2160 break;
2161 _get_reg_status(rtwdev, BTC_CSTATUS_BB_GNT_MUX_MON, &val);
2162 if (dm->wl_btg_rx == BTC_BTGCTRL_BB_GNT_FWCTRL)
2163 dm->wl_btg_rx_rb = BTC_BTGCTRL_BB_GNT_FWCTRL;
2164 else
2165 dm->wl_btg_rx_rb = val;
2166
2167 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC_MON, &val);
2168 if (dm->wl_pre_agc == BTC_PREAGC_BB_FWCTRL)
2169 dm->wl_pre_agc_rb = BTC_PREAGC_BB_FWCTRL;
2170 else
2171 dm->wl_pre_agc_rb = val;
2172 break;
2173 case BTC_RPT_TYPE_BT_VER:
2174 case BTC_RPT_TYPE_BT_SCAN:
2175 case BTC_RPT_TYPE_BT_AFH:
2176 case BTC_RPT_TYPE_BT_DEVICE:
2177 _update_bt_report(rtwdev, rpt_type, pfinfo);
2178 break;
2179 }
2180 return (rpt_len + BTC_RPT_HDR_SIZE);
2181
2182 err:
2183 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2184 "[BTC], %s(): Undefined version for type=%d\n", __func__, rpt_type);
2185 return 0;
2186 }
2187
_parse_btc_report(struct rtw89_dev * rtwdev,struct rtw89_btc_btf_fwinfo * pfwinfo,u8 * pbuf,u32 buf_len)2188 static void _parse_btc_report(struct rtw89_dev *rtwdev,
2189 struct rtw89_btc_btf_fwinfo *pfwinfo,
2190 u8 *pbuf, u32 buf_len)
2191 {
2192 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
2193 struct rtw89_btc_prpt *btc_prpt = NULL;
2194 u32 index = 0, rpt_len = 0;
2195
2196 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2197 "[BTC], %s(): buf_len:%d\n",
2198 __func__, buf_len);
2199
2200 while (pbuf) {
2201 btc_prpt = (struct rtw89_btc_prpt *)&pbuf[index];
2202 if (index + 2 >= ver->info_buf)
2203 break;
2204 /* At least 3 bytes: type(1) & len(2) */
2205 rpt_len = le16_to_cpu(btc_prpt->len);
2206 if ((index + rpt_len + BTC_RPT_HDR_SIZE) > buf_len)
2207 break;
2208
2209 rpt_len = _chk_btc_report(rtwdev, pfwinfo, pbuf, index);
2210 if (!rpt_len)
2211 break;
2212 index += rpt_len;
2213 }
2214 }
2215
2216 #define BTC_TLV_HDR_LEN 2
2217 #define BTC_TLV_HDR_LEN_V7 3
2218
_append_tdma(struct rtw89_dev * rtwdev)2219 static void _append_tdma(struct rtw89_dev *rtwdev)
2220 {
2221 struct rtw89_btc *btc = &rtwdev->btc;
2222 const struct rtw89_btc_ver *ver = btc->ver;
2223 struct rtw89_btc_dm *dm = &btc->dm;
2224 struct rtw89_btc_btf_tlv *tlv;
2225 struct rtw89_btc_btf_tlv_v7 *tlv_v7;
2226 struct rtw89_btc_fbtc_tdma *v;
2227 struct rtw89_btc_fbtc_tdma_v3 *v3;
2228 u16 len = btc->policy_len;
2229
2230 if (!btc->update_policy_force &&
2231 !memcmp(&dm->tdma, &dm->tdma_now, sizeof(dm->tdma))) {
2232 rtw89_debug(rtwdev,
2233 RTW89_DBG_BTC, "[BTC], %s(): tdma no change!\n",
2234 __func__);
2235 return;
2236 }
2237
2238 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
2239 tlv->type = CXPOLICY_TDMA;
2240 if (ver->fcxtdma == 1) {
2241 v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0];
2242 tlv->len = sizeof(*v);
2243 *v = dm->tdma;
2244 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
2245 } else if (ver->fcxtdma == 7) {
2246 tlv_v7 = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2247 tlv_v7->len = sizeof(dm->tdma);
2248 tlv_v7->ver = ver->fcxtdma;
2249 tlv_v7->type = CXPOLICY_TDMA;
2250 memcpy(tlv_v7->val, &dm->tdma, tlv_v7->len);
2251 btc->policy_len += BTC_TLV_HDR_LEN_V7 + tlv_v7->len;
2252 } else {
2253 tlv->len = sizeof(*v3);
2254 v3 = (struct rtw89_btc_fbtc_tdma_v3 *)&tlv->val[0];
2255 v3->fver = ver->fcxtdma;
2256 v3->tdma = dm->tdma;
2257 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v3);
2258 }
2259
2260 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2261 "[BTC], %s(): type:%d, rxflctrl=%d, txpause=%d, wtgle_n=%d, leak_n=%d, ext_ctrl=%d\n",
2262 __func__, dm->tdma.type, dm->tdma.rxflctrl,
2263 dm->tdma.txpause, dm->tdma.wtgle_n, dm->tdma.leak_n,
2264 dm->tdma.ext_ctrl);
2265 }
2266
_append_slot_v1(struct rtw89_dev * rtwdev)2267 static void _append_slot_v1(struct rtw89_dev *rtwdev)
2268 {
2269 struct rtw89_btc *btc = &rtwdev->btc;
2270 struct rtw89_btc_dm *dm = &btc->dm;
2271 struct rtw89_btc_btf_tlv *tlv = NULL;
2272 struct btc_fbtc_1slot *v = NULL;
2273 u16 len = 0;
2274 u8 i, cnt = 0;
2275
2276 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2277 "[BTC], %s(): A:btc->policy_len = %d\n",
2278 __func__, btc->policy_len);
2279
2280 for (i = 0; i < CXST_MAX; i++) {
2281 if (!btc->update_policy_force &&
2282 !memcmp(&dm->slot.v1[i], &dm->slot_now.v1[i],
2283 sizeof(dm->slot.v1[i])))
2284 continue;
2285
2286 len = btc->policy_len;
2287
2288 tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
2289 v = (struct btc_fbtc_1slot *)&tlv->val[0];
2290 tlv->type = CXPOLICY_SLOT;
2291 tlv->len = sizeof(*v);
2292
2293 v->fver = btc->ver->fcxslots;
2294 v->sid = i;
2295 v->slot = dm->slot.v1[i];
2296
2297 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2298 "[BTC], %s(): slot-%d: dur=%d, table=0x%08x, type=%d\n",
2299 __func__, i, dm->slot.v1[i].dur, dm->slot.v1[i].cxtbl,
2300 dm->slot.v1[i].cxtype);
2301 cnt++;
2302
2303 btc->policy_len += BTC_TLV_HDR_LEN + sizeof(*v);
2304 }
2305
2306 if (cnt > 0)
2307 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2308 "[BTC], %s(): slot update (cnt=%d)!!\n",
2309 __func__, cnt);
2310 }
2311
_append_slot_v7(struct rtw89_dev * rtwdev)2312 static void _append_slot_v7(struct rtw89_dev *rtwdev)
2313 {
2314 struct rtw89_btc_btf_tlv_v7 *tlv = NULL;
2315 struct rtw89_btc *btc = &rtwdev->btc;
2316 struct rtw89_btc_dm *dm = &btc->dm;
2317 u8 i, cnt = 0;
2318 u16 len;
2319
2320 for (i = 0; i < CXST_MAX; i++) {
2321 if (!btc->update_policy_force &&
2322 !memcmp(&dm->slot.v7[i], &dm->slot_now.v7[i],
2323 sizeof(dm->slot.v7[i])))
2324 continue;
2325
2326 len = btc->policy_len;
2327
2328 if (!tlv) {
2329 if ((len + BTC_TLV_HDR_LEN_V7) > RTW89_BTC_POLICY_MAXLEN) {
2330 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2331 "[BTC], %s(): buff overflow!\n", __func__);
2332 break;
2333 }
2334
2335 tlv = (struct rtw89_btc_btf_tlv_v7 *)&btc->policy[len];
2336 tlv->type = CXPOLICY_SLOT;
2337 tlv->ver = btc->ver->fcxslots;
2338 tlv->len = sizeof(dm->slot.v7[0]) + BTC_TLV_SLOT_ID_LEN_V7;
2339 len += BTC_TLV_HDR_LEN_V7;
2340 }
2341
2342 if ((len + (u16)tlv->len) > RTW89_BTC_POLICY_MAXLEN) {
2343 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2344 "[BTC], %s(): buff overflow!\n", __func__);
2345 break;
2346 }
2347
2348 btc->policy[len] = i; /* slot-id */
2349 memcpy(&btc->policy[len + 1], &dm->slot.v7[i],
2350 sizeof(dm->slot.v7[0]));
2351 len += tlv->len;
2352
2353 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2354 "[BTC], %s: policy_len=%d, slot-%d: dur=%d, type=%d, table=0x%08x\n",
2355 __func__, btc->policy_len, i, dm->slot.v7[i].dur,
2356 dm->slot.v7[i].cxtype, dm->slot.v7[i].cxtbl);
2357 cnt++;
2358 btc->policy_len = len; /* update total length */
2359 }
2360
2361 if (cnt > 0)
2362 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2363 "[BTC], %s: slot update (cnt=%d, len=%d)!!\n",
2364 __func__, cnt, btc->policy_len);
2365 }
2366
_append_slot(struct rtw89_dev * rtwdev)2367 static void _append_slot(struct rtw89_dev *rtwdev)
2368 {
2369 struct rtw89_btc *btc = &rtwdev->btc;
2370
2371 if (btc->ver->fcxslots == 7)
2372 _append_slot_v7(rtwdev);
2373 else
2374 _append_slot_v1(rtwdev);
2375 }
2376
rtw89_btc_fw_rpt_ver(struct rtw89_dev * rtwdev,u32 rpt_map)2377 static u32 rtw89_btc_fw_rpt_ver(struct rtw89_dev *rtwdev, u32 rpt_map)
2378 {
2379 struct rtw89_btc *btc = &rtwdev->btc;
2380 const struct rtw89_btc_ver *ver = btc->ver;
2381 u32 bit_map = 0;
2382
2383 switch (rpt_map) {
2384 case RPT_EN_TDMA:
2385 bit_map = BIT(0);
2386 break;
2387 case RPT_EN_CYCLE:
2388 bit_map = BIT(1);
2389 break;
2390 case RPT_EN_MREG:
2391 bit_map = BIT(2);
2392 break;
2393 case RPT_EN_BT_VER_INFO:
2394 bit_map = BIT(3);
2395 break;
2396 case RPT_EN_BT_SCAN_INFO:
2397 bit_map = BIT(4);
2398 break;
2399 case RPT_EN_BT_DEVICE_INFO:
2400 switch (ver->frptmap) {
2401 case 0:
2402 case 1:
2403 case 2:
2404 bit_map = BIT(6);
2405 break;
2406 case 3:
2407 case 4:
2408 bit_map = BIT(5);
2409 break;
2410 default:
2411 break;
2412 }
2413 break;
2414 case RPT_EN_BT_AFH_MAP:
2415 switch (ver->frptmap) {
2416 case 0:
2417 case 1:
2418 case 2:
2419 bit_map = BIT(5);
2420 break;
2421 case 3:
2422 case 4:
2423 bit_map = BIT(6);
2424 break;
2425 default:
2426 break;
2427 }
2428 break;
2429 case RPT_EN_BT_AFH_MAP_LE:
2430 switch (ver->frptmap) {
2431 case 2:
2432 bit_map = BIT(8);
2433 break;
2434 case 3:
2435 case 4:
2436 bit_map = BIT(7);
2437 break;
2438 default:
2439 break;
2440 }
2441 break;
2442 case RPT_EN_BT_TX_PWR_LVL:
2443 switch (ver->frptmap) {
2444 case 0:
2445 case 1:
2446 case 2:
2447 case 3:
2448 break;
2449 case 4:
2450 bit_map = BIT(8);
2451 break;
2452 default:
2453 break;
2454 }
2455 break;
2456 case RPT_EN_FW_STEP_INFO:
2457 switch (ver->frptmap) {
2458 case 1:
2459 case 2:
2460 bit_map = BIT(7);
2461 break;
2462 case 3:
2463 bit_map = BIT(8);
2464 break;
2465 case 4:
2466 bit_map = BIT(9);
2467 break;
2468 default:
2469 break;
2470 }
2471 break;
2472 case RPT_EN_TEST:
2473 bit_map = BIT(31);
2474 break;
2475 case RPT_EN_WL_ALL:
2476 switch (ver->frptmap) {
2477 case 0:
2478 case 1:
2479 case 2:
2480 bit_map = GENMASK(2, 0);
2481 break;
2482 case 3:
2483 bit_map = GENMASK(2, 0) | BIT(8);
2484 break;
2485 case 4:
2486 bit_map = GENMASK(2, 0) | BIT(9);
2487 break;
2488 default:
2489 break;
2490 }
2491 break;
2492 case RPT_EN_BT_ALL:
2493 switch (ver->frptmap) {
2494 case 0:
2495 case 1:
2496 bit_map = GENMASK(6, 3);
2497 break;
2498 case 2:
2499 bit_map = GENMASK(6, 3) | BIT(8);
2500 break;
2501 case 3:
2502 bit_map = GENMASK(7, 3);
2503 break;
2504 case 4:
2505 bit_map = GENMASK(8, 3);
2506 break;
2507 default:
2508 break;
2509 }
2510 break;
2511 case RPT_EN_ALL:
2512 switch (ver->frptmap) {
2513 case 0:
2514 bit_map = GENMASK(6, 0);
2515 break;
2516 case 1:
2517 bit_map = GENMASK(7, 0);
2518 break;
2519 case 2:
2520 case 3:
2521 bit_map = GENMASK(8, 0);
2522 break;
2523 case 4:
2524 bit_map = GENMASK(9, 0);
2525 break;
2526 default:
2527 break;
2528 }
2529 break;
2530 case RPT_EN_MONITER:
2531 switch (ver->frptmap) {
2532 case 0:
2533 case 1:
2534 bit_map = GENMASK(6, 2);
2535 break;
2536 case 2:
2537 bit_map = GENMASK(6, 2) | BIT(8);
2538 break;
2539 case 3:
2540 bit_map = GENMASK(8, 2);
2541 break;
2542 case 4:
2543 bit_map = GENMASK(9, 2);
2544 break;
2545 default:
2546 break;
2547 }
2548 break;
2549 }
2550
2551 return bit_map;
2552 }
2553
rtw89_btc_fw_set_slots(struct rtw89_dev * rtwdev)2554 static void rtw89_btc_fw_set_slots(struct rtw89_dev *rtwdev)
2555 {
2556 struct rtw89_btc *btc = &rtwdev->btc;
2557 const struct rtw89_btc_ver *ver = btc->ver;
2558 struct rtw89_btc_btf_tlv_v7 *tlv_v7 = NULL;
2559 struct rtw89_btc_btf_set_slot_table *tbl;
2560 struct rtw89_btc_dm *dm = &btc->dm;
2561 u16 n, len;
2562
2563 if (ver->fcxslots == 7) {
2564 len = sizeof(*tlv_v7) + sizeof(dm->slot.v7);
2565 tlv_v7 = kmalloc(len, GFP_KERNEL);
2566 if (!tlv_v7)
2567 return;
2568
2569 tlv_v7->type = SET_SLOT_TABLE;
2570 tlv_v7->ver = ver->fcxslots;
2571 tlv_v7->len = ARRAY_SIZE(dm->slot.v7);
2572 memcpy(tlv_v7->val, dm->slot.v7, sizeof(dm->slot.v7));
2573
2574 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, (u8 *)tlv_v7, len);
2575
2576 kfree(tlv_v7);
2577 } else {
2578 n = struct_size(tbl, tbls, CXST_MAX);
2579 tbl = kmalloc(n, GFP_KERNEL);
2580 if (!tbl)
2581 return;
2582
2583 tbl->fver = BTF_SET_SLOT_TABLE_VER;
2584 tbl->tbl_num = CXST_MAX;
2585 memcpy(tbl->tbls, dm->slot.v1, flex_array_size(tbl, tbls, CXST_MAX));
2586
2587 _send_fw_cmd(rtwdev, BTFC_SET, SET_SLOT_TABLE, tbl, n);
2588
2589 kfree(tbl);
2590 }
2591 }
2592
rtw89_btc_fw_en_rpt(struct rtw89_dev * rtwdev,u32 rpt_map,bool rpt_state)2593 static void rtw89_btc_fw_en_rpt(struct rtw89_dev *rtwdev,
2594 u32 rpt_map, bool rpt_state)
2595 {
2596 struct rtw89_btc *btc = &rtwdev->btc;
2597 struct rtw89_btc_wl_smap *wl_smap = &btc->cx.wl.status.map;
2598 struct rtw89_btc_btf_fwinfo *fwinfo = &btc->fwinfo;
2599 union rtw89_fbtc_rtp_ctrl r;
2600 u32 val, bit_map;
2601 int ret;
2602
2603 if ((wl_smap->rf_off || wl_smap->lps != BTC_LPS_OFF) && rpt_state != 0)
2604 return;
2605
2606 bit_map = rtw89_btc_fw_rpt_ver(rtwdev, rpt_map);
2607
2608 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2609 "[BTC], %s(): rpt_map=%x, rpt_state=%x\n",
2610 __func__, rpt_map, rpt_state);
2611
2612 if (rpt_state)
2613 val = fwinfo->rpt_en_map | bit_map;
2614 else
2615 val = fwinfo->rpt_en_map & ~bit_map;
2616
2617 if (val == fwinfo->rpt_en_map)
2618 return;
2619
2620 if (btc->ver->fcxbtcrpt == 7 || btc->ver->fcxbtcrpt == 8) {
2621 r.v8.type = SET_REPORT_EN;
2622 r.v8.fver = btc->ver->fcxbtcrpt;
2623 r.v8.len = sizeof(r.v8.map);
2624 r.v8.map = cpu_to_le32(val);
2625 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v8,
2626 sizeof(r.v8));
2627 } else {
2628 if (btc->ver->fcxbtcrpt == 105)
2629 r.v1.fver = 5;
2630 else
2631 r.v1.fver = btc->ver->fcxbtcrpt;
2632 r.v1.enable = cpu_to_le32(val);
2633 r.v1.para = cpu_to_le32(rpt_state);
2634 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_REPORT_EN, &r.v1,
2635 sizeof(r.v1));
2636 }
2637
2638 if (!ret)
2639 fwinfo->rpt_en_map = val;
2640 }
2641
btc_fw_set_monreg(struct rtw89_dev * rtwdev)2642 static void btc_fw_set_monreg(struct rtw89_dev *rtwdev)
2643 {
2644 const struct rtw89_chip_info *chip = rtwdev->chip;
2645 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
2646 struct rtw89_btc_btf_set_mon_reg_v1 *v1 = NULL;
2647 struct rtw89_btc_btf_set_mon_reg_v7 *v7 = NULL;
2648 u8 i, n, ulen, cxmreg_max;
2649 u16 sz = 0;
2650
2651 n = chip->mon_reg_num;
2652 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2653 "[BTC], %s(): mon_reg_num=%d\n", __func__, n);
2654
2655 if (ver->fcxmreg == 1)
2656 cxmreg_max = CXMREG_MAX;
2657 else
2658 cxmreg_max = CXMREG_MAX_V2;
2659
2660 if (n > cxmreg_max) {
2661 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2662 "[BTC], %s(): mon reg count %d > %d\n",
2663 __func__, n, cxmreg_max);
2664 return;
2665 }
2666
2667 ulen = sizeof(struct rtw89_btc_fbtc_mreg);
2668
2669 if (ver->fcxmreg == 7) {
2670 sz = struct_size(v7, regs, n);
2671 v7 = kmalloc(sz, GFP_KERNEL);
2672 if (!v7)
2673 return;
2674 v7->type = RPT_EN_MREG;
2675 v7->fver = ver->fcxmreg;
2676 v7->len = n;
2677 for (i = 0; i < n; i++) {
2678 v7->regs[i].type = chip->mon_reg[i].type;
2679 v7->regs[i].bytes = chip->mon_reg[i].bytes;
2680 v7->regs[i].offset = chip->mon_reg[i].offset;
2681 }
2682
2683 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v7, sz);
2684 kfree(v7);
2685 } else {
2686 sz = struct_size(v1, regs, n);
2687 v1 = kmalloc(sz, GFP_KERNEL);
2688 if (!v1)
2689 return;
2690 v1->fver = ver->fcxmreg;
2691 v1->reg_num = n;
2692 memcpy(v1->regs, chip->mon_reg, flex_array_size(v1, regs, n));
2693
2694 _send_fw_cmd(rtwdev, BTFC_SET, SET_MREG_TABLE, v1, sz);
2695 kfree(v1);
2696 }
2697
2698 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2699 "[BTC], %s(): sz=%d ulen=%d n=%d\n",
2700 __func__, sz, ulen, n);
2701
2702 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
2703 }
2704
_update_dm_step(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason_or_action)2705 static void _update_dm_step(struct rtw89_dev *rtwdev,
2706 enum btc_reason_and_action reason_or_action)
2707 {
2708 struct rtw89_btc *btc = &rtwdev->btc;
2709 struct rtw89_btc_dm *dm = &btc->dm;
2710
2711 /* use ring-structure to store dm step */
2712 dm->dm_step.step[dm->dm_step.step_pos] = reason_or_action;
2713 dm->dm_step.step_pos++;
2714
2715 if (dm->dm_step.step_pos >= ARRAY_SIZE(dm->dm_step.step)) {
2716 dm->dm_step.step_pos = 0;
2717 dm->dm_step.step_ov = true;
2718 }
2719 }
2720
_fw_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)2721 static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
2722 enum btc_reason_and_action action)
2723 {
2724 struct rtw89_btc *btc = &rtwdev->btc;
2725 struct rtw89_btc_dm *dm = &btc->dm;
2726 int ret;
2727
2728 dm->run_action = action;
2729
2730 _update_dm_step(rtwdev, action | BTC_ACT_EXT_BIT);
2731 _update_dm_step(rtwdev, policy_type | BTC_POLICY_EXT_BIT);
2732
2733 btc->policy_len = 0;
2734 btc->policy_type = policy_type;
2735
2736 _append_tdma(rtwdev);
2737 _append_slot(rtwdev);
2738
2739 if (btc->policy_len == 0 || btc->policy_len > RTW89_BTC_POLICY_MAXLEN)
2740 return;
2741
2742 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2743 "[BTC], %s(): action = %d -> policy type/len: 0x%04x/%d\n",
2744 __func__, action, policy_type, btc->policy_len);
2745
2746 if (dm->tdma.rxflctrl == CXFLC_NULLP ||
2747 dm->tdma.rxflctrl == CXFLC_QOSNULL)
2748 btc->lps = 1;
2749 else
2750 btc->lps = 0;
2751
2752 if (btc->lps == 1)
2753 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
2754
2755 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_CX_POLICY,
2756 btc->policy, btc->policy_len);
2757 if (!ret) {
2758 memcpy(&dm->tdma_now, &dm->tdma, sizeof(dm->tdma_now));
2759 if (btc->ver->fcxslots == 7)
2760 memcpy(&dm->slot_now.v7, &dm->slot.v7, sizeof(dm->slot_now.v7));
2761 else
2762 memcpy(&dm->slot_now.v1, &dm->slot.v1, sizeof(dm->slot_now.v1));
2763 }
2764
2765 if (btc->update_policy_force)
2766 btc->update_policy_force = false;
2767
2768 if (btc->lps == 0)
2769 rtw89_set_coex_ctrl_lps(rtwdev, btc->lps);
2770 }
2771
_fw_set_drv_info(struct rtw89_dev * rtwdev,u8 type)2772 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 type)
2773 {
2774 struct rtw89_btc *btc = &rtwdev->btc;
2775 const struct rtw89_btc_ver *ver = btc->ver;
2776 struct rtw89_btc_dm *dm = &btc->dm;
2777 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
2778 struct rtw89_btc_rf_trx_para rf_para = dm->rf_trx_para;
2779
2780 switch (type) {
2781 case CXDRVINFO_INIT:
2782 if (ver->fcxinit == 7)
2783 rtw89_fw_h2c_cxdrv_init_v7(rtwdev, type);
2784 else
2785 rtw89_fw_h2c_cxdrv_init(rtwdev, type);
2786 break;
2787 case CXDRVINFO_ROLE:
2788 if (ver->fwlrole == 0)
2789 rtw89_fw_h2c_cxdrv_role(rtwdev, type);
2790 else if (ver->fwlrole == 1)
2791 rtw89_fw_h2c_cxdrv_role_v1(rtwdev, type);
2792 else if (ver->fwlrole == 2)
2793 rtw89_fw_h2c_cxdrv_role_v2(rtwdev, type);
2794 else if (ver->fwlrole == 7)
2795 rtw89_fw_h2c_cxdrv_role_v7(rtwdev, type);
2796 else if (ver->fwlrole == 8)
2797 rtw89_fw_h2c_cxdrv_role_v8(rtwdev, type);
2798 break;
2799 case CXDRVINFO_CTRL:
2800 if (ver->drvinfo_type == 1)
2801 type = 2;
2802
2803 if (ver->fcxctrl == 7)
2804 rtw89_fw_h2c_cxdrv_ctrl_v7(rtwdev, type);
2805 else
2806 rtw89_fw_h2c_cxdrv_ctrl(rtwdev, type);
2807 break;
2808 case CXDRVINFO_TRX:
2809 if (ver->drvinfo_type == 1)
2810 type = 3;
2811
2812 dm->trx_info.tx_power = u32_get_bits(rf_para.wl_tx_power,
2813 RTW89_BTC_WL_DEF_TX_PWR);
2814 dm->trx_info.rx_gain = u32_get_bits(rf_para.wl_rx_gain,
2815 RTW89_BTC_WL_DEF_TX_PWR);
2816 dm->trx_info.bt_tx_power = u32_get_bits(rf_para.bt_tx_power,
2817 RTW89_BTC_WL_DEF_TX_PWR);
2818 dm->trx_info.bt_rx_gain = u32_get_bits(rf_para.bt_rx_gain,
2819 RTW89_BTC_WL_DEF_TX_PWR);
2820 dm->trx_info.cn = wl->cn_report;
2821 dm->trx_info.nhm = wl->nhm.pwr;
2822 rtw89_fw_h2c_cxdrv_trx(rtwdev, type);
2823 break;
2824 case CXDRVINFO_RFK:
2825 if (ver->drvinfo_type == 1)
2826 return;
2827
2828 rtw89_fw_h2c_cxdrv_rfk(rtwdev, type);
2829 break;
2830 case CXDRVINFO_TXPWR:
2831 case CXDRVINFO_FDDT:
2832 case CXDRVINFO_MLO:
2833 case CXDRVINFO_OSI:
2834 if (!ver->fcxosi)
2835 return;
2836
2837 if (ver->drvinfo_type == 2)
2838 type = 7;
2839 else
2840 return;
2841
2842 rtw89_fw_h2c_cxdrv_osi_info(rtwdev, type);
2843 break;
2844 default:
2845 break;
2846 }
2847 }
2848
2849 static
btc_fw_event(struct rtw89_dev * rtwdev,u8 evt_id,void * data,u32 len)2850 void btc_fw_event(struct rtw89_dev *rtwdev, u8 evt_id, void *data, u32 len)
2851 {
2852 struct rtw89_btc *btc = &rtwdev->btc;
2853 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
2854
2855 rtw89_debug(rtwdev, RTW89_DBG_BTC,
2856 "[BTC], %s(): evt_id:%d len:%d\n",
2857 __func__, evt_id, len);
2858
2859 if (!len || !data)
2860 return;
2861
2862 switch (evt_id) {
2863 case BTF_EVNT_RPT:
2864 _parse_btc_report(rtwdev, pfwinfo, data, len);
2865 break;
2866 default:
2867 break;
2868 }
2869 }
2870
_set_gnt(struct rtw89_dev * rtwdev,u8 phy_map,u8 wl_state,u8 bt_state)2871 static void _set_gnt(struct rtw89_dev *rtwdev, u8 phy_map, u8 wl_state, u8 bt_state)
2872 {
2873 struct rtw89_btc *btc = &rtwdev->btc;
2874 struct rtw89_btc_dm *dm = &btc->dm;
2875 struct rtw89_mac_ax_gnt *g = dm->gnt.band;
2876 u8 i;
2877
2878 if (phy_map > BTC_PHY_ALL)
2879 return;
2880
2881 for (i = 0; i < RTW89_PHY_NUM; i++) {
2882 if (!(phy_map & BIT(i)))
2883 continue;
2884
2885 switch (wl_state) {
2886 case BTC_GNT_HW:
2887 g[i].gnt_wl_sw_en = 0;
2888 g[i].gnt_wl = 0;
2889 break;
2890 case BTC_GNT_SW_LO:
2891 g[i].gnt_wl_sw_en = 1;
2892 g[i].gnt_wl = 0;
2893 break;
2894 case BTC_GNT_SW_HI:
2895 g[i].gnt_wl_sw_en = 1;
2896 g[i].gnt_wl = 1;
2897 break;
2898 }
2899
2900 switch (bt_state) {
2901 case BTC_GNT_HW:
2902 g[i].gnt_bt_sw_en = 0;
2903 g[i].gnt_bt = 0;
2904 break;
2905 case BTC_GNT_SW_LO:
2906 g[i].gnt_bt_sw_en = 1;
2907 g[i].gnt_bt = 0;
2908 break;
2909 case BTC_GNT_SW_HI:
2910 g[i].gnt_bt_sw_en = 1;
2911 g[i].gnt_bt = 1;
2912 break;
2913 }
2914 }
2915
2916 rtw89_chip_mac_cfg_gnt(rtwdev, &dm->gnt);
2917 }
2918
_set_gnt_v1(struct rtw89_dev * rtwdev,u8 phy_map,u8 wl_state,u8 bt_state,u8 wlact_state)2919 static void _set_gnt_v1(struct rtw89_dev *rtwdev, u8 phy_map,
2920 u8 wl_state, u8 bt_state, u8 wlact_state)
2921 {
2922 struct rtw89_btc *btc = &rtwdev->btc;
2923 struct rtw89_btc_dm *dm = &btc->dm;
2924 struct rtw89_btc_fbtc_outsrc_set_info *osi = &dm->ost_info;
2925 struct rtw89_mac_ax_wl_act *b = dm->gnt.bt;
2926 struct rtw89_mac_ax_gnt *g = dm->gnt.band;
2927 u8 i, bt_idx = dm->bt_select + 1;
2928
2929 if (phy_map > BTC_PHY_ALL)
2930 return;
2931
2932 for (i = 0; i < RTW89_PHY_NUM; i++) {
2933 if (!(phy_map & BIT(i)))
2934 continue;
2935
2936 switch (wl_state) {
2937 case BTC_GNT_HW:
2938 g[i].gnt_wl_sw_en = 0;
2939 g[i].gnt_wl = 0;
2940 break;
2941 case BTC_GNT_SW_LO:
2942 g[i].gnt_wl_sw_en = 1;
2943 g[i].gnt_wl = 0;
2944 break;
2945 case BTC_GNT_SW_HI:
2946 g[i].gnt_wl_sw_en = 1;
2947 g[i].gnt_wl = 1;
2948 break;
2949 }
2950
2951 switch (bt_state) {
2952 case BTC_GNT_HW:
2953 g[i].gnt_bt_sw_en = 0;
2954 g[i].gnt_bt = 0;
2955 break;
2956 case BTC_GNT_SW_LO:
2957 g[i].gnt_bt_sw_en = 1;
2958 g[i].gnt_bt = 0;
2959 break;
2960 case BTC_GNT_SW_HI:
2961 g[i].gnt_bt_sw_en = 1;
2962 g[i].gnt_bt = 1;
2963 break;
2964 }
2965 }
2966
2967 if (rtwdev->chip->para_ver & BTC_FEAT_WLAN_ACT_MUX) {
2968 for (i = 0; i < 2; i++) {
2969 if (!(bt_idx & BIT(i)))
2970 continue;
2971
2972 switch (wlact_state) {
2973 case BTC_WLACT_HW:
2974 b[i].wlan_act_en = 0;
2975 b[i].wlan_act = 0;
2976 break;
2977 case BTC_WLACT_SW_LO:
2978 b[i].wlan_act_en = 1;
2979 b[i].wlan_act = 0;
2980 break;
2981 case BTC_WLACT_SW_HI:
2982 b[i].wlan_act_en = 1;
2983 b[i].wlan_act = 1;
2984 break;
2985 }
2986 }
2987 }
2988
2989 if (!btc->ver->fcxosi) {
2990 rtw89_mac_cfg_gnt_v2(rtwdev, &dm->gnt);
2991 return;
2992 }
2993
2994 memcpy(osi->gnt_set, dm->gnt.band, sizeof(osi->gnt_set));
2995 memcpy(osi->wlact_set, dm->gnt.bt, sizeof(osi->wlact_set));
2996
2997 /* GBT source should be GBT_S1 in 1+1 (HWB0:5G + HWB1:2G) case */
2998 if (osi->rf_band[BTC_RF_S0] == 1 &&
2999 osi->rf_band[BTC_RF_S1] == 0)
3000 osi->rf_gbt_source = BTC_RF_S1;
3001 else
3002 osi->rf_gbt_source = BTC_RF_S0;
3003 }
3004
3005 #define BTC_TDMA_WLROLE_MAX 3
3006
_set_bt_ignore_wlan_act(struct rtw89_dev * rtwdev,u8 enable)3007 static void _set_bt_ignore_wlan_act(struct rtw89_dev *rtwdev, u8 enable)
3008 {
3009 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3010 "[BTC], %s(): set bt %s wlan_act\n", __func__,
3011 enable ? "ignore" : "do not ignore");
3012
3013 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_IGNORE_WLAN_ACT, &enable, 1);
3014 }
3015
3016 #define WL_TX_POWER_NO_BTC_CTRL GENMASK(31, 0)
3017 #define WL_TX_POWER_ALL_TIME GENMASK(15, 0)
3018 #define WL_TX_POWER_WITH_BT GENMASK(31, 16)
3019 #define WL_TX_POWER_INT_PART GENMASK(8, 2)
3020 #define WL_TX_POWER_FRA_PART GENMASK(1, 0)
3021 #define B_BTC_WL_TX_POWER_SIGN BIT(7)
3022 #define B_TSSI_WL_TX_POWER_SIGN BIT(8)
3023
_set_wl_tx_power(struct rtw89_dev * rtwdev,u32 level)3024 static void _set_wl_tx_power(struct rtw89_dev *rtwdev, u32 level)
3025 {
3026 const struct rtw89_chip_info *chip = rtwdev->chip;
3027 struct rtw89_btc *btc = &rtwdev->btc;
3028 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3029 u32 pwr_val;
3030
3031 if (wl->rf_para.tx_pwr_freerun == level)
3032 return;
3033
3034 wl->rf_para.tx_pwr_freerun = level;
3035 btc->dm.rf_trx_para.wl_tx_power = level;
3036
3037 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3038 "[BTC], %s(): level = %d\n",
3039 __func__, level);
3040
3041 if (level == RTW89_BTC_WL_DEF_TX_PWR) {
3042 pwr_val = WL_TX_POWER_NO_BTC_CTRL;
3043 } else { /* only apply "force tx power" */
3044 pwr_val = FIELD_PREP(WL_TX_POWER_INT_PART, level);
3045 if (pwr_val > RTW89_BTC_WL_DEF_TX_PWR)
3046 pwr_val = RTW89_BTC_WL_DEF_TX_PWR;
3047
3048 if (level & B_BTC_WL_TX_POWER_SIGN)
3049 pwr_val |= B_TSSI_WL_TX_POWER_SIGN;
3050 pwr_val |= WL_TX_POWER_WITH_BT;
3051 }
3052
3053 chip->ops->btc_set_wl_txpwr_ctrl(rtwdev, pwr_val);
3054 }
3055
_set_wl_rx_gain(struct rtw89_dev * rtwdev,u32 level)3056 static void _set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level)
3057 {
3058 const struct rtw89_chip_info *chip = rtwdev->chip;
3059 struct rtw89_btc *btc = &rtwdev->btc;
3060 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3061
3062 if (wl->rf_para.rx_gain_freerun == level)
3063 return;
3064
3065 wl->rf_para.rx_gain_freerun = level;
3066 btc->dm.rf_trx_para.wl_rx_gain = level;
3067
3068 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3069 "[BTC], %s(): level = %d\n",
3070 __func__, level);
3071
3072 chip->ops->btc_set_wl_rx_gain(rtwdev, level);
3073 }
3074
_set_bt_tx_power(struct rtw89_dev * rtwdev,u8 level)3075 static void _set_bt_tx_power(struct rtw89_dev *rtwdev, u8 level)
3076 {
3077 struct rtw89_btc *btc = &rtwdev->btc;
3078 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3079 int ret;
3080 u8 buf;
3081
3082 if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0)
3083 return;
3084
3085 if (bt->rf_para.tx_pwr_freerun == level)
3086 return;
3087
3088 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3089 "[BTC], %s(): level = %d\n",
3090 __func__, level);
3091
3092 buf = (s8)(-level);
3093 ret = _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_TX_PWR, &buf, 1);
3094 if (!ret) {
3095 bt->rf_para.tx_pwr_freerun = level;
3096 btc->dm.rf_trx_para.bt_tx_power = level;
3097 }
3098 }
3099
3100 #define BTC_BT_RX_NORMAL_LVL 7
3101
_set_bt_rx_gain(struct rtw89_dev * rtwdev,u8 level)3102 static void _set_bt_rx_gain(struct rtw89_dev *rtwdev, u8 level)
3103 {
3104 struct rtw89_btc *btc = &rtwdev->btc;
3105 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3106
3107 if (btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE] == 0)
3108 return;
3109
3110 if ((bt->rf_para.rx_gain_freerun == level ||
3111 level > BTC_BT_RX_NORMAL_LVL) &&
3112 (!rtwdev->chip->scbd || bt->lna_constrain == level))
3113 return;
3114
3115 bt->rf_para.rx_gain_freerun = level;
3116 btc->dm.rf_trx_para.bt_rx_gain = level;
3117
3118 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3119 "[BTC], %s(): level = %d\n",
3120 __func__, level);
3121
3122 if (level == BTC_BT_RX_NORMAL_LVL)
3123 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, false);
3124 else
3125 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
3126
3127 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_LNA_CONSTRAIN, &level, sizeof(level));
3128 }
3129
_set_rf_trx_para(struct rtw89_dev * rtwdev)3130 static void _set_rf_trx_para(struct rtw89_dev *rtwdev)
3131 {
3132 const struct rtw89_chip_info *chip = rtwdev->chip;
3133 struct rtw89_btc *btc = &rtwdev->btc;
3134 const struct rtw89_btc_ver *ver = btc->ver;
3135 struct rtw89_btc_dm *dm = &btc->dm;
3136 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3137 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3138 struct rtw89_btc_bt_link_info *b = &bt->link_info;
3139 struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
3140 struct rtw89_btc_rf_trx_para para;
3141 u32 wl_stb_chg = 0;
3142 u8 level_id = 0, link_mode = 0, i, dbcc_2g_phy = 0;
3143
3144 if (ver->fwlrole == 0) {
3145 link_mode = wl->role_info.link_mode;
3146 for (i = 0; i < RTW89_PHY_NUM; i++) {
3147 if (wl->dbcc_info.real_band[i] == RTW89_BAND_2G)
3148 dbcc_2g_phy = i;
3149 }
3150 } else if (ver->fwlrole == 1) {
3151 link_mode = wl->role_info_v1.link_mode;
3152 dbcc_2g_phy = wl->role_info_v1.dbcc_2g_phy;
3153 } else if (ver->fwlrole == 2) {
3154 link_mode = wl->role_info_v2.link_mode;
3155 dbcc_2g_phy = wl->role_info_v2.dbcc_2g_phy;
3156 }
3157
3158 /* decide trx_para_level */
3159 if (btc->ant_type == BTC_ANT_SHARED) {
3160 /* fix LNA2 + TIA gain not change by GNT_BT */
3161 if ((btc->dm.wl_btg_rx && b->profile_cnt.now != 0) ||
3162 dm->bt_only == 1)
3163 dm->trx_para_level = 1; /* for better BT ACI issue */
3164 else
3165 dm->trx_para_level = 0;
3166 } else { /* non-shared antenna */
3167 dm->trx_para_level = 5;
3168 /* modify trx_para if WK 2.4G-STA-DL + bt link */
3169 if (b->profile_cnt.now != 0 &&
3170 link_mode == BTC_WLINK_2G_STA &&
3171 wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) { /* uplink */
3172 if (wl->rssi_level == 4 && bt->rssi_level > 2)
3173 dm->trx_para_level = 6;
3174 else if (wl->rssi_level == 3 && bt->rssi_level > 3)
3175 dm->trx_para_level = 7;
3176 }
3177 }
3178
3179 level_id = dm->trx_para_level;
3180 if (level_id >= chip->rf_para_dlink_num ||
3181 level_id >= chip->rf_para_ulink_num) {
3182 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3183 "[BTC], %s(): invalid level_id: %d\n",
3184 __func__, level_id);
3185 return;
3186 }
3187
3188 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
3189 para = chip->rf_para_ulink[level_id];
3190 else
3191 para = chip->rf_para_dlink[level_id];
3192
3193 if (dm->fddt_train) {
3194 _set_wl_rx_gain(rtwdev, 1);
3195 _write_scbd(rtwdev, BTC_WSCB_RXGAIN, true);
3196 } else {
3197 _set_wl_tx_power(rtwdev, para.wl_tx_power);
3198 _set_wl_rx_gain(rtwdev, para.wl_rx_gain);
3199 _set_bt_tx_power(rtwdev, para.bt_tx_power);
3200 _set_bt_rx_gain(rtwdev, para.bt_rx_gain);
3201 }
3202
3203 if (!bt->enable.now || dm->wl_only || wl_smap->rf_off ||
3204 wl_smap->lps == BTC_LPS_RF_OFF ||
3205 link_mode == BTC_WLINK_5G ||
3206 link_mode == BTC_WLINK_NOLINK ||
3207 (rtwdev->dbcc_en && dbcc_2g_phy != RTW89_PHY_1))
3208 wl_stb_chg = 0;
3209 else
3210 wl_stb_chg = 1;
3211
3212 if (wl_stb_chg != dm->wl_stb_chg) {
3213 dm->wl_stb_chg = wl_stb_chg;
3214 chip->ops->btc_wl_s1_standby(rtwdev, dm->wl_stb_chg);
3215 }
3216 }
3217
_update_btc_state_map(struct rtw89_dev * rtwdev)3218 static void _update_btc_state_map(struct rtw89_dev *rtwdev)
3219 {
3220 struct rtw89_btc *btc = &rtwdev->btc;
3221 struct rtw89_btc_cx *cx = &btc->cx;
3222 struct rtw89_btc_wl_info *wl = &cx->wl;
3223 struct rtw89_btc_bt_info *bt = &cx->bt;
3224 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
3225
3226 if (wl->status.map.connecting || wl->status.map._4way ||
3227 wl->status.map.roaming || wl->status.map.dbccing) {
3228 cx->state_map = BTC_WLINKING;
3229 } else if (wl->status.map.scan) { /* wl scan */
3230 if (bt_linfo->status.map.inq_pag)
3231 cx->state_map = BTC_WSCAN_BSCAN;
3232 else
3233 cx->state_map = BTC_WSCAN_BNOSCAN;
3234 } else if (wl->status.map.busy) { /* only busy */
3235 if (bt_linfo->status.map.inq_pag)
3236 cx->state_map = BTC_WBUSY_BSCAN;
3237 else
3238 cx->state_map = BTC_WBUSY_BNOSCAN;
3239 } else { /* wl idle */
3240 cx->state_map = BTC_WIDLE;
3241 }
3242 }
3243
_set_bt_afh_info_v0(struct rtw89_dev * rtwdev)3244 static void _set_bt_afh_info_v0(struct rtw89_dev *rtwdev)
3245 {
3246 const struct rtw89_chip_info *chip = rtwdev->chip;
3247 struct rtw89_btc *btc = &rtwdev->btc;
3248 const struct rtw89_btc_ver *ver = btc->ver;
3249 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3250 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3251 struct rtw89_btc_bt_link_info *b = &bt->link_info;
3252 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3253 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3254 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
3255 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
3256 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
3257 struct rtw89_btc_wl_active_role *r;
3258 struct rtw89_btc_wl_active_role_v1 *r1;
3259 struct rtw89_btc_wl_active_role_v2 *r2;
3260 struct rtw89_btc_wl_active_role_v7 *r7;
3261 struct rtw89_btc_wl_rlink *rlink;
3262 u8 en = 0, i, ch = 0, bw = 0;
3263 u8 mode, connect_cnt;
3264
3265 if (btc->manual_ctrl || wl->status.map.scan)
3266 return;
3267
3268 if (ver->fwlrole == 0) {
3269 mode = wl_rinfo->link_mode;
3270 connect_cnt = wl_rinfo->connect_cnt;
3271 } else if (ver->fwlrole == 1) {
3272 mode = wl_rinfo_v1->link_mode;
3273 connect_cnt = wl_rinfo_v1->connect_cnt;
3274 } else if (ver->fwlrole == 2) {
3275 mode = wl_rinfo_v2->link_mode;
3276 connect_cnt = wl_rinfo_v2->connect_cnt;
3277 } else if (ver->fwlrole == 7) {
3278 mode = wl_rinfo_v7->link_mode;
3279 connect_cnt = wl_rinfo_v7->connect_cnt;
3280 } else if (ver->fwlrole == 8) {
3281 mode = wl_rinfo_v8->link_mode;
3282 connect_cnt = wl_rinfo_v8->connect_cnt;
3283 } else {
3284 return;
3285 }
3286
3287 if (wl->status.map.rf_off || bt->whql_test ||
3288 mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_5G ||
3289 connect_cnt > BTC_TDMA_WLROLE_MAX) {
3290 en = false;
3291 } else if (mode == BTC_WLINK_2G_MCC || mode == BTC_WLINK_2G_SCC) {
3292 en = true;
3293 /* get p2p channel */
3294 for (i = 0; i < RTW89_PORT_NUM; i++) {
3295 r = &wl_rinfo->active_role[i];
3296 r1 = &wl_rinfo_v1->active_role_v1[i];
3297 r2 = &wl_rinfo_v2->active_role_v2[i];
3298 r7 = &wl_rinfo_v7->active_role[i];
3299 rlink = &wl_rinfo_v8->rlink[i][0];
3300
3301 if (ver->fwlrole == 0 &&
3302 (r->role == RTW89_WIFI_ROLE_P2P_GO ||
3303 r->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3304 ch = r->ch;
3305 bw = r->bw;
3306 break;
3307 } else if (ver->fwlrole == 1 &&
3308 (r1->role == RTW89_WIFI_ROLE_P2P_GO ||
3309 r1->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3310 ch = r1->ch;
3311 bw = r1->bw;
3312 break;
3313 } else if (ver->fwlrole == 2 &&
3314 (r2->role == RTW89_WIFI_ROLE_P2P_GO ||
3315 r2->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3316 ch = r2->ch;
3317 bw = r2->bw;
3318 break;
3319 } else if (ver->fwlrole == 7 &&
3320 (r7->role == RTW89_WIFI_ROLE_P2P_GO ||
3321 r7->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3322 ch = r7->ch;
3323 bw = r7->bw;
3324 break;
3325 } else if (ver->fwlrole == 8 &&
3326 (rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
3327 rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3328 ch = rlink->ch;
3329 bw = rlink->bw;
3330 break;
3331 }
3332 }
3333 } else {
3334 en = true;
3335 /* get 2g channel */
3336 for (i = 0; i < RTW89_PORT_NUM; i++) {
3337 r = &wl_rinfo->active_role[i];
3338 r1 = &wl_rinfo_v1->active_role_v1[i];
3339 r2 = &wl_rinfo_v2->active_role_v2[i];
3340 r7 = &wl_rinfo_v7->active_role[i];
3341 rlink = &wl_rinfo_v8->rlink[i][0];
3342
3343 if (ver->fwlrole == 0 &&
3344 r->connected && r->band == RTW89_BAND_2G) {
3345 ch = r->ch;
3346 bw = r->bw;
3347 break;
3348 } else if (ver->fwlrole == 1 &&
3349 r1->connected && r1->band == RTW89_BAND_2G) {
3350 ch = r1->ch;
3351 bw = r1->bw;
3352 break;
3353 } else if (ver->fwlrole == 2 &&
3354 r2->connected && r2->band == RTW89_BAND_2G) {
3355 ch = r2->ch;
3356 bw = r2->bw;
3357 break;
3358 } else if (ver->fwlrole == 7 &&
3359 r7->connected && r7->band == RTW89_BAND_2G) {
3360 ch = r7->ch;
3361 bw = r7->bw;
3362 break;
3363 } else if (ver->fwlrole == 8 &&
3364 rlink->connected && rlink->rf_band == RTW89_BAND_2G) {
3365 ch = rlink->ch;
3366 bw = rlink->bw;
3367 break;
3368 }
3369 }
3370 }
3371
3372 switch (bw) {
3373 case RTW89_CHANNEL_WIDTH_20:
3374 bw = 20 + chip->afh_guard_ch * 2;
3375 break;
3376 case RTW89_CHANNEL_WIDTH_40:
3377 bw = 40 + chip->afh_guard_ch * 2;
3378 break;
3379 case RTW89_CHANNEL_WIDTH_5:
3380 bw = 5 + chip->afh_guard_ch * 2;
3381 break;
3382 case RTW89_CHANNEL_WIDTH_10:
3383 bw = 10 + chip->afh_guard_ch * 2;
3384 break;
3385 default:
3386 bw = 0;
3387 en = false; /* turn off AFH info if BW > 40 */
3388 break;
3389 }
3390
3391 if (wl->afh_info.en == en &&
3392 wl->afh_info.ch == ch &&
3393 wl->afh_info.bw == bw &&
3394 b->profile_cnt.last == b->profile_cnt.now) {
3395 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3396 "[BTC], %s(): return because no change!\n",
3397 __func__);
3398 return;
3399 }
3400
3401 wl->afh_info.en = en;
3402 wl->afh_info.ch = ch;
3403 wl->afh_info.bw = bw;
3404
3405 _send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3);
3406
3407 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3408 "[BTC], %s(): en=%d, ch=%d, bw=%d\n",
3409 __func__, en, ch, bw);
3410 btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++;
3411 }
3412
_set_bt_afh_info_v1(struct rtw89_dev * rtwdev)3413 static void _set_bt_afh_info_v1(struct rtw89_dev *rtwdev)
3414 {
3415 const struct rtw89_chip_info *chip = rtwdev->chip;
3416 struct rtw89_btc *btc = &rtwdev->btc;
3417 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3418 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
3419 struct rtw89_btc_wl_afh_info *wl_afh = &wl->afh_info;
3420 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3421 struct rtw89_btc_wl_rlink *rlink;
3422 u8 en = 0, ch = 0, bw = 0, buf[3] = {};
3423 u8 i, j, link_mode;
3424
3425 if (btc->manual_ctrl || wl->status.map.scan)
3426 return;
3427
3428 link_mode = wl_rinfo->link_mode;
3429
3430 for (i = 0; i < btc->ver->max_role_num; i++) {
3431 for (j = RTW89_MAC_0; j < RTW89_MAC_NUM; j++) {
3432 if (wl->status.map.rf_off || bt->whql_test ||
3433 link_mode == BTC_WLINK_NOLINK ||
3434 link_mode == BTC_WLINK_5G)
3435 break;
3436
3437 rlink = &wl_rinfo->rlink[i][j];
3438
3439 /* Don't care no-connected/non-2G-band role */
3440 if (!rlink->connected || !rlink->active ||
3441 rlink->rf_band != RTW89_BAND_2G)
3442 continue;
3443
3444 en = 1;
3445 ch = rlink->ch;
3446 bw = rlink->bw;
3447
3448 if (link_mode == BTC_WLINK_2G_MCC &&
3449 (rlink->role == RTW89_WIFI_ROLE_AP ||
3450 rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
3451 rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
3452 /* for 2.4G MCC, take role = ap/go/gc */
3453 break;
3454 } else if (link_mode != BTC_WLINK_2G_SCC ||
3455 rlink->bw == RTW89_CHANNEL_WIDTH_40) {
3456 /* for 2.4G scc, take bw = 40M */
3457 break;
3458 }
3459 }
3460 }
3461
3462 /* default AFH channel sapn = center-ch +- 6MHz */
3463 switch (bw) {
3464 case RTW89_CHANNEL_WIDTH_20:
3465 if (btc->dm.freerun || btc->dm.fddt_train)
3466 bw = 48;
3467 else
3468 bw = 20 + chip->afh_guard_ch * 2;
3469 break;
3470 case RTW89_CHANNEL_WIDTH_40:
3471 if (btc->dm.freerun)
3472 bw = 40 + chip->afh_guard_ch * 2;
3473 else
3474 bw = 40;
3475 break;
3476 case RTW89_CHANNEL_WIDTH_5:
3477 bw = 5 + chip->afh_guard_ch * 2;
3478 break;
3479 case RTW89_CHANNEL_WIDTH_10:
3480 bw = 10 + chip->afh_guard_ch * 2;
3481 break;
3482 default:
3483 en = false; /* turn off AFH info if invalid BW */
3484 bw = 0;
3485 ch = 0;
3486 break;
3487 }
3488
3489 if (!en || ch > 14 || ch == 0) {
3490 en = false;
3491 bw = 0;
3492 ch = 0;
3493 }
3494
3495 if (wl_afh->en == en &&
3496 wl_afh->ch == ch &&
3497 wl_afh->bw == bw &&
3498 (!bt->enable.now || bt->enable.last))
3499 return;
3500
3501 wl_afh->en = buf[0];
3502 wl_afh->ch = buf[1];
3503 wl_afh->bw = buf[2];
3504
3505 if (_send_fw_cmd(rtwdev, BTFC_SET, SET_BT_WL_CH_INFO, &wl->afh_info, 3)) {
3506 rtw89_debug(rtwdev, RTW89_DBG_BTC,
3507 "[BTC], %s(): en=%d, ch=%d, bw=%d\n",
3508 __func__, en, ch, bw);
3509
3510 btc->cx.cnt_wl[BTC_WCNT_CH_UPDATE]++;
3511 }
3512 }
3513
_set_bt_afh_info(struct rtw89_dev * rtwdev)3514 static void _set_bt_afh_info(struct rtw89_dev *rtwdev)
3515 {
3516 if (rtwdev->chip->chip_id == RTL8922A)
3517 _set_bt_afh_info_v1(rtwdev);
3518 else
3519 _set_bt_afh_info_v0(rtwdev);
3520 }
3521
_check_freerun(struct rtw89_dev * rtwdev)3522 static bool _check_freerun(struct rtw89_dev *rtwdev)
3523 {
3524 struct rtw89_btc *btc = &rtwdev->btc;
3525 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3526 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
3527 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
3528 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
3529 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
3530 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
3531 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
3532 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
3533 struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc;
3534 union rtw89_btc_module_info *md = &btc->mdinfo;
3535 const struct rtw89_btc_ver *ver = btc->ver;
3536 u8 isolation, connect_cnt = 0;
3537
3538 if (ver->fcxinit == 7)
3539 isolation = md->md_v7.ant.isolation;
3540 else
3541 isolation = md->md.ant.isolation;
3542
3543 if (ver->fwlrole == 0)
3544 connect_cnt = wl_rinfo->connect_cnt;
3545 else if (ver->fwlrole == 1)
3546 connect_cnt = wl_rinfo_v1->connect_cnt;
3547 else if (ver->fwlrole == 2)
3548 connect_cnt = wl_rinfo_v2->connect_cnt;
3549 else if (ver->fwlrole == 7)
3550 connect_cnt = wl_rinfo_v7->connect_cnt;
3551 else if (ver->fwlrole == 8)
3552 connect_cnt = wl_rinfo_v8->connect_cnt;
3553
3554 if (btc->ant_type == BTC_ANT_SHARED) {
3555 btc->dm.trx_para_level = 0;
3556 return false;
3557 }
3558
3559 /* The below is dedicated antenna case */
3560 if (connect_cnt > BTC_TDMA_WLROLE_MAX) {
3561 btc->dm.trx_para_level = 5;
3562 return true;
3563 }
3564
3565 if (bt_linfo->profile_cnt.now == 0) {
3566 btc->dm.trx_para_level = 5;
3567 return true;
3568 }
3569
3570 if (hid->pair_cnt > BTC_TDMA_BTHID_MAX) {
3571 btc->dm.trx_para_level = 5;
3572 return true;
3573 }
3574
3575 /* TODO get isolation by BT psd */
3576 if (isolation >= BTC_FREERUN_ANTISO_MIN) {
3577 btc->dm.trx_para_level = 5;
3578 return true;
3579 }
3580
3581 if (!wl->status.map.busy) {/* wl idle -> freerun */
3582 btc->dm.trx_para_level = 5;
3583 return true;
3584 } else if (wl->rssi_level > 1) {/* WL rssi < 50% (-60dBm) */
3585 btc->dm.trx_para_level = 0;
3586 return false;
3587 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
3588 if (wl->rssi_level == 0 && bt_linfo->rssi > 31) {
3589 btc->dm.trx_para_level = 6;
3590 return true;
3591 } else if (wl->rssi_level == 1 && bt_linfo->rssi > 36) {
3592 btc->dm.trx_para_level = 7;
3593 return true;
3594 }
3595 btc->dm.trx_para_level = 0;
3596 return false;
3597 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL)) {
3598 if (bt_linfo->rssi > 28) {
3599 btc->dm.trx_para_level = 6;
3600 return true;
3601 }
3602 }
3603
3604 btc->dm.trx_para_level = 0;
3605 return false;
3606 }
3607
3608 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; })
3609 #define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; })
3610 #define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; })
3611 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; })
3612
3613 struct btc_btinfo_lb2 {
3614 u8 connect: 1;
3615 u8 sco_busy: 1;
3616 u8 inq_pag: 1;
3617 u8 acl_busy: 1;
3618 u8 hfp: 1;
3619 u8 hid: 1;
3620 u8 a2dp: 1;
3621 u8 pan: 1;
3622 };
3623
3624 struct btc_btinfo_lb3 {
3625 u8 retry: 4;
3626 u8 cqddr: 1;
3627 u8 inq: 1;
3628 u8 mesh_busy: 1;
3629 u8 pag: 1;
3630 };
3631
3632 struct btc_btinfo_hb0 {
3633 s8 rssi;
3634 };
3635
3636 struct btc_btinfo_hb1 {
3637 u8 ble_connect: 1;
3638 u8 reinit: 1;
3639 u8 relink: 1;
3640 u8 igno_wl: 1;
3641 u8 voice: 1;
3642 u8 ble_scan: 1;
3643 u8 role_sw: 1;
3644 u8 multi_link: 1;
3645 };
3646
3647 struct btc_btinfo_hb2 {
3648 u8 pan_active: 1;
3649 u8 afh_update: 1;
3650 u8 a2dp_active: 1;
3651 u8 slave: 1;
3652 u8 hid_slot: 2;
3653 u8 hid_cnt: 2;
3654 };
3655
3656 struct btc_btinfo_hb3 {
3657 u8 a2dp_bitpool: 6;
3658 u8 tx_3m: 1;
3659 u8 a2dp_sink: 1;
3660 };
3661
3662 union btc_btinfo {
3663 u8 val;
3664 struct btc_btinfo_lb2 lb2;
3665 struct btc_btinfo_lb3 lb3;
3666 struct btc_btinfo_hb0 hb0;
3667 struct btc_btinfo_hb1 hb1;
3668 struct btc_btinfo_hb2 hb2;
3669 struct btc_btinfo_hb3 hb3;
3670 };
3671
_set_policy(struct rtw89_dev * rtwdev,u16 policy_type,enum btc_reason_and_action action)3672 static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
3673 enum btc_reason_and_action action)
3674 {
3675 const struct rtw89_chip_info *chip = rtwdev->chip;
3676
3677 chip->ops->btc_set_policy(rtwdev, policy_type);
3678 _fw_set_policy(rtwdev, policy_type, action);
3679 }
3680
3681 #define BTC_B1_MAX 250 /* unit ms */
rtw89_btc_set_policy(struct rtw89_dev * rtwdev,u16 policy_type)3682 void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type)
3683 {
3684 struct rtw89_btc *btc = &rtwdev->btc;
3685 struct rtw89_btc_dm *dm = &btc->dm;
3686 struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
3687 struct rtw89_btc_fbtc_slot *s = dm->slot.v1;
3688 u8 type;
3689 u32 tbl_w1, tbl_b1, tbl_b4;
3690
3691 if (btc->ant_type == BTC_ANT_SHARED) {
3692 if (btc->cx.wl.status.map._4way)
3693 tbl_w1 = cxtbl[1];
3694 else
3695 tbl_w1 = cxtbl[8];
3696 tbl_b1 = cxtbl[3];
3697 tbl_b4 = cxtbl[3];
3698 } else {
3699 tbl_w1 = cxtbl[16];
3700 tbl_b1 = cxtbl[17];
3701 tbl_b4 = cxtbl[17];
3702 }
3703
3704 type = (u8)((policy_type & BTC_CXP_MASK) >> 8);
3705 btc->bt_req_en = false;
3706
3707 switch (type) {
3708 case BTC_CXP_USERDEF0:
3709 *t = t_def[CXTD_OFF];
3710 s[CXST_OFF] = s_def[CXST_OFF];
3711 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
3712 btc->update_policy_force = true;
3713 break;
3714 case BTC_CXP_OFF: /* TDMA off */
3715 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
3716 *t = t_def[CXTD_OFF];
3717 s[CXST_OFF] = s_def[CXST_OFF];
3718
3719 switch (policy_type) {
3720 case BTC_CXP_OFF_BT:
3721 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
3722 break;
3723 case BTC_CXP_OFF_WL:
3724 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
3725 break;
3726 case BTC_CXP_OFF_EQ0:
3727 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
3728 break;
3729 case BTC_CXP_OFF_EQ1:
3730 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
3731 break;
3732 case BTC_CXP_OFF_EQ2:
3733 _slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
3734 break;
3735 case BTC_CXP_OFF_EQ3:
3736 _slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
3737 break;
3738 case BTC_CXP_OFF_BWB0:
3739 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
3740 break;
3741 case BTC_CXP_OFF_BWB1:
3742 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
3743 break;
3744 case BTC_CXP_OFF_BWB3:
3745 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
3746 break;
3747 }
3748 break;
3749 case BTC_CXP_OFFB: /* TDMA off + beacon protect */
3750 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
3751 *t = t_def[CXTD_OFF_B2];
3752 s[CXST_OFF] = s_def[CXST_OFF];
3753 switch (policy_type) {
3754 case BTC_CXP_OFFB_BWB0:
3755 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
3756 break;
3757 }
3758 break;
3759 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
3760 btc->bt_req_en = true;
3761 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3762 *t = t_def[CXTD_OFF_EXT];
3763 switch (policy_type) {
3764 case BTC_CXP_OFFE_DEF:
3765 s[CXST_E2G] = s_def[CXST_E2G];
3766 s[CXST_E5G] = s_def[CXST_E5G];
3767 s[CXST_EBT] = s_def[CXST_EBT];
3768 s[CXST_ENULL] = s_def[CXST_ENULL];
3769 break;
3770 case BTC_CXP_OFFE_DEF2:
3771 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
3772 s[CXST_E5G] = s_def[CXST_E5G];
3773 s[CXST_EBT] = s_def[CXST_EBT];
3774 s[CXST_ENULL] = s_def[CXST_ENULL];
3775 break;
3776 }
3777 break;
3778 case BTC_CXP_FIX: /* TDMA Fix-Slot */
3779 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3780 *t = t_def[CXTD_FIX];
3781 switch (policy_type) {
3782 case BTC_CXP_FIX_TD3030:
3783 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3784 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3785 break;
3786 case BTC_CXP_FIX_TD5050:
3787 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3788 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
3789 break;
3790 case BTC_CXP_FIX_TD2030:
3791 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3792 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3793 break;
3794 case BTC_CXP_FIX_TD4010:
3795 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
3796 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3797 break;
3798 case BTC_CXP_FIX_TD4010ISO:
3799 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
3800 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3801 break;
3802 case BTC_CXP_FIX_TD4010ISO_DL:
3803 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
3804 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
3805 break;
3806 case BTC_CXP_FIX_TD4010ISO_UL:
3807 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
3808 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
3809 break;
3810 case BTC_CXP_FIX_TD7010:
3811 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
3812 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
3813 break;
3814 case BTC_CXP_FIX_TD2060:
3815 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3816 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3817 break;
3818 case BTC_CXP_FIX_TD3060:
3819 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3820 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3821 break;
3822 case BTC_CXP_FIX_TD2080:
3823 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3824 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
3825 break;
3826 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
3827 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3828 tbl_w1, SLOT_ISO);
3829 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3830 tbl_b1, SLOT_MIX);
3831 break;
3832 }
3833 break;
3834 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
3835 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3836 *t = t_def[CXTD_PFIX];
3837 if (btc->cx.wl.role_info.role_map.role.ap)
3838 _tdma_set_flctrl(btc, CXFLC_QOSNULL);
3839
3840 switch (policy_type) {
3841 case BTC_CXP_PFIX_TD3030:
3842 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3843 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3844 break;
3845 case BTC_CXP_PFIX_TD5050:
3846 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3847 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
3848 break;
3849 case BTC_CXP_PFIX_TD2030:
3850 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3851 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
3852 break;
3853 case BTC_CXP_PFIX_TD2060:
3854 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3855 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3856 break;
3857 case BTC_CXP_PFIX_TD3070:
3858 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3859 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
3860 break;
3861 case BTC_CXP_PFIX_TD2080:
3862 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3863 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
3864 break;
3865 }
3866 break;
3867 case BTC_CXP_AUTO: /* TDMA Auto-Slot */
3868 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3869 *t = t_def[CXTD_AUTO];
3870 switch (policy_type) {
3871 case BTC_CXP_AUTO_TD50B1:
3872 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3873 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3874 break;
3875 case BTC_CXP_AUTO_TD60B1:
3876 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3877 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3878 break;
3879 case BTC_CXP_AUTO_TD20B1:
3880 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3881 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3882 break;
3883 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
3884 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3885 tbl_w1, SLOT_ISO);
3886 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3887 tbl_b1, SLOT_MIX);
3888 break;
3889 }
3890 break;
3891 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
3892 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3893 *t = t_def[CXTD_PAUTO];
3894 switch (policy_type) {
3895 case BTC_CXP_PAUTO_TD50B1:
3896 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3897 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3898 break;
3899 case BTC_CXP_PAUTO_TD60B1:
3900 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3901 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3902 break;
3903 case BTC_CXP_PAUTO_TD20B1:
3904 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3905 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3906 break;
3907 case BTC_CXP_PAUTO_TDW1B1:
3908 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3909 tbl_w1, SLOT_ISO);
3910 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
3911 tbl_b1, SLOT_MIX);
3912 break;
3913 }
3914 break;
3915 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
3916 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3917 *t = t_def[CXTD_AUTO2];
3918 switch (policy_type) {
3919 case BTC_CXP_AUTO2_TD3050:
3920 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3921 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3922 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3923 break;
3924 case BTC_CXP_AUTO2_TD3070:
3925 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3926 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
3927 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3928 break;
3929 case BTC_CXP_AUTO2_TD5050:
3930 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3931 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3932 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3933 break;
3934 case BTC_CXP_AUTO2_TD6060:
3935 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3936 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
3937 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3938 break;
3939 case BTC_CXP_AUTO2_TD2080:
3940 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3941 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
3942 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3943 break;
3944 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
3945 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3946 tbl_w1, SLOT_ISO);
3947 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
3948 tbl_b4, SLOT_MIX);
3949 break;
3950 }
3951 break;
3952 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
3953 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
3954 *t = t_def[CXTD_PAUTO2];
3955 switch (policy_type) {
3956 case BTC_CXP_PAUTO2_TD3050:
3957 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3958 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3959 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3960 break;
3961 case BTC_CXP_PAUTO2_TD3070:
3962 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
3963 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
3964 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3965 break;
3966 case BTC_CXP_PAUTO2_TD5050:
3967 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
3968 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
3969 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3970 break;
3971 case BTC_CXP_PAUTO2_TD6060:
3972 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
3973 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
3974 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3975 break;
3976 case BTC_CXP_PAUTO2_TD2080:
3977 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
3978 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
3979 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
3980 break;
3981 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
3982 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
3983 tbl_w1, SLOT_ISO);
3984 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
3985 tbl_b4, SLOT_MIX);
3986 break;
3987 }
3988 break;
3989 }
3990 }
3991 EXPORT_SYMBOL(rtw89_btc_set_policy);
3992
rtw89_btc_set_policy_v1(struct rtw89_dev * rtwdev,u16 policy_type)3993 void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
3994 {
3995 struct rtw89_btc *btc = &rtwdev->btc;
3996 struct rtw89_btc_dm *dm = &btc->dm;
3997 struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
3998 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1;
3999 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
4000 struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
4001 struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc;
4002 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4003 u8 type, null_role;
4004 u32 tbl_w1, tbl_b1, tbl_b4;
4005 u16 dur_2;
4006
4007 if (wl->status.map.lps) {
4008 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
4009 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
4010 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4011 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4012 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4013 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4014 }
4015
4016 type = FIELD_GET(BTC_CXP_MASK, policy_type);
4017
4018 if (btc->ant_type == BTC_ANT_SHARED) {
4019 if (btc->cx.wl.status.map._4way)
4020 tbl_w1 = cxtbl[1];
4021 else if (hid->exist && hid->type == BTC_HID_218)
4022 tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */
4023 else
4024 tbl_w1 = cxtbl[8];
4025
4026 if (dm->leak_ap &&
4027 (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) {
4028 tbl_b1 = cxtbl[3];
4029 tbl_b4 = cxtbl[3];
4030 } else if (hid->exist && hid->type == BTC_HID_218) {
4031 tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */
4032 tbl_b4 = cxtbl[4];
4033 } else {
4034 tbl_b1 = cxtbl[2];
4035 tbl_b4 = cxtbl[2];
4036 }
4037 } else {
4038 tbl_b1 = cxtbl[17];
4039 tbl_b4 = cxtbl[17];
4040
4041 if (wl->bg_mode)
4042 tbl_w1 = cxtbl[8];
4043 else if ((wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) &&
4044 hid->exist)
4045 tbl_w1 = cxtbl[19];
4046 else
4047 tbl_w1 = cxtbl[16];
4048 }
4049
4050 switch (type) {
4051 case BTC_CXP_USERDEF0:
4052 btc->update_policy_force = true;
4053 *t = t_def[CXTD_OFF];
4054 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4055 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4056 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
4057 break;
4058 case BTC_CXP_OFF: /* TDMA off */
4059 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
4060 *t = t_def[CXTD_OFF];
4061 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4062 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4063
4064 switch (policy_type) {
4065 case BTC_CXP_OFF_BT:
4066 _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
4067 break;
4068 case BTC_CXP_OFF_WL:
4069 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
4070 break;
4071 case BTC_CXP_OFF_WL2:
4072 _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
4073 _slot_set_type(btc, CXST_OFF, SLOT_ISO);
4074 break;
4075 case BTC_CXP_OFF_EQ0:
4076 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
4077 _slot_set_type(btc, CXST_OFF, SLOT_ISO);
4078 break;
4079 case BTC_CXP_OFF_EQ1:
4080 _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
4081 break;
4082 case BTC_CXP_OFF_EQ2:
4083 _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
4084 break;
4085 case BTC_CXP_OFF_EQ3:
4086 _slot_set_tbl(btc, CXST_OFF, cxtbl[24]);
4087 break;
4088 case BTC_CXP_OFF_EQ4:
4089 _slot_set_tbl(btc, CXST_OFF, cxtbl[26]);
4090 break;
4091 case BTC_CXP_OFF_EQ5:
4092 _slot_set_tbl(btc, CXST_OFF, cxtbl[27]);
4093 break;
4094 case BTC_CXP_OFF_BWB0:
4095 _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
4096 break;
4097 case BTC_CXP_OFF_BWB1:
4098 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
4099 break;
4100 case BTC_CXP_OFF_BWB2:
4101 _slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
4102 break;
4103 case BTC_CXP_OFF_BWB3:
4104 _slot_set_tbl(btc, CXST_OFF, cxtbl[6]);
4105 break;
4106 default:
4107 break;
4108 }
4109 break;
4110 case BTC_CXP_OFFB: /* TDMA off + beacon protect */
4111 _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
4112 *t = t_def[CXTD_OFF_B2];
4113 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4114 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4115
4116 switch (policy_type) {
4117 case BTC_CXP_OFFB_BWB0:
4118 _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
4119 break;
4120 default:
4121 break;
4122 }
4123 break;
4124 case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
4125 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4126 *t = t_def[CXTD_OFF_EXT];
4127
4128 /* To avoid wl-s0 tx break by hid/hfp tx */
4129 if (hid->exist || hfp->exist)
4130 tbl_w1 = cxtbl[16];
4131
4132 dur_2 = dm->e2g_slot_limit;
4133
4134 switch (policy_type) {
4135 case BTC_CXP_OFFE_2GBWISOB: /* for normal-case */
4136 _slot_set(btc, CXST_E2G, 5, tbl_w1, SLOT_ISO);
4137 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4138 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4139 _slot_set_dur(btc, CXST_EBT, dur_2);
4140 break;
4141 case BTC_CXP_OFFE_2GISOB: /* for bt no-link */
4142 _slot_set(btc, CXST_E2G, 5, cxtbl[1], SLOT_ISO);
4143 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4144 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4145 _slot_set_dur(btc, CXST_EBT, dur_2);
4146 break;
4147 case BTC_CXP_OFFE_DEF:
4148 _slot_set_le(btc, CXST_E2G, s_def[CXST_E2G].dur,
4149 s_def[CXST_E2G].cxtbl, s_def[CXST_E2G].cxtype);
4150 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4151 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4152 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4153 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4154 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
4155 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
4156 break;
4157 case BTC_CXP_OFFE_DEF2:
4158 _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
4159 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4160 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4161 _slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4162 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4163 _slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
4164 s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
4165 break;
4166 case BTC_CXP_OFFE_2GBWMIXB:
4167 if (a2dp->exist)
4168 _slot_set(btc, CXST_E2G, 5, cxtbl[2], SLOT_MIX);
4169 else
4170 _slot_set(btc, CXST_E2G, 5, tbl_w1, SLOT_MIX);
4171 _slot_set_le(btc, CXST_EBT, cpu_to_le16(40),
4172 s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4173 break;
4174 case BTC_CXP_OFFE_WL: /* for 4-way */
4175 _slot_set(btc, CXST_E2G, 5, cxtbl[1], SLOT_MIX);
4176 _slot_set(btc, CXST_EBT, 5, cxtbl[1], SLOT_MIX);
4177 break;
4178 default:
4179 break;
4180 }
4181 _slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4182 s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4183 _slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4184 s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4185 break;
4186 case BTC_CXP_FIX: /* TDMA Fix-Slot */
4187 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4188 *t = t_def[CXTD_FIX];
4189
4190 switch (policy_type) {
4191 case BTC_CXP_FIX_TD3030:
4192 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4193 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4194 break;
4195 case BTC_CXP_FIX_TD5050:
4196 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4197 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
4198 break;
4199 case BTC_CXP_FIX_TD2030:
4200 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4201 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4202 break;
4203 case BTC_CXP_FIX_TD4010:
4204 _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
4205 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4206 break;
4207 case BTC_CXP_FIX_TD4010ISO:
4208 _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
4209 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4210 break;
4211 case BTC_CXP_FIX_TD4010ISO_DL:
4212 _slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
4213 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
4214 break;
4215 case BTC_CXP_FIX_TD4010ISO_UL:
4216 _slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
4217 _slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
4218 break;
4219 case BTC_CXP_FIX_TD7010:
4220 _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
4221 _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4222 break;
4223 case BTC_CXP_FIX_TD2060:
4224 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4225 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4226 break;
4227 case BTC_CXP_FIX_TD3060:
4228 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4229 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4230 break;
4231 case BTC_CXP_FIX_TD2080:
4232 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4233 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
4234 break;
4235 case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
4236 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4237 tbl_w1, SLOT_ISO);
4238 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4239 tbl_b1, SLOT_MIX);
4240 break;
4241 default:
4242 break;
4243 }
4244 break;
4245 case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
4246 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4247 *t = t_def[CXTD_PFIX];
4248
4249 switch (policy_type) {
4250 case BTC_CXP_PFIX_TD3030:
4251 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4252 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4253 break;
4254 case BTC_CXP_PFIX_TD5050:
4255 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4256 _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
4257 break;
4258 case BTC_CXP_PFIX_TD2030:
4259 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4260 _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4261 break;
4262 case BTC_CXP_PFIX_TD2060:
4263 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4264 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4265 break;
4266 case BTC_CXP_PFIX_TD3070:
4267 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4268 _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4269 break;
4270 case BTC_CXP_PFIX_TD2080:
4271 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4272 _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
4273 break;
4274 case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */
4275 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4276 tbl_w1, SLOT_ISO);
4277 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4278 tbl_b1, SLOT_MIX);
4279 break;
4280 default:
4281 break;
4282 }
4283 break;
4284 case BTC_CXP_AUTO: /* TDMA Auto-Slot */
4285 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4286 *t = t_def[CXTD_AUTO];
4287
4288 switch (policy_type) {
4289 case BTC_CXP_AUTO_TD50B1:
4290 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4291 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4292 break;
4293 case BTC_CXP_AUTO_TD60B1:
4294 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4295 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4296 break;
4297 case BTC_CXP_AUTO_TD20B1:
4298 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4299 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4300 break;
4301 case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
4302 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4303 tbl_w1, SLOT_ISO);
4304 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4305 tbl_b1, SLOT_MIX);
4306 break;
4307 default:
4308 break;
4309 }
4310 break;
4311 case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
4312 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4313 *t = t_def[CXTD_PAUTO];
4314
4315 switch (policy_type) {
4316 case BTC_CXP_PAUTO_TD50B1:
4317 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4318 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4319 break;
4320 case BTC_CXP_PAUTO_TD60B1:
4321 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4322 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4323 break;
4324 case BTC_CXP_PAUTO_TD20B1:
4325 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4326 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4327 break;
4328 case BTC_CXP_PAUTO_TDW1B1:
4329 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4330 tbl_w1, SLOT_ISO);
4331 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4332 tbl_b1, SLOT_MIX);
4333 break;
4334 default:
4335 break;
4336 }
4337 break;
4338 case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
4339 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4340 *t = t_def[CXTD_AUTO2];
4341
4342 switch (policy_type) {
4343 case BTC_CXP_AUTO2_TD3050:
4344 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4345 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4346 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4347 break;
4348 case BTC_CXP_AUTO2_TD3070:
4349 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4350 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4351 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
4352 break;
4353 case BTC_CXP_AUTO2_TD5050:
4354 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4355 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4356 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4357 break;
4358 case BTC_CXP_AUTO2_TD6060:
4359 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4360 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4361 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
4362 break;
4363 case BTC_CXP_AUTO2_TD2080:
4364 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4365 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4366 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
4367 break;
4368 case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
4369 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4370 tbl_w1, SLOT_ISO);
4371 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4372 tbl_b1, SLOT_MIX);
4373 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
4374 tbl_b4, SLOT_MIX);
4375 break;
4376 default:
4377 break;
4378 }
4379 break;
4380 case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
4381 _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4382 *t = t_def[CXTD_PAUTO2];
4383
4384 switch (policy_type) {
4385 case BTC_CXP_PAUTO2_TD3050:
4386 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4387 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4388 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4389 break;
4390 case BTC_CXP_PAUTO2_TD3070:
4391 _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4392 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4393 _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
4394 break;
4395 case BTC_CXP_PAUTO2_TD5050:
4396 _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4397 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4398 _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4399 break;
4400 case BTC_CXP_PAUTO2_TD6060:
4401 _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4402 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4403 _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
4404 break;
4405 case BTC_CXP_PAUTO2_TD2080:
4406 _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4407 _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4408 _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
4409 break;
4410 case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
4411 _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4412 tbl_w1, SLOT_ISO);
4413 _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4414 tbl_b1, SLOT_MIX);
4415 _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
4416 tbl_b4, SLOT_MIX);
4417 break;
4418 default:
4419 break;
4420 }
4421 break;
4422 }
4423
4424 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) {
4425 null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) |
4426 FIELD_PREP(0xf0, dm->wl_scc.null_role2);
4427 _tdma_set_flctrl_role(btc, null_role);
4428 }
4429
4430 /* enter leak_slot after each null-1 */
4431 if (dm->leak_ap && dm->tdma.leak_n > 1)
4432 _tdma_set_lek(btc, 1);
4433
4434 if (dm->tdma_instant_excute) {
4435 btc->dm.tdma.option_ctrl |= BIT(0);
4436 btc->update_policy_force = true;
4437 }
4438 }
4439 EXPORT_SYMBOL(rtw89_btc_set_policy_v1);
4440
_set_bt_plut(struct rtw89_dev * rtwdev,u8 phy_map,u8 tx_val,u8 rx_val)4441 static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
4442 u8 tx_val, u8 rx_val)
4443 {
4444 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
4445 struct rtw89_mac_ax_plt plt;
4446
4447 plt.tx = tx_val;
4448 plt.rx = rx_val;
4449
4450 if (rtwdev->btc.ver->fwlrole == 8) {
4451 plt.band = wl->pta_req_mac;
4452 if (wl->bt_polut_type[plt.band] == tx_val)
4453 return;
4454
4455 wl->bt_polut_type[plt.band] = tx_val;
4456 rtw89_mac_cfg_plt(rtwdev, &plt);
4457 } else {
4458 plt.band = RTW89_MAC_0;
4459
4460 if (phy_map & BTC_PHY_0)
4461 rtw89_mac_cfg_plt(rtwdev, &plt);
4462
4463 if (!rtwdev->dbcc_en)
4464 return;
4465
4466 plt.band = RTW89_MAC_1;
4467 if (phy_map & BTC_PHY_1)
4468 rtw89_mac_cfg_plt(rtwdev, &plt);
4469 }
4470 }
4471
_set_ant_v0(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4472 static void _set_ant_v0(struct rtw89_dev *rtwdev, bool force_exec,
4473 u8 phy_map, u8 type)
4474 {
4475 struct rtw89_btc *btc = &rtwdev->btc;
4476 struct rtw89_btc_dm *dm = &btc->dm;
4477 struct rtw89_btc_cx *cx = &btc->cx;
4478 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4479 struct rtw89_btc_bt_info *bt = &cx->bt;
4480 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4481 u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0;
4482 bool dbcc_chg = false;
4483 u32 ant_path_type;
4484
4485 ant_path_type = ((phy_map << 8) + type);
4486
4487 if (btc->ver->fwlrole == 1)
4488 dbcc_chg = wl->role_info_v1.dbcc_chg;
4489 else if (btc->ver->fwlrole == 2)
4490 dbcc_chg = wl->role_info_v2.dbcc_chg;
4491 else if (btc->ver->fwlrole == 7)
4492 dbcc_chg = wl->role_info_v7.dbcc_chg;
4493 else if (btc->ver->fwlrole == 8)
4494 dbcc_chg = wl->role_info_v8.dbcc_chg;
4495
4496 if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
4497 btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
4498 btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || dbcc_chg)
4499 force_exec = FC_EXEC;
4500
4501 if (!force_exec && ant_path_type == dm->set_ant_path) {
4502 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4503 "[BTC], %s(): return by no change!!\n",
4504 __func__);
4505 return;
4506 } else if (bt->rfk_info.map.run) {
4507 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4508 "[BTC], %s(): return by bt rfk!!\n", __func__);
4509 return;
4510 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
4511 wl->rfk_info.state != BTC_WRFK_STOP) {
4512 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4513 "[BTC], %s(): return by wl rfk!!\n", __func__);
4514 return;
4515 }
4516
4517 dm->set_ant_path = ant_path_type;
4518
4519 rtw89_debug(rtwdev,
4520 RTW89_DBG_BTC,
4521 "[BTC], %s(): path=0x%x, set_type=0x%x\n",
4522 __func__, phy_map, dm->set_ant_path & 0xff);
4523
4524 switch (type) {
4525 case BTC_ANT_WPOWERON:
4526 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4527 break;
4528 case BTC_ANT_WINIT:
4529 if (bt->enable.now)
4530 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
4531 else
4532 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4533
4534 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4535 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT);
4536 break;
4537 case BTC_ANT_WONLY:
4538 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4539 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4540 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4541 break;
4542 case BTC_ANT_WOFF:
4543 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4544 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4545 break;
4546 case BTC_ANT_W2G:
4547 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4548 if (rtwdev->dbcc_en) {
4549 for (i = 0; i < RTW89_PHY_NUM; i++) {
4550 b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G);
4551
4552 gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
4553 gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
4554 /* BT should control by GNT_BT if WL_2G at S0 */
4555 if (i == 1 &&
4556 wl_dinfo->real_band[0] == RTW89_BAND_2G &&
4557 wl_dinfo->real_band[1] == RTW89_BAND_5G)
4558 gnt_bt_ctrl = BTC_GNT_HW;
4559 _set_gnt(rtwdev, BIT(i), gnt_wl_ctrl, gnt_bt_ctrl);
4560 plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE;
4561 _set_bt_plut(rtwdev, BIT(i),
4562 plt_ctrl, plt_ctrl);
4563 }
4564 } else {
4565 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
4566 _set_bt_plut(rtwdev, BTC_PHY_ALL,
4567 BTC_PLT_BT, BTC_PLT_BT);
4568 }
4569 break;
4570 case BTC_ANT_W5G:
4571 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4572 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW);
4573 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4574 break;
4575 case BTC_ANT_W25G:
4576 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4577 _set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
4578 _set_bt_plut(rtwdev, BTC_PHY_ALL,
4579 BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
4580 break;
4581 case BTC_ANT_FREERUN:
4582 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4583 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI);
4584 _set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4585 break;
4586 case BTC_ANT_WRFK:
4587 case BTC_ANT_WRFK2:
4588 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4589 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4590 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
4591 break;
4592 case BTC_ANT_BRFK:
4593 rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4594 _set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
4595 _set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
4596 break;
4597 default:
4598 break;
4599 }
4600 }
4601
_set_ant_v1(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4602 static void _set_ant_v1(struct rtw89_dev *rtwdev, bool force_exec,
4603 u8 phy_map, u8 type)
4604 {
4605 struct rtw89_btc *btc = &rtwdev->btc;
4606 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4607 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4608 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
4609 u32 ant_path_type = rtw89_get_antpath_type(phy_map, type);
4610 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4611 struct rtw89_btc_dm *dm = &btc->dm;
4612 u8 gwl = BTC_GNT_HW;
4613
4614 if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
4615 btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
4616 btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || wl_rinfo->dbcc_chg)
4617 force_exec = FC_EXEC;
4618
4619 if (wl_rinfo->link_mode != BTC_WLINK_25G_MCC &&
4620 btc->dm.wl_btg_rx == 2)
4621 force_exec = FC_EXEC;
4622
4623 if (!force_exec && ant_path_type == dm->set_ant_path) {
4624 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4625 "[BTC], %s(): return by no change!!\n",
4626 __func__);
4627 return;
4628 } else if (bt->rfk_info.map.run) {
4629 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4630 "[BTC], %s(): return by bt rfk!!\n", __func__);
4631 return;
4632 } else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
4633 wl->rfk_info.state != BTC_WRFK_STOP) {
4634 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4635 "[BTC], %s(): return by wl rfk!!\n", __func__);
4636 return;
4637 }
4638
4639 dm->set_ant_path = ant_path_type;
4640
4641 rtw89_debug(rtwdev, RTW89_DBG_BTC,
4642 "[BTC], %s(): path=0x%x, set_type=0x%x\n",
4643 __func__, phy_map, dm->set_ant_path & 0xff);
4644
4645 switch (type) {
4646 case BTC_ANT_WINIT:
4647 /* To avoid BT MP driver case (bt_enable but no mailbox) */
4648 if (bt->enable.now && bt->run_patch_code)
4649 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
4650 BTC_WLACT_SW_LO);
4651 else
4652 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4653 BTC_WLACT_SW_HI);
4654 break;
4655 case BTC_ANT_WONLY:
4656 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4657 BTC_WLACT_SW_HI);
4658 break;
4659 case BTC_ANT_WOFF:
4660 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
4661 BTC_WLACT_SW_LO);
4662 break;
4663 case BTC_ANT_W2G:
4664 case BTC_ANT_W25G:
4665 if (wl_rinfo->dbcc_en) {
4666 if (wl_dinfo->real_band[RTW89_PHY_0] == RTW89_BAND_2G)
4667 gwl = BTC_GNT_HW;
4668 else
4669 gwl = BTC_GNT_SW_HI;
4670 _set_gnt_v1(rtwdev, BTC_PHY_0, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4671
4672 if (wl_dinfo->real_band[RTW89_PHY_1] == RTW89_BAND_2G)
4673 gwl = BTC_GNT_HW;
4674 else
4675 gwl = BTC_GNT_SW_HI;
4676 _set_gnt_v1(rtwdev, BTC_PHY_1, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4677 } else {
4678 gwl = BTC_GNT_HW;
4679 _set_gnt_v1(rtwdev, phy_map, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4680 }
4681 break;
4682 case BTC_ANT_W5G:
4683 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW, BTC_WLACT_HW);
4684 break;
4685 case BTC_ANT_FREERUN:
4686 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI,
4687 BTC_WLACT_SW_LO);
4688 break;
4689 case BTC_ANT_WRFK:
4690 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4691 BTC_WLACT_HW);
4692 break;
4693 case BTC_ANT_WRFK2:
4694 _set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4695 BTC_WLACT_SW_HI); /* no BT-Tx */
4696 break;
4697 default:
4698 return;
4699 }
4700
4701 _set_bt_plut(rtwdev, phy_map, BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
4702 }
4703
_set_ant(struct rtw89_dev * rtwdev,bool force_exec,u8 phy_map,u8 type)4704 static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
4705 u8 phy_map, u8 type)
4706 {
4707 if (rtwdev->chip->chip_id == RTL8922A)
4708 _set_ant_v1(rtwdev, force_exec, phy_map, type);
4709 else
4710 _set_ant_v0(rtwdev, force_exec, phy_map, type);
4711 }
4712
_action_wl_only(struct rtw89_dev * rtwdev)4713 static void _action_wl_only(struct rtw89_dev *rtwdev)
4714 {
4715 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
4716 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY);
4717 }
4718
_action_wl_init(struct rtw89_dev * rtwdev)4719 static void _action_wl_init(struct rtw89_dev *rtwdev)
4720 {
4721 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4722
4723 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT);
4724 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT);
4725 }
4726
_action_wl_off(struct rtw89_dev * rtwdev,u8 mode)4727 static void _action_wl_off(struct rtw89_dev *rtwdev, u8 mode)
4728 {
4729 struct rtw89_btc *btc = &rtwdev->btc;
4730 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4731
4732 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4733
4734 if (wl->status.map.rf_off || btc->dm.bt_only) {
4735 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF);
4736 } else if (wl->status.map.lps == BTC_LPS_RF_ON) {
4737 if (mode == BTC_WLINK_5G)
4738 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
4739 else
4740 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4741 }
4742
4743 if (mode == BTC_WLINK_5G) {
4744 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OFF);
4745 } else if (wl->status.map.lps == BTC_LPS_RF_ON) {
4746 if (btc->cx.bt.link_info.a2dp_desc.active)
4747 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
4748 else
4749 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_WL_OFF);
4750 } else {
4751 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
4752 }
4753 }
4754
_action_freerun(struct rtw89_dev * rtwdev)4755 static void _action_freerun(struct rtw89_dev *rtwdev)
4756 {
4757 struct rtw89_btc *btc = &rtwdev->btc;
4758
4759 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4760
4761 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN);
4762 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN);
4763
4764 btc->dm.freerun = true;
4765 }
4766
_action_bt_whql(struct rtw89_dev * rtwdev)4767 static void _action_bt_whql(struct rtw89_dev *rtwdev)
4768 {
4769 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4770
4771 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4772 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL);
4773 }
4774
_action_bt_off(struct rtw89_dev * rtwdev)4775 static void _action_bt_off(struct rtw89_dev *rtwdev)
4776 {
4777 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4778
4779 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
4780 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF);
4781 }
4782
_action_bt_idle(struct rtw89_dev * rtwdev)4783 static void _action_bt_idle(struct rtw89_dev *rtwdev)
4784 {
4785 struct rtw89_btc *btc = &rtwdev->btc;
4786 struct rtw89_btc_bt_link_info *b = &btc->cx.bt.link_info;
4787 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4788
4789 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4790
4791 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
4792 switch (btc->cx.state_map) {
4793 case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/
4794 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */
4795 if (b->status.map.connect)
4796 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_IDLE);
4797 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
4798 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_DL, BTC_ACT_BT_IDLE);
4799 else
4800 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_UL, BTC_ACT_BT_IDLE);
4801 break;
4802 case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */
4803 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050,
4804 BTC_ACT_BT_IDLE);
4805 break;
4806 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */
4807 _set_policy(rtwdev, BTC_CXP_FIX_TD5050,
4808 BTC_ACT_BT_IDLE);
4809 break;
4810 case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */
4811 _set_policy(rtwdev, BTC_CXP_FIX_TD7010,
4812 BTC_ACT_BT_IDLE);
4813 break;
4814 case BTC_WIDLE: /* wl-idle + bt-idle */
4815 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE);
4816 break;
4817 }
4818 } else { /* dedicated-antenna */
4819 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE);
4820 }
4821 }
4822
_action_bt_hfp(struct rtw89_dev * rtwdev)4823 static void _action_bt_hfp(struct rtw89_dev *rtwdev)
4824 {
4825 struct rtw89_btc *btc = &rtwdev->btc;
4826 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4827
4828 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4829
4830 if (btc->ant_type == BTC_ANT_SHARED) {
4831 if (btc->cx.wl.status.map._4way) {
4832 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP);
4833 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4834 btc->cx.bt.scan_rx_low_pri = true;
4835 _set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP);
4836 } else {
4837 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
4838 }
4839 } else {
4840 if (wl->bg_mode)
4841 _set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
4842 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
4843 _set_policy(rtwdev, BTC_CXP_OFF_EQ5, BTC_ACT_BT_HFP);
4844 else
4845 _set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP);
4846 }
4847 }
4848
_action_bt_hid(struct rtw89_dev * rtwdev)4849 static void _action_bt_hid(struct rtw89_dev *rtwdev)
4850 {
4851 const struct rtw89_chip_info *chip = rtwdev->chip;
4852 struct rtw89_btc *btc = &rtwdev->btc;
4853 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4854 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4855 struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc;
4856 u16 policy_type = BTC_CXP_OFF_BT;
4857
4858 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4859
4860 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
4861 if (wl->status.map._4way) {
4862 policy_type = BTC_CXP_OFF_WL;
4863 } else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4864 btc->cx.bt.scan_rx_low_pri = true;
4865 if (hid->type & BTC_HID_BLE)
4866 policy_type = BTC_CXP_OFF_BWB0;
4867 else
4868 policy_type = BTC_CXP_OFF_BWB2;
4869 } else if (hid->type == BTC_HID_218) {
4870 bt->scan_rx_low_pri = true;
4871 policy_type = BTC_CXP_OFF_BWB2;
4872 } else if (chip->para_ver == 0x1) {
4873 policy_type = BTC_CXP_OFF_BWB3;
4874 } else {
4875 policy_type = BTC_CXP_OFF_BWB1;
4876 }
4877 } else { /* dedicated-antenna */
4878 if (wl->bg_mode)
4879 policy_type = BTC_CXP_OFF_BWB1;
4880 else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
4881 policy_type = BTC_CXP_OFF_EQ4;
4882 else
4883 policy_type = BTC_CXP_OFF_EQ3;
4884 }
4885
4886 _set_policy(rtwdev, policy_type, BTC_ACT_BT_HID);
4887 }
4888
_action_bt_a2dp(struct rtw89_dev * rtwdev)4889 static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
4890 {
4891 struct rtw89_btc *btc = &rtwdev->btc;
4892 struct rtw89_btc_dm *dm = &btc->dm;
4893
4894 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4895
4896 dm->slot_dur[CXST_W1] = 20;
4897 dm->slot_dur[CXST_B1] = BTC_B1_MAX;
4898
4899 switch (btc->cx.state_map) {
4900 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
4901 _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
4902 break;
4903 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
4904 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP);
4905 break;
4906 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */
4907 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP);
4908 break;
4909 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
4910 case BTC_WLINKING: /* wl-connecting + bt-A2DP */
4911 if (btc->cx.wl.rfk_info.con_rfk)
4912 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP);
4913 else
4914 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP);
4915 break;
4916 case BTC_WIDLE: /* wl-idle + bt-A2DP */
4917 _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP);
4918 break;
4919 }
4920 }
4921
_action_bt_a2dpsink(struct rtw89_dev * rtwdev)4922 static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev)
4923 {
4924 struct rtw89_btc *btc = &rtwdev->btc;
4925
4926 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4927
4928 switch (btc->cx.state_map) {
4929 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */
4930 _set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK);
4931 break;
4932 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */
4933 _set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK);
4934 break;
4935 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */
4936 _set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK);
4937 break;
4938 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */
4939 _set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK);
4940 break;
4941 case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */
4942 if (btc->cx.wl.rfk_info.con_rfk)
4943 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DPSINK);
4944 else
4945 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
4946 break;
4947 case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */
4948 _set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK);
4949 break;
4950 }
4951 }
4952
_action_bt_pan(struct rtw89_dev * rtwdev)4953 static void _action_bt_pan(struct rtw89_dev *rtwdev)
4954 {
4955 struct rtw89_btc *btc = &rtwdev->btc;
4956 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
4957 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
4958 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
4959
4960 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4961
4962 switch (btc->cx.state_map) {
4963 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */
4964 if (a2dp.active || !pan.exist) {
4965 btc->dm.slot_dur[CXST_W1] = 80;
4966 btc->dm.slot_dur[CXST_B1] = 20;
4967 _set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN);
4968 } else {
4969 _set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
4970 }
4971 break;
4972 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */
4973 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN);
4974 break;
4975 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */
4976 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN);
4977 break;
4978 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */
4979 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN);
4980 break;
4981 case BTC_WLINKING: /* wl-connecting + bt-PAN */
4982 _set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO, BTC_ACT_BT_PAN);
4983 break;
4984 case BTC_WIDLE: /* wl-idle + bt-pan */
4985 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN);
4986 break;
4987 }
4988 }
4989
_action_bt_a2dp_hid(struct rtw89_dev * rtwdev)4990 static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
4991 {
4992 struct rtw89_btc *btc = &rtwdev->btc;
4993 struct rtw89_btc_dm *dm = &btc->dm;
4994
4995 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4996
4997 dm->slot_dur[CXST_W1] = 20;
4998 dm->slot_dur[CXST_B1] = BTC_B1_MAX;
4999
5000 switch (btc->cx.state_map) {
5001 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */
5002 case BTC_WIDLE: /* wl-idle + bt-A2DP */
5003 _set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
5004 break;
5005 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */
5006 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_HID);
5007 break;
5008
5009 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */
5010 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
5011 break;
5012 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */
5013 case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */
5014 if (btc->cx.wl.rfk_info.con_rfk)
5015 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP_HID);
5016 else
5017 _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
5018 break;
5019 }
5020 }
5021
_action_bt_a2dp_pan(struct rtw89_dev * rtwdev)5022 static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev)
5023 {
5024 struct rtw89_btc *btc = &rtwdev->btc;
5025
5026 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5027
5028 switch (btc->cx.state_map) {
5029 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */
5030 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
5031 break;
5032 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */
5033 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
5034 break;
5035 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */
5036 _set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN);
5037 break;
5038 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */
5039 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
5040 break;
5041 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */
5042 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN);
5043 break;
5044 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */
5045 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN);
5046 break;
5047 }
5048 }
5049
_action_bt_pan_hid(struct rtw89_dev * rtwdev)5050 static void _action_bt_pan_hid(struct rtw89_dev *rtwdev)
5051 {
5052 struct rtw89_btc *btc = &rtwdev->btc;
5053
5054 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5055
5056 switch (btc->cx.state_map) {
5057 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */
5058 _set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID);
5059 break;
5060 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */
5061 _set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID);
5062 break;
5063 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */
5064 _set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID);
5065 break;
5066 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */
5067 _set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID);
5068 break;
5069 case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */
5070 _set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID);
5071 break;
5072 case BTC_WIDLE: /* wl-idle + bt-PAN+HID */
5073 _set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID);
5074 break;
5075 }
5076 }
5077
_action_bt_a2dp_pan_hid(struct rtw89_dev * rtwdev)5078 static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev)
5079 {
5080 struct rtw89_btc *btc = &rtwdev->btc;
5081
5082 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5083
5084 switch (btc->cx.state_map) {
5085 case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */
5086 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
5087 BTC_ACT_BT_A2DP_PAN_HID);
5088 break;
5089 case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */
5090 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
5091 BTC_ACT_BT_A2DP_PAN_HID);
5092 break;
5093 case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */
5094 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3070,
5095 BTC_ACT_BT_A2DP_PAN_HID);
5096 break;
5097 case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */
5098 case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */
5099 _set_policy(rtwdev, BTC_CXP_AUTO2_TD3050,
5100 BTC_ACT_BT_A2DP_PAN_HID);
5101 break;
5102 case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */
5103 _set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080,
5104 BTC_ACT_BT_A2DP_PAN_HID);
5105 break;
5106 }
5107 }
5108
_action_wl_5g(struct rtw89_dev * rtwdev)5109 static void _action_wl_5g(struct rtw89_dev *rtwdev)
5110 {
5111 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
5112 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G);
5113 }
5114
_action_wl_other(struct rtw89_dev * rtwdev)5115 static void _action_wl_other(struct rtw89_dev *rtwdev)
5116 {
5117 struct rtw89_btc *btc = &rtwdev->btc;
5118
5119 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5120
5121 if (btc->ant_type == BTC_ANT_SHARED)
5122 _set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER);
5123 else
5124 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER);
5125 }
5126
_action_wl_nc(struct rtw89_dev * rtwdev)5127 static void _action_wl_nc(struct rtw89_dev *rtwdev)
5128 {
5129 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5130 _set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC);
5131 }
5132
_action_wl_rfk(struct rtw89_dev * rtwdev)5133 static void _action_wl_rfk(struct rtw89_dev *rtwdev)
5134 {
5135 struct rtw89_btc *btc = &rtwdev->btc;
5136 struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info;
5137
5138 if (rfk.state != BTC_WRFK_START)
5139 return;
5140
5141 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n",
5142 __func__, rfk.band);
5143
5144 btc->dm.tdma_instant_excute = 1;
5145
5146 if (rfk.state == BTC_WRFK_ONESHOT_START ||
5147 btc->ant_type == BTC_ANT_SHARED) {
5148 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2);
5149 _set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK);
5150 } else {
5151 _set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
5152 _set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK);
5153 }
5154 }
5155
_set_btg_ctrl(struct rtw89_dev * rtwdev)5156 static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
5157 {
5158 struct rtw89_btc *btc = &rtwdev->btc;
5159 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5160 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5161 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5162 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
5163 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5164 struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info;
5165 struct rtw89_btc_wl_role_info *wl_rinfo_v0 = &wl->role_info;
5166 const struct rtw89_chip_info *chip = rtwdev->chip;
5167 const struct rtw89_btc_ver *ver = btc->ver;
5168 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5169 struct rtw89_btc_dm *dm = &btc->dm;
5170 struct _wl_rinfo_now wl_rinfo;
5171 u32 is_btg = BTC_BTGCTRL_DISABLE;
5172
5173 if (btc->manual_ctrl)
5174 return;
5175
5176 if (ver->fwlrole == 0)
5177 wl_rinfo.link_mode = wl_rinfo_v0->link_mode;
5178 else if (ver->fwlrole == 1)
5179 wl_rinfo.link_mode = wl_rinfo_v1->link_mode;
5180 else if (ver->fwlrole == 2)
5181 wl_rinfo.link_mode = wl_rinfo_v2->link_mode;
5182 else if (ver->fwlrole == 7)
5183 wl_rinfo.link_mode = wl_rinfo_v7->link_mode;
5184 else if (ver->fwlrole == 8)
5185 wl_rinfo.link_mode = wl_rinfo_v8->link_mode;
5186 else
5187 return;
5188
5189 /* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */
5190 if (btc->ant_type == BTC_ANT_SHARED) {
5191 if (!(bt->run_patch_code && bt->enable.now))
5192 is_btg = BTC_BTGCTRL_DISABLE;
5193 else if (wl_rinfo.link_mode != BTC_WLINK_5G)
5194 is_btg = BTC_BTGCTRL_ENABLE;
5195 else
5196 is_btg = BTC_BTGCTRL_DISABLE;
5197
5198 /* bb call ctrl_btg() in WL FW by slot */
5199 if (!ver->fcxosi &&
5200 wl_rinfo.link_mode == BTC_WLINK_25G_MCC)
5201 is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL;
5202 }
5203
5204 if (is_btg == dm->wl_btg_rx)
5205 return;
5206 else
5207 dm->wl_btg_rx = is_btg;
5208
5209 /* skip setup if btg_ctrl set by wl fw */
5210 if (!ver->fcxosi && is_btg > BTC_BTGCTRL_ENABLE)
5211 return;
5212
5213 /* Below flow is for BTC_FEAT_NEW_BBAPI_FLOW = 1 */
5214 if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */
5215 if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */
5216 o_info->btg_rx[BTC_RF_S0] = BTC_BTGCTRL_DISABLE;
5217 else
5218 o_info->btg_rx[BTC_RF_S0] = is_btg;
5219
5220 if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */
5221 o_info->btg_rx[BTC_RF_S1] = BTC_BTGCTRL_DISABLE;
5222 else
5223 o_info->btg_rx[BTC_RF_S1] = is_btg;
5224 } else { /* 2+0 or 0+2 */
5225 o_info->btg_rx[BTC_RF_S0] = is_btg;
5226 o_info->btg_rx[BTC_RF_S1] = is_btg;
5227 }
5228
5229 if (ver->fcxosi)
5230 return;
5231
5232 chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S0],
5233 RTW89_PHY_0);
5234 if (chip->chip_id != RTL8922A)
5235 return;
5236
5237 chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S1],
5238 RTW89_PHY_1);
5239 }
5240
_set_wl_preagc_ctrl(struct rtw89_dev * rtwdev)5241 static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev)
5242 {
5243 struct rtw89_btc *btc = &rtwdev->btc;
5244 struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info;
5245 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
5246 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5247 struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2;
5248 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
5249 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8;
5250 const struct rtw89_chip_info *chip = rtwdev->chip;
5251 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5252 struct rtw89_btc_dm *dm = &btc->dm;
5253 u8 is_preagc, val, link_mode, dbcc_2g_phy;
5254 u8 role_ver = rtwdev->btc.ver->fwlrole;
5255 bool dbcc_en;
5256
5257 if (btc->manual_ctrl)
5258 return;
5259
5260 if (role_ver == 2) {
5261 dbcc_en = rinfo_v2->dbcc_en;
5262 link_mode = rinfo_v2->link_mode;
5263 dbcc_2g_phy = rinfo_v2->dbcc_2g_phy;
5264 } else if (role_ver == 7) {
5265 dbcc_en = rinfo_v7->dbcc_en;
5266 link_mode = rinfo_v7->link_mode;
5267 dbcc_2g_phy = rinfo_v7->dbcc_2g_phy;
5268 } else if (role_ver == 8) {
5269 dbcc_en = rinfo_v8->dbcc_en;
5270 link_mode = rinfo_v8->link_mode;
5271 dbcc_2g_phy = rinfo_v7->dbcc_2g_phy;
5272 } else {
5273 return;
5274 }
5275
5276 if (!(bt->run_patch_code && bt->enable.now)) {
5277 is_preagc = BTC_PREAGC_DISABLE;
5278 } else if (link_mode == BTC_WLINK_5G) {
5279 is_preagc = BTC_PREAGC_DISABLE;
5280 } else if (link_mode == BTC_WLINK_NOLINK ||
5281 btc->cx.bt.link_info.profile_cnt.now == 0) {
5282 is_preagc = BTC_PREAGC_DISABLE;
5283 } else if (dm->tdma_now.type != CXTDMA_OFF &&
5284 !bt_linfo->hfp_desc.exist &&
5285 !bt_linfo->hid_desc.exist &&
5286 dm->fddt_train == BTC_FDDT_DISABLE) {
5287 is_preagc = BTC_PREAGC_DISABLE;
5288 } else if (dbcc_en && (dbcc_2g_phy != RTW89_PHY_1)) {
5289 is_preagc = BTC_PREAGC_DISABLE;
5290 } else if (btc->ant_type == BTC_ANT_SHARED) {
5291 is_preagc = BTC_PREAGC_DISABLE;
5292 } else {
5293 is_preagc = BTC_PREAGC_ENABLE;
5294 }
5295
5296 if (!btc->ver->fcxosi && link_mode == BTC_WLINK_25G_MCC)
5297 is_preagc = BTC_PREAGC_BB_FWCTRL;
5298
5299 if (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
5300 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) {
5301 _get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val);
5302 dm->wl_pre_agc_rb = val;
5303 }
5304
5305 if ((wl->coex_mode == BTC_MODE_NORMAL &&
5306 (dm->run_reason == BTC_RSN_NTFY_INIT ||
5307 dm->run_reason == BTC_RSN_NTFY_SWBAND ||
5308 dm->wl_pre_agc_rb != dm->wl_pre_agc)) ||
5309 is_preagc != dm->wl_pre_agc) {
5310 dm->wl_pre_agc = is_preagc;
5311
5312 if (!btc->ver->fcxosi && is_preagc > BTC_PREAGC_ENABLE)
5313 return;
5314
5315 if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */
5316 if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */
5317 o_info->nbtg_tx[BTC_RF_S0] = BTC_PREAGC_DISABLE;
5318 else
5319 o_info->nbtg_tx[BTC_RF_S0] = is_preagc;
5320
5321 if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */
5322 o_info->nbtg_tx[BTC_RF_S1] = BTC_PREAGC_DISABLE;
5323 else
5324 o_info->nbtg_tx[BTC_RF_S1] = is_preagc;
5325
5326 } else { /* 2+0 or 0+2 */
5327 o_info->nbtg_tx[BTC_RF_S0] = is_preagc;
5328 o_info->nbtg_tx[BTC_RF_S1] = is_preagc;
5329 }
5330
5331 if (btc->ver->fcxosi)
5332 return;
5333
5334 chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S0],
5335 RTW89_PHY_0);
5336 if (chip->chip_id != RTL8922A)
5337 return;
5338 chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S1],
5339 RTW89_PHY_1);
5340 }
5341 }
5342
5343 struct rtw89_txtime_data {
5344 struct rtw89_dev *rtwdev;
5345 int type;
5346 u32 tx_time;
5347 u8 tx_retry;
5348 u16 enable;
5349 bool reenable;
5350 };
5351
__rtw89_tx_time_iter(struct rtw89_vif_link * rtwvif_link,struct rtw89_sta_link * rtwsta_link,struct rtw89_txtime_data * iter_data)5352 static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link,
5353 struct rtw89_sta_link *rtwsta_link,
5354 struct rtw89_txtime_data *iter_data)
5355 {
5356 struct rtw89_dev *rtwdev = iter_data->rtwdev;
5357 struct rtw89_btc *btc = &rtwdev->btc;
5358 struct rtw89_btc_cx *cx = &btc->cx;
5359 struct rtw89_btc_wl_info *wl = &cx->wl;
5360 struct rtw89_btc_wl_link_info *plink = NULL;
5361 u8 port = rtwvif_link->port;
5362 u32 tx_time = iter_data->tx_time;
5363 u8 tx_retry = iter_data->tx_retry;
5364 u16 enable = iter_data->enable;
5365 bool reenable = iter_data->reenable;
5366
5367 if (btc->ver->fwlrole == 8)
5368 plink = &wl->rlink_info[port][0];
5369 else
5370 plink = &wl->link_info[port];
5371
5372 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5373 "[BTC], %s(): port = %d\n", __func__, port);
5374
5375 if (!plink->connected) {
5376 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5377 "[BTC], %s(): connected = %d\n",
5378 __func__, plink->connected);
5379 return;
5380 }
5381
5382 /* backup the original tx time before tx-limit on */
5383 if (reenable) {
5384 rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time);
5385 rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry);
5386 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5387 "[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n",
5388 __func__, plink->tx_time, plink->tx_retry);
5389 }
5390
5391 /* restore the original tx time if no tx-limit */
5392 if (!enable) {
5393 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time);
5394 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true,
5395 plink->tx_retry);
5396 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5397 "[BTC], %s(): restore, tx_time=%d tx_retry= %d\n",
5398 __func__, plink->tx_time, plink->tx_retry);
5399
5400 } else {
5401 rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time);
5402 rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry);
5403 rtw89_debug(rtwdev, RTW89_DBG_BTC,
5404 "[BTC], %s(): set, tx_time=%d tx_retry= %d\n",
5405 __func__, tx_time, tx_retry);
5406 }
5407 }
5408
rtw89_tx_time_iter(void * data,struct ieee80211_sta * sta)5409 static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
5410 {
5411 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
5412 struct rtw89_txtime_data *iter_data =
5413 (struct rtw89_txtime_data *)data;
5414 struct rtw89_vif_link *rtwvif_link;
5415 struct rtw89_sta_link *rtwsta_link;
5416 unsigned int link_id;
5417
5418 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
5419 rtwvif_link = rtwsta_link->rtwvif_link;
5420 __rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data);
5421 }
5422 }
5423
_set_wl_tx_limit(struct rtw89_dev * rtwdev)5424 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
5425 {
5426 struct rtw89_btc *btc = &rtwdev->btc;
5427 const struct rtw89_btc_ver *ver = btc->ver;
5428 struct rtw89_btc_cx *cx = &btc->cx;
5429 struct rtw89_btc_dm *dm = &btc->dm;
5430 struct rtw89_btc_wl_info *wl = &cx->wl;
5431 struct rtw89_btc_bt_info *bt = &cx->bt;
5432 struct rtw89_btc_bt_link_info *b = &bt->link_info;
5433 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
5434 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
5435 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5436 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5437 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5438 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
5439 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5440 struct rtw89_txtime_data data = {.rtwdev = rtwdev};
5441 u8 mode, igno_bt, tx_retry;
5442 u32 tx_time;
5443 u16 enable;
5444 bool reenable = false;
5445
5446 if (btc->manual_ctrl)
5447 return;
5448
5449 if (ver->fwlrole == 0)
5450 mode = wl_rinfo->link_mode;
5451 else if (ver->fwlrole == 1)
5452 mode = wl_rinfo_v1->link_mode;
5453 else if (ver->fwlrole == 2)
5454 mode = wl_rinfo_v2->link_mode;
5455 else if (ver->fwlrole == 7)
5456 mode = wl_rinfo_v7->link_mode;
5457 else if (ver->fwlrole == 8)
5458 mode = wl_rinfo_v8->link_mode;
5459 else
5460 return;
5461
5462 if (ver->fcxctrl == 7)
5463 igno_bt = btc->ctrl.ctrl_v7.igno_bt;
5464 else
5465 igno_bt = btc->ctrl.ctrl.igno_bt;
5466
5467 if (btc->dm.freerun || igno_bt || b->profile_cnt.now == 0 ||
5468 mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) {
5469 enable = 0;
5470 tx_time = BTC_MAX_TX_TIME_DEF;
5471 tx_retry = BTC_MAX_TX_RETRY_DEF;
5472 } else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) {
5473 enable = 1;
5474 tx_time = BTC_MAX_TX_TIME_L2;
5475 tx_retry = BTC_MAX_TX_RETRY_L1;
5476 } else if (hfp->exist || hid->exist) {
5477 enable = 1;
5478 tx_time = BTC_MAX_TX_TIME_L3;
5479 tx_retry = BTC_MAX_TX_RETRY_L1;
5480 } else {
5481 enable = 0;
5482 tx_time = BTC_MAX_TX_TIME_DEF;
5483 tx_retry = BTC_MAX_TX_RETRY_DEF;
5484 }
5485
5486 if (dm->wl_tx_limit.enable == enable &&
5487 dm->wl_tx_limit.tx_time == tx_time &&
5488 dm->wl_tx_limit.tx_retry == tx_retry)
5489 return;
5490
5491 if (!dm->wl_tx_limit.enable && enable)
5492 reenable = true;
5493
5494 dm->wl_tx_limit.enable = enable;
5495 dm->wl_tx_limit.tx_time = tx_time;
5496 dm->wl_tx_limit.tx_retry = tx_retry;
5497
5498 data.enable = enable;
5499 data.tx_time = tx_time;
5500 data.tx_retry = tx_retry;
5501 data.reenable = reenable;
5502
5503 ieee80211_iterate_stations_atomic(rtwdev->hw,
5504 rtw89_tx_time_iter,
5505 &data);
5506 }
5507
_set_bt_rx_agc(struct rtw89_dev * rtwdev)5508 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
5509 {
5510 struct rtw89_btc *btc = &rtwdev->btc;
5511 const struct rtw89_btc_ver *ver = btc->ver;
5512 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5513 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5514 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5515 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5516 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
5517 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5518 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5519 bool bt_hi_lna_rx = false;
5520 u8 mode;
5521
5522 if (ver->fwlrole == 0)
5523 mode = wl_rinfo->link_mode;
5524 else if (ver->fwlrole == 1)
5525 mode = wl_rinfo_v1->link_mode;
5526 else if (ver->fwlrole == 2)
5527 mode = wl_rinfo_v2->link_mode;
5528 else if (ver->fwlrole == 7)
5529 mode = wl_rinfo_v7->link_mode;
5530 else if (ver->fwlrole == 8)
5531 mode = wl_rinfo_v8->link_mode;
5532 else
5533 return;
5534
5535 if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
5536 bt_hi_lna_rx = true;
5537
5538 if (bt_hi_lna_rx == bt->hi_lna_rx)
5539 return;
5540
5541 _write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx);
5542 }
5543
_set_bt_rx_scan_pri(struct rtw89_dev * rtwdev)5544 static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev)
5545 {
5546 struct rtw89_btc *btc = &rtwdev->btc;
5547 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5548
5549 _write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri));
5550 }
5551
_wl_req_mac(struct rtw89_dev * rtwdev,u8 mac)5552 static void _wl_req_mac(struct rtw89_dev *rtwdev, u8 mac)
5553 {
5554 struct rtw89_btc *btc = &rtwdev->btc;
5555 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5556 struct rtw89_btc_dm *dm = &btc->dm;
5557 u32 add;
5558
5559 if (mac == wl->pta_req_mac)
5560 return;
5561
5562 dm->ost_info.pta_req_hw_band = mac;
5563 wl->pta_req_mac = mac;
5564 wl->pta_reg_mac_chg = true;
5565
5566 if (btc->ver->fcxosi)
5567 return;
5568
5569 if (rtwdev->chip->chip_gen == RTW89_CHIP_BE)
5570 add = R_BE_BTC_CFG;
5571 else
5572 add = R_AX_BTC_CFG;
5573
5574 if (mac == RTW89_MAC_0)
5575 rtw89_write32_clr(rtwdev, add, B_AX_WL_SRC);
5576 else
5577 rtw89_write32_set(rtwdev, add, B_AX_WL_SRC);
5578 }
5579
_action_common(struct rtw89_dev * rtwdev)5580 static void _action_common(struct rtw89_dev *rtwdev)
5581 {
5582 struct rtw89_btc *btc = &rtwdev->btc;
5583 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5584 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8;
5585 struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
5586 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5587 struct rtw89_btc_dm *dm = &btc->dm;
5588 u32 bt_rom_code_id, bt_fw_ver;
5589
5590 if (btc->ver->fwlrole == 8)
5591 _wl_req_mac(rtwdev, rinfo_v8->pta_req_band);
5592
5593 _set_btg_ctrl(rtwdev);
5594 _set_wl_preagc_ctrl(rtwdev);
5595 _set_wl_tx_limit(rtwdev);
5596 _set_bt_afh_info(rtwdev);
5597 _set_bt_rx_agc(rtwdev);
5598 _set_rf_trx_para(rtwdev);
5599 _set_bt_rx_scan_pri(rtwdev);
5600
5601 bt_rom_code_id = chip_id_to_bt_rom_code_id(rtwdev->btc.ver->chip_id);
5602 bt_fw_ver = bt->ver_info.fw & 0xffff;
5603 if (bt->enable.now &&
5604 (bt_fw_ver == 0 ||
5605 (bt_fw_ver == bt_rom_code_id && bt->run_patch_code && rtwdev->chip->scbd)))
5606 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 1);
5607 else
5608 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 0);
5609
5610 if (dm->run_reason == BTC_RSN_NTFY_INIT ||
5611 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE ||
5612 dm->run_reason == BTC_RSN_NTFY_POWEROFF) {
5613 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
5614
5615 if (wl_smap->rf_off == 1 || wl_smap->lps != BTC_LPS_OFF)
5616 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
5617 else
5618 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
5619 }
5620
5621 if (wl->scbd_change) {
5622 rtw89_mac_cfg_sb(rtwdev, wl->scbd);
5623 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n",
5624 wl->scbd);
5625 wl->scbd_change = false;
5626 btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++;
5627 }
5628
5629 if (btc->ver->fcxosi) {
5630 if (memcmp(&dm->ost_info_last, &dm->ost_info,
5631 sizeof(dm->ost_info_last)) ||
5632 dm->run_reason == BTC_RSN_NTFY_INIT ||
5633 dm->run_reason == BTC_RSN_NTFY_RADIO_STATE) {
5634 dm->ost_info_last = dm->ost_info;
5635 _fw_set_drv_info(rtwdev, CXDRVINFO_OSI);
5636 }
5637 }
5638 btc->dm.tdma_instant_excute = 0;
5639 wl->pta_reg_mac_chg = false;
5640 }
5641
_action_by_bt(struct rtw89_dev * rtwdev)5642 static void _action_by_bt(struct rtw89_dev *rtwdev)
5643 {
5644 struct rtw89_btc *btc = &rtwdev->btc;
5645 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5646 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
5647 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
5648 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
5649 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
5650 struct rtw89_btc_dm *dm = &btc->dm;
5651 u8 profile_map = 0;
5652
5653 if (dm->freerun_chk) {
5654 _action_freerun(rtwdev);
5655 return;
5656 }
5657
5658 if (bt_linfo->hfp_desc.exist)
5659 profile_map |= BTC_BT_HFP;
5660
5661 if (bt_linfo->hid_desc.exist)
5662 profile_map |= BTC_BT_HID;
5663
5664 if (bt_linfo->a2dp_desc.exist)
5665 profile_map |= BTC_BT_A2DP;
5666
5667 if (bt_linfo->pan_desc.exist)
5668 profile_map |= BTC_BT_PAN;
5669
5670 switch (profile_map) {
5671 case BTC_BT_NOPROFILE:
5672 if (pan.active)
5673 _action_bt_pan(rtwdev);
5674 else
5675 _action_bt_idle(rtwdev);
5676 break;
5677 case BTC_BT_HFP:
5678 _action_bt_hfp(rtwdev);
5679 break;
5680 case BTC_BT_HFP | BTC_BT_HID:
5681 case BTC_BT_HID:
5682 _action_bt_hid(rtwdev);
5683 break;
5684 case BTC_BT_A2DP:
5685 if (a2dp.sink)
5686 _action_bt_a2dpsink(rtwdev);
5687 else if (bt_linfo->multi_link.now && !hid.pair_cnt)
5688 _action_bt_a2dp_pan(rtwdev);
5689 else
5690 _action_bt_a2dp(rtwdev);
5691 break;
5692 case BTC_BT_PAN:
5693 _action_bt_pan(rtwdev);
5694 break;
5695 case BTC_BT_A2DP | BTC_BT_HFP:
5696 case BTC_BT_A2DP | BTC_BT_HID:
5697 case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID:
5698 if (a2dp.sink)
5699 _action_bt_a2dpsink(rtwdev);
5700 else if (pan.active)
5701 _action_bt_a2dp_pan_hid(rtwdev);
5702 else
5703 _action_bt_a2dp_hid(rtwdev);
5704 break;
5705 case BTC_BT_A2DP | BTC_BT_PAN:
5706 if (a2dp.sink)
5707 _action_bt_a2dpsink(rtwdev);
5708 else
5709 _action_bt_a2dp_pan(rtwdev);
5710 break;
5711 case BTC_BT_PAN | BTC_BT_HFP:
5712 case BTC_BT_PAN | BTC_BT_HID:
5713 case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID:
5714 _action_bt_pan_hid(rtwdev);
5715 break;
5716 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID:
5717 case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP:
5718 default:
5719 if (a2dp.sink)
5720 _action_bt_a2dpsink(rtwdev);
5721 else
5722 _action_bt_a2dp_pan_hid(rtwdev);
5723 break;
5724 }
5725 }
5726
_action_wl_2g_sta(struct rtw89_dev * rtwdev)5727 static void _action_wl_2g_sta(struct rtw89_dev *rtwdev)
5728 {
5729 _action_by_bt(rtwdev);
5730 }
5731
_action_wl_25g_mcc(struct rtw89_dev * rtwdev)5732 static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev)
5733 {
5734 struct rtw89_btc *btc = &rtwdev->btc;
5735 u16 policy_type = BTC_CXP_OFF_BT;
5736
5737 if (btc->ant_type == BTC_ANT_SHARED) {
5738 if (btc->cx.wl.status.map._4way)
5739 policy_type = BTC_CXP_OFFE_WL;
5740 else if (btc->cx.wl.status.val & btc_scanning_map.val)
5741 policy_type = BTC_CXP_OFFE_2GBWMIXB;
5742 else if (btc->cx.bt.link_info.status.map.connect == 0)
5743 policy_type = BTC_CXP_OFFE_2GISOB;
5744 else
5745 policy_type = BTC_CXP_OFFE_2GBWISOB;
5746 } else { /* dedicated-antenna */
5747 policy_type = BTC_CXP_OFF_EQ0;
5748 }
5749
5750 btc->dm.e2g_slot_limit = BTC_E2G_LIMIT_DEF;
5751
5752 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
5753 _set_policy(rtwdev, policy_type, BTC_ACT_WL_25G_MCC);
5754 }
5755
_action_wl_scan(struct rtw89_dev * rtwdev)5756 static void _action_wl_scan(struct rtw89_dev *rtwdev)
5757 {
5758 struct rtw89_btc *btc = &rtwdev->btc;
5759 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5760 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5761
5762 if (btc->cx.state_map != BTC_WLINKING &&
5763 RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
5764 _action_wl_25g_mcc(rtwdev);
5765 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n");
5766 } else if (rtwdev->dbcc_en) {
5767 if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G &&
5768 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
5769 _action_wl_5g(rtwdev);
5770 else
5771 _action_by_bt(rtwdev);
5772 } else {
5773 if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G)
5774 _action_wl_5g(rtwdev);
5775 else
5776 _action_by_bt(rtwdev);
5777 }
5778 }
5779
_action_wl_2g_mcc(struct rtw89_dev * rtwdev)5780 static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev)
5781 { struct rtw89_btc *btc = &rtwdev->btc;
5782
5783 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5784
5785 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5786 if (btc->cx.bt.link_info.profile_cnt.now == 0)
5787 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
5788 BTC_ACT_WL_2G_MCC);
5789 else
5790 _set_policy(rtwdev, BTC_CXP_OFFE_DEF,
5791 BTC_ACT_WL_2G_MCC);
5792 } else { /* dedicated-antenna */
5793 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC);
5794 }
5795 }
5796
_action_wl_2g_scc(struct rtw89_dev * rtwdev)5797 static void _action_wl_2g_scc(struct rtw89_dev *rtwdev)
5798 {
5799 struct rtw89_btc *btc = &rtwdev->btc;
5800
5801 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5802
5803 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5804 if (btc->cx.bt.link_info.profile_cnt.now == 0)
5805 _set_policy(rtwdev,
5806 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC);
5807 else
5808 _set_policy(rtwdev,
5809 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC);
5810 } else { /* dedicated-antenna */
5811 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC);
5812 }
5813 }
5814
_action_wl_2g_scc_v1(struct rtw89_dev * rtwdev)5815 static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev)
5816 {
5817 struct rtw89_btc *btc = &rtwdev->btc;
5818 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5819 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5820 struct rtw89_btc_dm *dm = &btc->dm;
5821 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
5822 u16 policy_type = BTC_CXP_OFF_BT;
5823 u32 dur;
5824
5825 if (btc->ant_type == BTC_ANT_DEDICATED) {
5826 policy_type = BTC_CXP_OFF_EQ0;
5827 } else {
5828 /* shared-antenna */
5829 switch (wl_rinfo->mrole_type) {
5830 case BTC_WLMROLE_STA_GC:
5831 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5832 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
5833 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5834 _action_by_bt(rtwdev);
5835 return;
5836 case BTC_WLMROLE_STA_STA:
5837 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5838 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
5839 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5840 _action_by_bt(rtwdev);
5841 return;
5842 case BTC_WLMROLE_STA_GC_NOA:
5843 case BTC_WLMROLE_STA_GO:
5844 case BTC_WLMROLE_STA_GO_NOA:
5845 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5846 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
5847 dur = wl_rinfo->mrole_noa_duration;
5848
5849 if (wl->status.map._4way) {
5850 dm->wl_scc.ebt_null = 0;
5851 policy_type = BTC_CXP_OFFE_WL;
5852 } else if (bt->link_info.status.map.connect == 0) {
5853 dm->wl_scc.ebt_null = 0;
5854 policy_type = BTC_CXP_OFFE_2GISOB;
5855 } else if (bt->link_info.a2dp_desc.exist &&
5856 dur < btc->bt_req_len) {
5857 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5858 policy_type = BTC_CXP_OFFE_2GBWMIXB2;
5859 } else if (bt->link_info.a2dp_desc.exist ||
5860 bt->link_info.pan_desc.exist) {
5861 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5862 policy_type = BTC_CXP_OFFE_2GBWISOB;
5863 } else {
5864 dm->wl_scc.ebt_null = 0;
5865 policy_type = BTC_CXP_OFFE_2GBWISOB;
5866 }
5867 break;
5868 default:
5869 break;
5870 }
5871 }
5872
5873 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5874 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5875 }
5876
_action_wl_2g_scc_v2(struct rtw89_dev * rtwdev)5877 static void _action_wl_2g_scc_v2(struct rtw89_dev *rtwdev)
5878 {
5879 struct rtw89_btc *btc = &rtwdev->btc;
5880 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5881 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5882 struct rtw89_btc_dm *dm = &btc->dm;
5883 struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2;
5884 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
5885 u32 dur, mrole_type, mrole_noa_duration;
5886 u16 policy_type = BTC_CXP_OFF_BT;
5887
5888 if (btc->ver->fwlrole == 2) {
5889 mrole_type = rinfo_v2->mrole_type;
5890 mrole_noa_duration = rinfo_v2->mrole_noa_duration;
5891 } else if (btc->ver->fwlrole == 7) {
5892 mrole_type = rinfo_v7->mrole_type;
5893 mrole_noa_duration = rinfo_v7->mrole_noa_duration;
5894 } else {
5895 return;
5896 }
5897
5898 if (btc->ant_type == BTC_ANT_DEDICATED) {
5899 policy_type = BTC_CXP_OFF_EQ0;
5900 } else {
5901 /* shared-antenna */
5902 switch (mrole_type) {
5903 case BTC_WLMROLE_STA_GC:
5904 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5905 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
5906 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5907 _action_by_bt(rtwdev);
5908 return;
5909 case BTC_WLMROLE_STA_STA:
5910 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5911 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
5912 dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5913 _action_by_bt(rtwdev);
5914 return;
5915 case BTC_WLMROLE_STA_GC_NOA:
5916 case BTC_WLMROLE_STA_GO:
5917 case BTC_WLMROLE_STA_GO_NOA:
5918 dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5919 dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
5920 dur = mrole_noa_duration;
5921
5922 if (wl->status.map._4way) {
5923 dm->wl_scc.ebt_null = 0;
5924 policy_type = BTC_CXP_OFFE_WL;
5925 } else if (bt->link_info.status.map.connect == 0) {
5926 dm->wl_scc.ebt_null = 0;
5927 policy_type = BTC_CXP_OFFE_2GISOB;
5928 } else if (bt->link_info.a2dp_desc.exist &&
5929 dur < btc->bt_req_len) {
5930 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5931 policy_type = BTC_CXP_OFFE_2GBWMIXB2;
5932 } else if (bt->link_info.a2dp_desc.exist ||
5933 bt->link_info.pan_desc.exist) {
5934 dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5935 policy_type = BTC_CXP_OFFE_2GBWISOB;
5936 } else {
5937 dm->wl_scc.ebt_null = 0;
5938 policy_type = BTC_CXP_OFFE_2GBWISOB;
5939 }
5940 break;
5941 default:
5942 break;
5943 }
5944 }
5945
5946 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5947 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5948 }
5949
_action_wl_2g_scc_v8(struct rtw89_dev * rtwdev)5950 static void _action_wl_2g_scc_v8(struct rtw89_dev *rtwdev)
5951 {
5952 struct rtw89_btc *btc = &rtwdev->btc;
5953 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5954 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5955 struct rtw89_btc_dm *dm = &btc->dm;
5956 u16 policy_type = BTC_CXP_OFF_BT;
5957
5958 if (btc->ant_type == BTC_ANT_SHARED) {
5959 if (wl->status.map._4way)
5960 policy_type = BTC_CXP_OFFE_WL;
5961 else if (bt->link_info.status.map.connect == 0)
5962 policy_type = BTC_CXP_OFFE_2GISOB;
5963 else
5964 policy_type = BTC_CXP_OFFE_2GBWISOB;
5965 } else {
5966 policy_type = BTC_CXP_OFF_EQ0;
5967 }
5968
5969 dm->e2g_slot_limit = BTC_E2G_LIMIT_DEF;
5970
5971 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5972 _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5973 }
5974
_action_wl_2g_ap(struct rtw89_dev * rtwdev)5975 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
5976 {
5977 struct rtw89_btc *btc = &rtwdev->btc;
5978
5979 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5980
5981 if (btc->ant_type == BTC_ANT_SHARED) {
5982 if (btc->cx.bt.link_info.profile_cnt.now == 0)
5983 _set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
5984 BTC_ACT_WL_2G_AP);
5985 else
5986 _set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP);
5987 } else {/* dedicated-antenna */
5988 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP);
5989 }
5990 }
5991
_action_wl_2g_go(struct rtw89_dev * rtwdev)5992 static void _action_wl_2g_go(struct rtw89_dev *rtwdev)
5993 {
5994 struct rtw89_btc *btc = &rtwdev->btc;
5995
5996 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5997
5998 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5999 if (btc->cx.bt.link_info.profile_cnt.now == 0)
6000 _set_policy(rtwdev,
6001 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO);
6002 else
6003 _set_policy(rtwdev,
6004 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO);
6005 } else { /* dedicated-antenna */
6006 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO);
6007 }
6008 }
6009
_action_wl_2g_gc(struct rtw89_dev * rtwdev)6010 static void _action_wl_2g_gc(struct rtw89_dev *rtwdev)
6011 {
6012 struct rtw89_btc *btc = &rtwdev->btc;
6013
6014 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6015
6016 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6017 _action_by_bt(rtwdev);
6018 } else {/* dedicated-antenna */
6019 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC);
6020 }
6021 }
6022
_action_wl_2g_nan(struct rtw89_dev * rtwdev)6023 static void _action_wl_2g_nan(struct rtw89_dev *rtwdev)
6024 {
6025 struct rtw89_btc *btc = &rtwdev->btc;
6026
6027 _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6028
6029 if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6030 if (btc->cx.bt.link_info.profile_cnt.now == 0)
6031 _set_policy(rtwdev,
6032 BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN);
6033 else
6034 _set_policy(rtwdev,
6035 BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN);
6036 } else { /* dedicated-antenna */
6037 _set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN);
6038 }
6039 }
6040
_read_scbd(struct rtw89_dev * rtwdev)6041 static u32 _read_scbd(struct rtw89_dev *rtwdev)
6042 {
6043 const struct rtw89_chip_info *chip = rtwdev->chip;
6044 struct rtw89_btc *btc = &rtwdev->btc;
6045 u32 scbd_val = 0;
6046
6047 if (!chip->scbd)
6048 return 0;
6049
6050 scbd_val = rtw89_mac_get_sb(rtwdev);
6051 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n",
6052 scbd_val);
6053
6054 btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++;
6055 return scbd_val;
6056 }
6057
_write_scbd(struct rtw89_dev * rtwdev,u32 val,bool state)6058 static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state)
6059 {
6060 const struct rtw89_chip_info *chip = rtwdev->chip;
6061 struct rtw89_btc *btc = &rtwdev->btc;
6062 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6063 u32 scbd_val = 0;
6064 u8 force_exec = false;
6065
6066 if (!chip->scbd)
6067 return;
6068
6069 scbd_val = state ? wl->scbd | val : wl->scbd & ~val;
6070
6071 if (val & BTC_WSCB_ACTIVE || val & BTC_WSCB_ON)
6072 force_exec = true;
6073
6074 if (scbd_val != wl->scbd || force_exec) {
6075 wl->scbd = scbd_val;
6076 wl->scbd_change = true;
6077 }
6078 }
6079
6080 static u8
_update_rssi_state(struct rtw89_dev * rtwdev,u8 pre_state,u8 rssi,u8 thresh)6081 _update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh)
6082 {
6083 const struct rtw89_chip_info *chip = rtwdev->chip;
6084 u8 next_state, tol = chip->rssi_tol;
6085
6086 if (pre_state == BTC_RSSI_ST_LOW ||
6087 pre_state == BTC_RSSI_ST_STAY_LOW) {
6088 if (rssi >= (thresh + tol))
6089 next_state = BTC_RSSI_ST_HIGH;
6090 else
6091 next_state = BTC_RSSI_ST_STAY_LOW;
6092 } else {
6093 if (rssi < thresh)
6094 next_state = BTC_RSSI_ST_LOW;
6095 else
6096 next_state = BTC_RSSI_ST_STAY_HIGH;
6097 }
6098
6099 return next_state;
6100 }
6101
6102 static
_update_dbcc_band(struct rtw89_dev * rtwdev,enum rtw89_phy_idx phy_idx)6103 void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
6104 {
6105 struct rtw89_btc *btc = &rtwdev->btc;
6106
6107 btc->cx.wl.dbcc_info.real_band[phy_idx] =
6108 btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ?
6109 btc->cx.wl.dbcc_info.scan_band[phy_idx] :
6110 btc->cx.wl.dbcc_info.op_band[phy_idx];
6111 }
6112
_update_wl_info(struct rtw89_dev * rtwdev)6113 static void _update_wl_info(struct rtw89_dev *rtwdev)
6114 {
6115 struct rtw89_btc *btc = &rtwdev->btc;
6116 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6117 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6118 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
6119 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6120 u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
6121 u8 cnt_2g = 0, cnt_5g = 0, phy;
6122 u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0};
6123 bool b2g = false, b5g = false, client_joined = false;
6124
6125 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6126
6127 for (i = 0; i < RTW89_PORT_NUM; i++) {
6128 /* check if role active? */
6129 if (!wl_linfo[i].active)
6130 continue;
6131
6132 cnt_active++;
6133 wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role;
6134 wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid;
6135 wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy;
6136 wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band;
6137 wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
6138 wl_rinfo->active_role[cnt_active - 1].connected = 0;
6139
6140 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
6141
6142 phy = wl_linfo[i].phy;
6143
6144 /* check dbcc role */
6145 if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) {
6146 wl_dinfo->role[phy] = wl_linfo[i].role;
6147 wl_dinfo->op_band[phy] = wl_linfo[i].band;
6148 _update_dbcc_band(rtwdev, phy);
6149 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6150 }
6151
6152 if (wl_linfo[i].connected == MLME_NO_LINK) {
6153 continue;
6154 } else if (wl_linfo[i].connected == MLME_LINKING) {
6155 cnt_connecting++;
6156 } else {
6157 cnt_connect++;
6158 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6159 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6160 wl_linfo[i].client_cnt > 1)
6161 client_joined = true;
6162 }
6163
6164 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
6165 wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch;
6166 wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw;
6167 wl_rinfo->active_role[cnt_active - 1].connected = 1;
6168
6169 /* only care 2 roles + BT coex */
6170 if (wl_linfo[i].band != RTW89_BAND_2G) {
6171 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
6172 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
6173 cnt_5g++;
6174 b5g = true;
6175 } else {
6176 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
6177 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
6178 cnt_2g++;
6179 b2g = true;
6180 }
6181 }
6182
6183 wl_rinfo->connect_cnt = cnt_connect;
6184
6185 /* Be careful to change the following sequence!! */
6186 if (cnt_connect == 0) {
6187 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6188 wl_rinfo->role_map.role.none = 1;
6189 } else if (!b2g && b5g) {
6190 wl_rinfo->link_mode = BTC_WLINK_5G;
6191 } else if (wl_rinfo->role_map.role.nan) {
6192 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
6193 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
6194 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6195 } else if (b2g && b5g && cnt_connect == 2) {
6196 if (rtwdev->dbcc_en) {
6197 switch (wl_dinfo->role[RTW89_PHY_0]) {
6198 case RTW89_WIFI_ROLE_STATION:
6199 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6200 break;
6201 case RTW89_WIFI_ROLE_P2P_GO:
6202 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6203 break;
6204 case RTW89_WIFI_ROLE_P2P_CLIENT:
6205 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6206 break;
6207 case RTW89_WIFI_ROLE_AP:
6208 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6209 break;
6210 default:
6211 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6212 break;
6213 }
6214 } else {
6215 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
6216 }
6217 } else if (!b5g && cnt_connect == 2) {
6218 if (wl_rinfo->role_map.role.station &&
6219 (wl_rinfo->role_map.role.p2p_go ||
6220 wl_rinfo->role_map.role.p2p_gc ||
6221 wl_rinfo->role_map.role.ap)) {
6222 if (wl_2g_ch[0] == wl_2g_ch[1])
6223 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
6224 else
6225 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6226 } else {
6227 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6228 }
6229 } else if (!b5g && cnt_connect == 1) {
6230 if (wl_rinfo->role_map.role.station)
6231 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6232 else if (wl_rinfo->role_map.role.ap)
6233 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6234 else if (wl_rinfo->role_map.role.p2p_go)
6235 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6236 else if (wl_rinfo->role_map.role.p2p_gc)
6237 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6238 else
6239 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6240 }
6241
6242 /* if no client_joined, don't care P2P-GO/AP role */
6243 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6244 if (!client_joined) {
6245 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6246 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6247 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6248 wl_rinfo->connect_cnt = 1;
6249 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6250 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6251 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6252 wl_rinfo->connect_cnt = 0;
6253 }
6254 }
6255 }
6256
6257 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6258 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6259 cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6260
6261 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6262 }
6263
_update_wl_info_v1(struct rtw89_dev * rtwdev)6264 static void _update_wl_info_v1(struct rtw89_dev *rtwdev)
6265 {
6266 struct rtw89_btc *btc = &rtwdev->btc;
6267 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6268 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6269 struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
6270 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6271 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
6272 u8 cnt_2g = 0, cnt_5g = 0, phy;
6273 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
6274 bool b2g = false, b5g = false, client_joined = false;
6275 u8 i;
6276
6277 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6278
6279 for (i = 0; i < RTW89_PORT_NUM; i++) {
6280 if (!wl_linfo[i].active)
6281 continue;
6282
6283 cnt_active++;
6284 wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role;
6285 wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid;
6286 wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy;
6287 wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band;
6288 wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
6289 wl_rinfo->active_role_v1[cnt_active - 1].connected = 0;
6290
6291 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
6292
6293 phy = wl_linfo[i].phy;
6294
6295 if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) {
6296 wl_dinfo->role[phy] = wl_linfo[i].role;
6297 wl_dinfo->op_band[phy] = wl_linfo[i].band;
6298 _update_dbcc_band(rtwdev, phy);
6299 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6300 }
6301
6302 if (wl_linfo[i].connected == MLME_NO_LINK) {
6303 continue;
6304 } else if (wl_linfo[i].connected == MLME_LINKING) {
6305 cnt_connecting++;
6306 } else {
6307 cnt_connect++;
6308 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6309 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6310 wl_linfo[i].client_cnt > 1)
6311 client_joined = true;
6312 }
6313
6314 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
6315 wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch;
6316 wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw;
6317 wl_rinfo->active_role_v1[cnt_active - 1].connected = 1;
6318
6319 /* only care 2 roles + BT coex */
6320 if (wl_linfo[i].band != RTW89_BAND_2G) {
6321 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
6322 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
6323 cnt_5g++;
6324 b5g = true;
6325 } else {
6326 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
6327 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
6328 cnt_2g++;
6329 b2g = true;
6330 }
6331 }
6332
6333 wl_rinfo->connect_cnt = cnt_connect;
6334
6335 /* Be careful to change the following sequence!! */
6336 if (cnt_connect == 0) {
6337 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6338 wl_rinfo->role_map.role.none = 1;
6339 } else if (!b2g && b5g) {
6340 wl_rinfo->link_mode = BTC_WLINK_5G;
6341 } else if (wl_rinfo->role_map.role.nan) {
6342 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
6343 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
6344 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6345 } else if (b2g && b5g && cnt_connect == 2) {
6346 if (rtwdev->dbcc_en) {
6347 switch (wl_dinfo->role[RTW89_PHY_0]) {
6348 case RTW89_WIFI_ROLE_STATION:
6349 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6350 break;
6351 case RTW89_WIFI_ROLE_P2P_GO:
6352 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6353 break;
6354 case RTW89_WIFI_ROLE_P2P_CLIENT:
6355 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6356 break;
6357 case RTW89_WIFI_ROLE_AP:
6358 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6359 break;
6360 default:
6361 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6362 break;
6363 }
6364 } else {
6365 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
6366 }
6367 } else if (!b5g && cnt_connect == 2) {
6368 if (wl_rinfo->role_map.role.station &&
6369 (wl_rinfo->role_map.role.p2p_go ||
6370 wl_rinfo->role_map.role.p2p_gc ||
6371 wl_rinfo->role_map.role.ap)) {
6372 if (wl_2g_ch[0] == wl_2g_ch[1])
6373 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
6374 else
6375 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6376 } else {
6377 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6378 }
6379 } else if (!b5g && cnt_connect == 1) {
6380 if (wl_rinfo->role_map.role.station)
6381 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6382 else if (wl_rinfo->role_map.role.ap)
6383 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6384 else if (wl_rinfo->role_map.role.p2p_go)
6385 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6386 else if (wl_rinfo->role_map.role.p2p_gc)
6387 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6388 else
6389 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6390 }
6391
6392 /* if no client_joined, don't care P2P-GO/AP role */
6393 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6394 if (!client_joined) {
6395 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6396 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6397 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6398 wl_rinfo->connect_cnt = 1;
6399 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6400 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6401 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6402 wl_rinfo->connect_cnt = 0;
6403 }
6404 }
6405 }
6406
6407 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6408 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6409 cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6410
6411 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6412 }
6413
_update_wl_info_v2(struct rtw89_dev * rtwdev)6414 static void _update_wl_info_v2(struct rtw89_dev *rtwdev)
6415 {
6416 struct rtw89_btc *btc = &rtwdev->btc;
6417 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6418 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6419 struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2;
6420 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6421 u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
6422 u8 cnt_2g = 0, cnt_5g = 0, phy;
6423 u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
6424 bool b2g = false, b5g = false, client_joined = false;
6425 u8 i;
6426
6427 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6428
6429 for (i = 0; i < RTW89_PORT_NUM; i++) {
6430 if (!wl_linfo[i].active)
6431 continue;
6432
6433 cnt_active++;
6434 wl_rinfo->active_role_v2[cnt_active - 1].role = wl_linfo[i].role;
6435 wl_rinfo->active_role_v2[cnt_active - 1].pid = wl_linfo[i].pid;
6436 wl_rinfo->active_role_v2[cnt_active - 1].phy = wl_linfo[i].phy;
6437 wl_rinfo->active_role_v2[cnt_active - 1].band = wl_linfo[i].band;
6438 wl_rinfo->active_role_v2[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
6439 wl_rinfo->active_role_v2[cnt_active - 1].connected = 0;
6440
6441 wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
6442
6443 phy = wl_linfo[i].phy;
6444
6445 if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) {
6446 wl_dinfo->role[phy] = wl_linfo[i].role;
6447 wl_dinfo->op_band[phy] = wl_linfo[i].band;
6448 _update_dbcc_band(rtwdev, phy);
6449 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6450 }
6451
6452 if (wl_linfo[i].connected == MLME_NO_LINK) {
6453 continue;
6454 } else if (wl_linfo[i].connected == MLME_LINKING) {
6455 cnt_connecting++;
6456 } else {
6457 cnt_connect++;
6458 if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6459 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6460 wl_linfo[i].client_cnt > 1)
6461 client_joined = true;
6462 }
6463
6464 wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
6465 wl_rinfo->active_role_v2[cnt_active - 1].ch = wl_linfo[i].ch;
6466 wl_rinfo->active_role_v2[cnt_active - 1].bw = wl_linfo[i].bw;
6467 wl_rinfo->active_role_v2[cnt_active - 1].connected = 1;
6468
6469 /* only care 2 roles + BT coex */
6470 if (wl_linfo[i].band != RTW89_BAND_2G) {
6471 if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
6472 wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
6473 cnt_5g++;
6474 b5g = true;
6475 } else {
6476 if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
6477 wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
6478 cnt_2g++;
6479 b2g = true;
6480 }
6481 }
6482
6483 wl_rinfo->connect_cnt = cnt_connect;
6484
6485 /* Be careful to change the following sequence!! */
6486 if (cnt_connect == 0) {
6487 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6488 wl_rinfo->role_map.role.none = 1;
6489 } else if (!b2g && b5g) {
6490 wl_rinfo->link_mode = BTC_WLINK_5G;
6491 } else if (wl_rinfo->role_map.role.nan) {
6492 wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
6493 } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
6494 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6495 } else if (b2g && b5g && cnt_connect == 2) {
6496 if (rtwdev->dbcc_en) {
6497 switch (wl_dinfo->role[RTW89_PHY_0]) {
6498 case RTW89_WIFI_ROLE_STATION:
6499 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6500 break;
6501 case RTW89_WIFI_ROLE_P2P_GO:
6502 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6503 break;
6504 case RTW89_WIFI_ROLE_P2P_CLIENT:
6505 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6506 break;
6507 case RTW89_WIFI_ROLE_AP:
6508 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6509 break;
6510 default:
6511 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6512 break;
6513 }
6514 } else {
6515 wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
6516 }
6517 } else if (!b5g && cnt_connect == 2) {
6518 if (wl_rinfo->role_map.role.station &&
6519 (wl_rinfo->role_map.role.p2p_go ||
6520 wl_rinfo->role_map.role.p2p_gc ||
6521 wl_rinfo->role_map.role.ap)) {
6522 if (wl_2g_ch[0] == wl_2g_ch[1])
6523 wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
6524 else
6525 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6526 } else {
6527 wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6528 }
6529 } else if (!b5g && cnt_connect == 1) {
6530 if (wl_rinfo->role_map.role.station)
6531 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6532 else if (wl_rinfo->role_map.role.ap)
6533 wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6534 else if (wl_rinfo->role_map.role.p2p_go)
6535 wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6536 else if (wl_rinfo->role_map.role.p2p_gc)
6537 wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6538 else
6539 wl_rinfo->link_mode = BTC_WLINK_OTHER;
6540 }
6541
6542 /* if no client_joined, don't care P2P-GO/AP role */
6543 if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6544 if (!client_joined) {
6545 if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6546 wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6547 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6548 wl_rinfo->connect_cnt = 1;
6549 } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6550 wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6551 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6552 wl_rinfo->connect_cnt = 0;
6553 }
6554 }
6555 }
6556
6557 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6558 "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6559 cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6560
6561 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6562 }
6563
6564 #define BTC_CHK_HANG_MAX 3
6565 #define BTC_SCB_INV_VALUE GENMASK(31, 0)
6566
_get_role_link_mode(u8 role)6567 static u8 _get_role_link_mode(u8 role)
6568 {
6569 switch (role) {
6570 case RTW89_WIFI_ROLE_STATION:
6571 return BTC_WLINK_2G_STA;
6572 case RTW89_WIFI_ROLE_P2P_GO:
6573 return BTC_WLINK_2G_GO;
6574 case RTW89_WIFI_ROLE_P2P_CLIENT:
6575 return BTC_WLINK_2G_GC;
6576 case RTW89_WIFI_ROLE_AP:
6577 return BTC_WLINK_2G_AP;
6578 default:
6579 return BTC_WLINK_OTHER;
6580 }
6581 }
6582
_chk_role_ch_group(const struct rtw89_btc_chdef * r1,const struct rtw89_btc_chdef * r2)6583 static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1,
6584 const struct rtw89_btc_chdef *r2)
6585 {
6586 if (r1->chan != r2->chan) { /* primary ch is different */
6587 return false;
6588 } else if (r1->bw == RTW89_CHANNEL_WIDTH_40 &&
6589 r2->bw == RTW89_CHANNEL_WIDTH_40) {
6590 if (r1->offset != r2->offset)
6591 return false;
6592 }
6593 return true;
6594 }
6595
_chk_dbcc(struct rtw89_dev * rtwdev,struct rtw89_btc_chdef * ch,u8 * phy,u8 * role,u8 link_cnt)6596 static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch,
6597 u8 *phy, u8 *role, u8 link_cnt)
6598 {
6599 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6600 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
6601 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8;
6602 bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false;
6603 u8 j, k, dbcc_2g_cid, dbcc_2g_cid2, dbcc_2g_phy, pta_req_band;
6604
6605 /* find out the 2G-PHY by connect-id ->ch */
6606 for (j = 0; j < link_cnt; j++) {
6607 if (ch[j].center_ch <= 14) {
6608 is_2g_ch_exist = true;
6609 break;
6610 }
6611 }
6612
6613 /* If no any 2G-port exist, it's impossible because 5G-exclude */
6614 if (!is_2g_ch_exist)
6615 return BTC_WLINK_5G;
6616
6617 dbcc_2g_cid = j;
6618 dbcc_2g_phy = phy[dbcc_2g_cid];
6619
6620 if (dbcc_2g_phy == RTW89_PHY_1)
6621 pta_req_band = RTW89_PHY_1;
6622 else
6623 pta_req_band = RTW89_PHY_0;
6624
6625 if (rtwdev->btc.ver->fwlrole == 7) {
6626 rinfo_v7->dbcc_2g_phy = dbcc_2g_phy;
6627 } else if (rtwdev->btc.ver->fwlrole == 8) {
6628 rinfo_v8->dbcc_2g_phy = dbcc_2g_phy;
6629 rinfo_v8->pta_req_band = pta_req_band;
6630 }
6631
6632 /* connect_cnt <= 2 */
6633 if (link_cnt < BTC_TDMA_WLROLE_MAX)
6634 return (_get_role_link_mode((role[dbcc_2g_cid])));
6635
6636 /* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */
6637 for (k = 0; k < link_cnt; k++) {
6638 if (k == dbcc_2g_cid)
6639 continue;
6640
6641 if (phy[k] == dbcc_2g_phy) {
6642 is_multi_role_in_2g_phy = true;
6643 dbcc_2g_cid2 = k;
6644 break;
6645 }
6646 }
6647
6648 /* Single-role in 2G-PHY */
6649 if (!is_multi_role_in_2g_phy)
6650 return (_get_role_link_mode(role[dbcc_2g_cid]));
6651
6652 /* 2-role in 2G-PHY */
6653 if (ch[dbcc_2g_cid2].center_ch > 14)
6654 return BTC_WLINK_25G_MCC;
6655 else if (_chk_role_ch_group(&ch[dbcc_2g_cid], &ch[dbcc_2g_cid2]))
6656 return BTC_WLINK_2G_SCC;
6657 else
6658 return BTC_WLINK_2G_MCC;
6659 }
6660
_update_role_link_mode(struct rtw89_dev * rtwdev,bool client_joined,u32 noa)6661 static void _update_role_link_mode(struct rtw89_dev *rtwdev,
6662 bool client_joined, u32 noa)
6663 {
6664 struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &rtwdev->btc.cx.wl.role_info_v8;
6665 struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &rtwdev->btc.cx.wl.role_info_v7;
6666 u8 role_ver = rtwdev->btc.ver->fwlrole;
6667 u32 type = BTC_WLMROLE_NONE, dur = 0;
6668 u8 link_mode, connect_cnt;
6669 u32 wl_role;
6670
6671 if (role_ver == 7) {
6672 wl_role = rinfo_v7->role_map;
6673 link_mode = rinfo_v7->link_mode;
6674 connect_cnt = rinfo_v7->connect_cnt;
6675 } else if (role_ver == 8) {
6676 wl_role = rinfo_v8->role_map;
6677 link_mode = rinfo_v8->link_mode;
6678 connect_cnt = rinfo_v8->connect_cnt;
6679 } else {
6680 return;
6681 }
6682
6683 /* if no client_joined, don't care P2P-GO/AP role */
6684 if (((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
6685 (wl_role & BIT(RTW89_WIFI_ROLE_AP))) && !client_joined) {
6686 if (link_mode == BTC_WLINK_2G_SCC) {
6687 if (role_ver == 7) {
6688 rinfo_v7->link_mode = BTC_WLINK_2G_STA;
6689 rinfo_v7->connect_cnt--;
6690 } else if (role_ver == 8) {
6691 rinfo_v8->link_mode = BTC_WLINK_2G_STA;
6692 rinfo_v8->connect_cnt--;
6693 }
6694 } else if (link_mode == BTC_WLINK_2G_GO ||
6695 link_mode == BTC_WLINK_2G_AP) {
6696 if (role_ver == 7) {
6697 rinfo_v7->link_mode = BTC_WLINK_NOLINK;
6698 rinfo_v7->connect_cnt--;
6699 } else if (role_ver == 8) {
6700 rinfo_v8->link_mode = BTC_WLINK_NOLINK;
6701 rinfo_v8->connect_cnt--;
6702 }
6703 }
6704 }
6705
6706 /* Identify 2-Role type */
6707 if (connect_cnt >= 2 &&
6708 (link_mode == BTC_WLINK_2G_SCC ||
6709 link_mode == BTC_WLINK_2G_MCC ||
6710 link_mode == BTC_WLINK_25G_MCC ||
6711 link_mode == BTC_WLINK_5G)) {
6712 if ((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
6713 (wl_role & BIT(RTW89_WIFI_ROLE_AP)))
6714 type = noa ? BTC_WLMROLE_STA_GO_NOA : BTC_WLMROLE_STA_GO;
6715 else if (wl_role & BIT(RTW89_WIFI_ROLE_P2P_CLIENT))
6716 type = noa ? BTC_WLMROLE_STA_GC_NOA : BTC_WLMROLE_STA_GC;
6717 else
6718 type = BTC_WLMROLE_STA_STA;
6719
6720 dur = noa;
6721 }
6722
6723 if (role_ver == 7) {
6724 rinfo_v7->mrole_type = type;
6725 rinfo_v7->mrole_noa_duration = dur;
6726 } else if (role_ver == 8) {
6727 rinfo_v8->mrole_type = type;
6728 rinfo_v8->mrole_noa_duration = dur;
6729 }
6730 }
6731
_update_wl_info_v7(struct rtw89_dev * rtwdev,u8 rid)6732 static void _update_wl_info_v7(struct rtw89_dev *rtwdev, u8 rid)
6733 {
6734 struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER];
6735 struct rtw89_btc *btc = &rtwdev->btc;
6736 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6737 struct rtw89_btc_wl_role_info_v7 *wl_rinfo = &wl->role_info_v7;
6738 struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6739 struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6740 struct rtw89_btc_wl_active_role_v7 *act_role = NULL;
6741 u8 i, mode, cnt = 0, cnt_2g = 0, cnt_5g = 0, phy_now = RTW89_PHY_NUM, phy_dbcc;
6742 bool b2g = false, b5g = false, client_joined = false, client_inc_2g = false;
6743 u8 client_cnt_last[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6744 u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6745 u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6746 u8 mac = RTW89_MAC_0, dbcc_2g_phy = RTW89_PHY_0;
6747 u32 noa_duration = 0;
6748
6749 memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6750
6751 for (i = 0; i < RTW89_PORT_NUM; i++) {
6752 if (!wl_linfo[i].active || wl_linfo[i].phy >= RTW89_PHY_NUM)
6753 continue;
6754
6755 act_role = &wl_rinfo->active_role[i];
6756 act_role->role = wl_linfo[i].role;
6757
6758 /* check if role connect? */
6759 if (wl_linfo[i].connected == MLME_NO_LINK) {
6760 act_role->connected = 0;
6761 continue;
6762 } else if (wl_linfo[i].connected == MLME_LINKING) {
6763 continue;
6764 }
6765
6766 cnt++;
6767 act_role->connected = 1;
6768 act_role->pid = wl_linfo[i].pid;
6769 act_role->phy = wl_linfo[i].phy;
6770 act_role->band = wl_linfo[i].band;
6771 act_role->ch = wl_linfo[i].ch;
6772 act_role->bw = wl_linfo[i].bw;
6773 act_role->noa = wl_linfo[i].noa;
6774 act_role->noa_dur = wl_linfo[i].noa_duration;
6775 cid_ch[cnt - 1] = wl_linfo[i].chdef;
6776 cid_phy[cnt - 1] = wl_linfo[i].phy;
6777 cid_role[cnt - 1] = wl_linfo[i].role;
6778 wl_rinfo->role_map |= BIT(wl_linfo[i].role);
6779
6780 if (rid == i)
6781 phy_now = act_role->phy;
6782
6783 if (wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6784 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) {
6785 if (wl_linfo[i].client_cnt > 1)
6786 client_joined = true;
6787 if (client_cnt_last[i] < wl_linfo[i].client_cnt &&
6788 wl_linfo[i].chdef.band == RTW89_BAND_2G)
6789 client_inc_2g = true;
6790 act_role->client_cnt = wl_linfo[i].client_cnt;
6791 } else {
6792 act_role->client_cnt = 0;
6793 }
6794
6795 if (act_role->noa && act_role->noa_dur > 0)
6796 noa_duration = act_role->noa_dur;
6797
6798 if (rtwdev->dbcc_en) {
6799 phy_dbcc = wl_linfo[i].phy;
6800 wl_dinfo->role[phy_dbcc] |= BIT(wl_linfo[i].role);
6801 wl_dinfo->op_band[phy_dbcc] = wl_linfo[i].chdef.band;
6802 }
6803
6804 if (wl_linfo[i].chdef.band != RTW89_BAND_2G) {
6805 cnt_5g++;
6806 b5g = true;
6807 } else {
6808 if (((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6809 wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6810 client_joined) ||
6811 wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_CLIENT)
6812 wl_rinfo->p2p_2g = 1;
6813
6814 if ((wl_linfo[i].mode & BIT(BTC_WL_MODE_11B)) ||
6815 (wl_linfo[i].mode & BIT(BTC_WL_MODE_11G)))
6816 wl->bg_mode = 1;
6817 else if (wl_linfo[i].mode & BIT(BTC_WL_MODE_HE))
6818 wl->he_mode = true;
6819
6820 cnt_2g++;
6821 b2g = true;
6822 }
6823
6824 if (act_role->band == RTW89_BAND_5G && act_role->ch >= 100)
6825 wl->is_5g_hi_channel = 1;
6826 else
6827 wl->is_5g_hi_channel = 0;
6828 }
6829
6830 wl_rinfo->connect_cnt = cnt;
6831 wl->client_cnt_inc_2g = client_inc_2g;
6832
6833 if (cnt == 0) {
6834 mode = BTC_WLINK_NOLINK;
6835 wl_rinfo->role_map = BIT(RTW89_WIFI_ROLE_NONE);
6836 } else if (!b2g && b5g) {
6837 mode = BTC_WLINK_5G;
6838 } else if (wl_rinfo->role_map & BIT(RTW89_WIFI_ROLE_NAN)) {
6839 mode = BTC_WLINK_2G_NAN;
6840 } else if (cnt > BTC_TDMA_WLROLE_MAX) {
6841 mode = BTC_WLINK_OTHER;
6842 } else if (rtwdev->dbcc_en) {
6843 mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt);
6844
6845 /* correct 2G-located PHY band for gnt ctrl */
6846 if (dbcc_2g_phy < RTW89_PHY_NUM)
6847 wl_dinfo->op_band[dbcc_2g_phy] = RTW89_BAND_2G;
6848 } else if (b2g && b5g && cnt == 2) {
6849 mode = BTC_WLINK_25G_MCC;
6850 } else if (!b5g && cnt == 2) { /* cnt_connect = 2 */
6851 if (_chk_role_ch_group(&cid_ch[0], &cid_ch[cnt - 1]))
6852 mode = BTC_WLINK_2G_SCC;
6853 else
6854 mode = BTC_WLINK_2G_MCC;
6855 } else if (!b5g && cnt == 1) { /* cnt_connect = 1 */
6856 mode = _get_role_link_mode(cid_role[0]);
6857 } else {
6858 mode = BTC_WLINK_NOLINK;
6859 }
6860
6861 wl_rinfo->link_mode = mode;
6862 _update_role_link_mode(rtwdev, client_joined, noa_duration);
6863
6864 /* todo DBCC related event */
6865 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] wl_info phy_now=%d\n", phy_now);
6866 rtw89_debug(rtwdev, RTW89_DBG_BTC,
6867 "[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g);
6868
6869 if (wl_rinfo->dbcc_en != rtwdev->dbcc_en) {
6870 wl_rinfo->dbcc_chg = 1;
6871 wl_rinfo->dbcc_en = rtwdev->dbcc_en;
6872 btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++;
6873 }
6874
6875 if (rtwdev->dbcc_en) {
6876 wl_rinfo->dbcc_2g_phy = dbcc_2g_phy;
6877
6878 if (dbcc_2g_phy == RTW89_PHY_1)
6879 mac = RTW89_MAC_1;
6880
6881 _update_dbcc_band(rtwdev, RTW89_PHY_0);
6882 _update_dbcc_band(rtwdev, RTW89_PHY_1);
6883 }
6884 _wl_req_mac(rtwdev, mac);
6885 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6886 }
6887
_update_wl_link_mode(struct rtw89_dev * rtwdev,u8 hw_band,u8 type)6888 static u8 _update_wl_link_mode(struct rtw89_dev *rtwdev, u8 hw_band, u8 type)
6889 {
6890 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6891 struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info;
6892 u8 mode = BTC_WLINK_NOLINK;
6893
6894 switch (type) {
6895 case RTW89_MR_WTYPE_NONE: /* no-link */
6896 mode = BTC_WLINK_NOLINK;
6897 break;
6898 case RTW89_MR_WTYPE_NONMLD: /* Non_MLO 1-role 2+0/0+2 */
6899 case RTW89_MR_WTYPE_MLD1L1R: /* MLO only-1 link 2+0/0+2 */
6900 if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) {
6901 mode = BTC_WLINK_5G;
6902 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) {
6903 mode = BTC_WLINK_2G_GO;
6904 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT) {
6905 if (wl->role_info_v8.p2p_2g)
6906 mode = BTC_WLINK_2G_GC;
6907 else
6908 mode = BTC_WLINK_2G_STA;
6909 }
6910 break;
6911 case RTW89_MR_WTYPE_NONMLD_NONMLD: /* Non_MLO 2-role 2+0/0+2 */
6912 case RTW89_MR_WTYPE_MLD1L1R_NONMLD: /* MLO only-1 link + P2P 2+0/0+2 */
6913 if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) {
6914 mode = BTC_WLINK_5G;
6915 } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_5GHZ ||
6916 mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_6GHZ) {
6917 mode = BTC_WLINK_25G_MCC;
6918 } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ) {
6919 mode = BTC_WLINK_2G_MCC;
6920 } else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_2GHZ) {
6921 mode = BTC_WLINK_2G_SCC;
6922 }
6923 break;
6924 case RTW89_MR_WTYPE_MLD2L1R: /* MLO_MLSR 2+0/0+2 */
6925 if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G)
6926 mode = BTC_WLINK_5G;
6927 else if (wl->role_info_v8.p2p_2g)
6928 mode = BTC_WLINK_2G_GC;
6929 else
6930 mode = BTC_WLINK_2G_STA;
6931 break;
6932 case RTW89_MR_WTYPE_MLD2L1R_NONMLD: /* MLO_MLSR + P2P 2+0/0+2 */
6933 case RTW89_MR_WTYPE_MLD2L2R_NONMLD: /* MLO_MLMR + P2P 1+1/2+2 */
6934 /* driver may doze 1-link to
6935 * 2G+5G -> TDMA slot switch by E2G/E5G
6936 * 5G only -> TDMA slot switch by E5G
6937 */
6938 mode = BTC_WLINK_25G_MCC;
6939 break;
6940 case RTW89_MR_WTYPE_MLD2L2R: /* MLO_MLMR 1+1/2+2 */
6941 if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) {
6942 mode = BTC_WLINK_5G;
6943 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) {
6944 mode = BTC_WLINK_2G_GO;
6945 } else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT) {
6946 if (wl->role_info_v8.p2p_2g)
6947 mode = BTC_WLINK_2G_GC;
6948 else
6949 mode = BTC_WLINK_2G_STA;
6950 }
6951 break;
6952 }
6953 return mode;
6954 }
6955
_update_wl_mlo_info(struct rtw89_dev * rtwdev)6956 static void _update_wl_mlo_info(struct rtw89_dev *rtwdev)
6957 {
6958 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6959 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
6960 struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info;
6961 struct rtw89_mr_chanctx_info qinfo;
6962 u8 track_band = RTW89_PHY_0;
6963 u8 rf_band = RTW89_BAND_2G;
6964 u8 i, type;
6965
6966 /* parse MLO info form PHL API for each HW-band */
6967 for (i = RTW89_MAC_0; i <= RTW89_MAC_1; i++) {
6968 memset(&qinfo, 0, sizeof(qinfo));
6969
6970 rtw89_query_mr_chanctx_info(rtwdev, i, &qinfo);
6971 mlo_info->wmode[i] = qinfo.wmode;
6972 mlo_info->ch_type[i] = qinfo.ctxtype;
6973 mlo_info->wtype = qinfo.wtype;
6974
6975 if (mlo_info->ch_type[i] == RTW89_MR_CTX1_5GHZ ||
6976 mlo_info->ch_type[i] == RTW89_MR_CTX2_5GHZ ||
6977 mlo_info->ch_type[i] == RTW89_MR_CTX2_5GHZ_6GHZ)
6978 mlo_info->hwb_rf_band[i] = RTW89_BAND_5G;
6979 else if (mlo_info->ch_type[i] == RTW89_MR_CTX1_6GHZ ||
6980 mlo_info->ch_type[i] == RTW89_MR_CTX2_6GHZ)
6981 mlo_info->hwb_rf_band[i] = RTW89_BAND_6G;
6982 else /* check if "2G-included" or unknown in each HW-band */
6983 mlo_info->hwb_rf_band[i] = RTW89_BAND_2G;
6984 }
6985
6986 mlo_info->link_status = rtwdev->mlo_dbcc_mode;
6987 type = mlo_info->wtype;
6988
6989 if (mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R ||
6990 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R ||
6991 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R ||
6992 mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R_NONMLD ||
6993 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD ||
6994 mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R_NONMLD)
6995 mlo_info->mlo_en = 1;
6996 else
6997 mlo_info->mlo_en = 0;
6998
6999 if (mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_NONE &&
7000 mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_UNKNOWN &&
7001 mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_NONE &&
7002 mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_UNKNOWN)
7003 mlo_info->dual_hw_band_en = 1; /* two HW-hand link exist */
7004 else
7005 mlo_info->dual_hw_band_en = 0;
7006
7007 if (mlo_info->link_status == MLO_2_PLUS_0_2RF ||
7008 mlo_info->link_status == MLO_0_PLUS_2_2RF ||
7009 mlo_info->link_status == MLO_2_PLUS_2_2RF)
7010 mlo_info->mlo_adie = 2;
7011 else
7012 mlo_info->mlo_adie = 1;
7013
7014 switch (mlo_info->link_status) {
7015 default:
7016 case MLO_2_PLUS_0_1RF: /* 2+0 */
7017 case MLO_2_PLUS_0_2RF:
7018 mlo_info->rf_combination = BTC_MLO_RF_2_PLUS_0;
7019 track_band = RTW89_MAC_0;
7020 rf_band = mlo_info->hwb_rf_band[RTW89_MAC_0];
7021 mlo_info->path_rf_band[BTC_RF_S0] = rf_band;
7022 mlo_info->path_rf_band[BTC_RF_S1] = rf_band;
7023
7024 wl_rinfo->pta_req_band = RTW89_MAC_0;
7025 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0;
7026 wl_rinfo->dbcc_en = 0;
7027 break;
7028 case MLO_0_PLUS_2_1RF: /* 0+2 */
7029 case MLO_0_PLUS_2_2RF:
7030 mlo_info->rf_combination = BTC_MLO_RF_0_PLUS_2;
7031 track_band = RTW89_MAC_1;
7032 rf_band = mlo_info->hwb_rf_band[RTW89_MAC_1];
7033 mlo_info->path_rf_band[BTC_RF_S0] = rf_band;
7034 mlo_info->path_rf_band[BTC_RF_S1] = rf_band;
7035
7036 wl_rinfo->pta_req_band = RTW89_MAC_1;
7037 wl_rinfo->dbcc_2g_phy = RTW89_PHY_1;
7038 wl_rinfo->dbcc_en = 0;
7039 break;
7040 case MLO_1_PLUS_1_1RF: /* 1+1 */
7041 case MLO_1_PLUS_1_2RF: /* 1+1 */
7042 case MLO_2_PLUS_2_2RF: /* 2+2 */
7043 case DBCC_LEGACY: /* DBCC 1+1 */
7044 if (mlo_info->link_status == MLO_2_PLUS_2_2RF)
7045 mlo_info->rf_combination = BTC_MLO_RF_2_PLUS_2;
7046 else
7047 mlo_info->rf_combination = BTC_MLO_RF_1_PLUS_1;
7048
7049 if (mlo_info->hwb_rf_band[RTW89_MAC_0] == RTW89_BAND_2G)
7050 track_band = RTW89_MAC_0;
7051 else
7052 track_band = RTW89_MAC_1;
7053
7054 mlo_info->path_rf_band[BTC_RF_S0] =
7055 mlo_info->hwb_rf_band[RTW89_MAC_0];
7056 mlo_info->path_rf_band[BTC_RF_S1] =
7057 mlo_info->hwb_rf_band[RTW89_MAC_1];
7058
7059 /* Check ch count from ch_type @ 2.4G HW-band, and modify type */
7060 if (mlo_info->ch_type[track_band] == RTW89_MR_CTX1_2GHZ)
7061 type = RTW89_MR_WTYPE_NONMLD; /* only 1-role at 2G */
7062 else
7063 type = RTW89_MR_WTYPE_NONMLD_NONMLD;
7064
7065 if (mlo_info->hwb_rf_band[RTW89_MAC_0] == RTW89_BAND_2G) {
7066 wl_rinfo->pta_req_band = RTW89_MAC_0;
7067 wl_rinfo->dbcc_2g_phy = RTW89_PHY_0;
7068 } else {
7069 wl_rinfo->pta_req_band = RTW89_MAC_1;
7070 wl_rinfo->dbcc_2g_phy = RTW89_PHY_1;
7071 }
7072
7073 if (mlo_info->wmode[RTW89_MAC_0] == RTW89_MR_WMODE_NONE &&
7074 mlo_info->wmode[RTW89_MAC_1] == RTW89_MR_WMODE_NONE)
7075 wl_rinfo->dbcc_en = 0;
7076 else
7077 wl_rinfo->dbcc_en = 1;
7078 break;
7079 }
7080
7081 wl_rinfo->link_mode = _update_wl_link_mode(rtwdev, track_band, type);
7082
7083 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(), mode=%s, pta_band=%d",
7084 __func__, id_to_linkmode(wl_rinfo->link_mode),
7085 wl_rinfo->pta_req_band);
7086 }
7087
_update_wl_non_mlo_info(struct rtw89_dev * rtwdev)7088 static void _update_wl_non_mlo_info(struct rtw89_dev *rtwdev)
7089 {
7090 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
7091 struct rtw89_btc_wl_rlink *rlink = NULL;
7092 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
7093 struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7094 u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7095 u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7096 bool b2g = false, b5g = false, outloop = false;
7097 u8 mode = BTC_WLINK_NOLINK;
7098 u8 cnt_2g = 0, cnt_5g = 0;
7099 u8 i, j, cnt = 0;
7100
7101 for (j = RTW89_PHY_0; j < RTW89_PHY_NUM; j++) {
7102 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
7103 rlink = &wl_rinfo->rlink[i][j];
7104
7105 if (!rlink->active || !rlink->connected)
7106 continue;
7107
7108 if (cnt >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER) {
7109 outloop = true;
7110 break;
7111 }
7112
7113 cid_ch[cnt] = wl->rlink_info[i][j].chdef;
7114 cid_phy[cnt] = rlink->phy;
7115 cid_role[cnt] = rlink->role;
7116 cnt++;
7117
7118 if (rlink->rf_band != RTW89_BAND_2G) {
7119 cnt_5g++;
7120 b5g = true;
7121 } else {
7122 cnt_2g++;
7123 b2g = true;
7124 }
7125 }
7126 if (outloop)
7127 break;
7128 }
7129
7130 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7131 "[BTC], %s(): cnt_2g=%d, cnt_5g=%d\n", __func__, cnt_2g, cnt_5g);
7132
7133 wl_rinfo->dbcc_en = rtwdev->dbcc_en;
7134 /* Be careful to change the following sequence!! */
7135 if (cnt == 0) {
7136 mode = BTC_WLINK_NOLINK;
7137 } else if (!b2g && b5g) {
7138 mode = BTC_WLINK_5G;
7139 } else if (wl_rinfo->dbcc_en) {
7140 mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt);
7141 } else if (b2g && b5g) {
7142 mode = BTC_WLINK_25G_MCC;
7143 } else if (!b5g && cnt >= 2) {
7144 if (_chk_role_ch_group(&cid_ch[0], &cid_ch[1]))
7145 mode = BTC_WLINK_2G_SCC;
7146 else
7147 mode = BTC_WLINK_2G_MCC;
7148 } else if (!b5g) { /* cnt_connect = 1 */
7149 mode = _get_role_link_mode(cid_role[0]);
7150 }
7151
7152 wl_rinfo->link_mode = mode;
7153 }
7154
_modify_role_link_mode(struct rtw89_dev * rtwdev)7155 static void _modify_role_link_mode(struct rtw89_dev *rtwdev)
7156 {
7157 struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
7158 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
7159 u8 go_cleint_exist = wl->go_client_exist;
7160 u8 link_mode = wl_rinfo->link_mode;
7161 u32 role_map = wl_rinfo->role_map;
7162 u8 noa_exist = wl->noa_exist;
7163 u32 mrole = BTC_WLMROLE_NONE;
7164
7165 /* if no client_joined, don't care P2P-GO/AP role */
7166 if (((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
7167 (role_map & BIT(RTW89_WIFI_ROLE_AP))) && !go_cleint_exist) {
7168 if (link_mode == BTC_WLINK_2G_SCC) {
7169 wl_rinfo->link_mode = BTC_WLINK_2G_STA;
7170 } else if (link_mode == BTC_WLINK_2G_GO ||
7171 link_mode == BTC_WLINK_2G_AP) {
7172 wl_rinfo->link_mode = BTC_WLINK_NOLINK;
7173 }
7174 }
7175
7176 /* Identify 2-Role type */
7177 if (link_mode == BTC_WLINK_2G_SCC ||
7178 link_mode == BTC_WLINK_2G_MCC ||
7179 link_mode == BTC_WLINK_25G_MCC ||
7180 link_mode == BTC_WLINK_5G) {
7181 if ((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
7182 (role_map & BIT(RTW89_WIFI_ROLE_AP))) {
7183 if (noa_exist)
7184 mrole = BTC_WLMROLE_STA_GO_NOA;
7185 else
7186 mrole = BTC_WLMROLE_STA_GO;
7187 } else if (role_map & BIT(RTW89_WIFI_ROLE_P2P_CLIENT)) {
7188 if (noa_exist)
7189 mrole = BTC_WLMROLE_STA_GC_NOA;
7190 else
7191 mrole = BTC_WLMROLE_STA_GC;
7192 } else {
7193 mrole = BTC_WLMROLE_STA_STA;
7194 }
7195 }
7196
7197 wl_rinfo->mrole_type = mrole;
7198
7199 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7200 "[BTC], %s(): link_mode=%s, mrole_type=%d\n", __func__,
7201 id_to_linkmode(wl_rinfo->link_mode), wl_rinfo->mrole_type);
7202 }
7203
_update_wl_info_v8(struct rtw89_dev * rtwdev,u8 role_id,u8 rlink_id,enum btc_role_state state)7204 static void _update_wl_info_v8(struct rtw89_dev *rtwdev, u8 role_id, u8 rlink_id,
7205 enum btc_role_state state)
7206 {
7207 struct rtw89_btc_wl_rlink *rlink = NULL;
7208 struct rtw89_btc_wl_link_info *wl_linfo;
7209 struct rtw89_btc *btc = &rtwdev->btc;
7210 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7211 struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
7212 bool client_joined = false, noa_exist = false, p2p_exist = false;
7213 bool is_5g_hi_channel = false, bg_mode = false, dbcc_en_ori;
7214 u8 i, j, link_mode_ori;
7215 u32 role_map = 0;
7216
7217 if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id >= RTW89_MAC_NUM)
7218 return;
7219
7220 /* Extract wl->link_info[role_id][rlink_id] to wl->role_info
7221 * role_id: role index
7222 * rlink_id: rlink index (= HW-band index)
7223 * pid: port_index
7224 */
7225
7226 wl_linfo = &wl->rlink_info[role_id][rlink_id];
7227 rlink = &wl_rinfo->rlink[role_id][rlink_id];
7228
7229 rlink->role = wl_linfo->role;
7230 rlink->active = wl_linfo->active; /* Doze or not */
7231 rlink->pid = wl_linfo->pid;
7232 rlink->phy = wl_linfo->phy;
7233 rlink->rf_band = wl_linfo->band;
7234 rlink->ch = wl_linfo->ch;
7235 rlink->bw = wl_linfo->bw;
7236 rlink->noa = wl_linfo->noa;
7237 rlink->noa_dur = wl_linfo->noa_duration / 1000;
7238 rlink->client_cnt = wl_linfo->client_cnt;
7239 rlink->mode = wl_linfo->mode;
7240
7241 switch (wl_linfo->connected) {
7242 case MLME_NO_LINK:
7243 rlink->connected = 0;
7244 break;
7245 case MLME_LINKED:
7246 rlink->connected = 1;
7247 break;
7248 default:
7249 return;
7250 }
7251
7252 for (j = RTW89_MAC_0; j <= RTW89_MAC_1; j++) {
7253 for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
7254 rlink = &wl_rinfo->rlink[i][j];
7255
7256 if (!rlink->active || !rlink->connected)
7257 continue;
7258
7259 role_map |= BIT(rlink->role);
7260
7261 /* only one noa-role exist */
7262 if (rlink->noa && rlink->noa_dur > 0)
7263 noa_exist = true;
7264
7265 /* for WL 5G-Rx interfered with BT issue */
7266 if (rlink->rf_band == RTW89_BAND_5G) {
7267 if (rlink->ch >= 100)
7268 is_5g_hi_channel = true;
7269
7270 continue;
7271 }
7272
7273 /* only if client connect for p2p-Go/AP */
7274 if ((rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
7275 rlink->role == RTW89_WIFI_ROLE_AP) &&
7276 rlink->client_cnt > 1) {
7277 p2p_exist = true;
7278 client_joined = true;
7279 }
7280
7281 /* Identify if P2P-Go (GO/GC/AP) exist at 2G band */
7282 if (rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)
7283 p2p_exist = true;
7284
7285 if ((rlink->mode & BIT(BTC_WL_MODE_11B)) ||
7286 (rlink->mode & BIT(BTC_WL_MODE_11G)))
7287 bg_mode = true;
7288 }
7289 }
7290
7291 link_mode_ori = wl_rinfo->link_mode;
7292 wl->is_5g_hi_channel = is_5g_hi_channel;
7293 wl->bg_mode = bg_mode;
7294 wl->go_client_exist = client_joined;
7295 wl->noa_exist = noa_exist;
7296 wl_rinfo->p2p_2g = p2p_exist;
7297 wl_rinfo->role_map = role_map;
7298
7299 dbcc_en_ori = wl_rinfo->dbcc_en;
7300
7301 if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) {
7302 /* for MLO-supported, link-mode from driver directly */
7303 _update_wl_mlo_info(rtwdev);
7304 } else {
7305 /* for non-MLO-supported, link-mode by BTC */
7306 _update_wl_non_mlo_info(rtwdev);
7307 }
7308
7309 _modify_role_link_mode(rtwdev);
7310
7311 if (link_mode_ori != wl_rinfo->link_mode)
7312 wl->link_mode_chg = true;
7313
7314 if (wl_rinfo->dbcc_en != dbcc_en_ori) {
7315 wl->dbcc_chg = true;
7316 btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++;
7317 }
7318 }
7319
rtw89_coex_act1_work(struct wiphy * wiphy,struct wiphy_work * work)7320 void rtw89_coex_act1_work(struct wiphy *wiphy, struct wiphy_work *work)
7321 {
7322 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7323 coex_act1_work.work);
7324 struct rtw89_btc *btc = &rtwdev->btc;
7325 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7326 struct rtw89_btc_cx *cx = &btc->cx;
7327 struct rtw89_btc_wl_info *wl = &cx->wl;
7328
7329 lockdep_assert_wiphy(wiphy);
7330
7331 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7332 dm->cnt_notify[BTC_NCNT_TIMER]++;
7333 if (wl->status.map._4way)
7334 wl->status.map._4way = false;
7335 if (wl->status.map.connecting)
7336 wl->status.map.connecting = false;
7337
7338 _run_coex(rtwdev, BTC_RSN_ACT1_WORK);
7339 }
7340
rtw89_coex_bt_devinfo_work(struct wiphy * wiphy,struct wiphy_work * work)7341 void rtw89_coex_bt_devinfo_work(struct wiphy *wiphy, struct wiphy_work *work)
7342 {
7343 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7344 coex_bt_devinfo_work.work);
7345 struct rtw89_btc *btc = &rtwdev->btc;
7346 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7347 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
7348
7349 lockdep_assert_wiphy(wiphy);
7350
7351 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7352 dm->cnt_notify[BTC_NCNT_TIMER]++;
7353 a2dp->play_latency = 0;
7354 _run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK);
7355 }
7356
rtw89_coex_rfk_chk_work(struct wiphy * wiphy,struct wiphy_work * work)7357 void rtw89_coex_rfk_chk_work(struct wiphy *wiphy, struct wiphy_work *work)
7358 {
7359 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7360 coex_rfk_chk_work.work);
7361 struct rtw89_btc *btc = &rtwdev->btc;
7362 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7363 struct rtw89_btc_cx *cx = &btc->cx;
7364 struct rtw89_btc_wl_info *wl = &cx->wl;
7365
7366 lockdep_assert_wiphy(wiphy);
7367
7368 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7369 dm->cnt_notify[BTC_NCNT_TIMER]++;
7370 if (wl->rfk_info.state != BTC_WRFK_STOP) {
7371 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7372 "[BTC], %s(): RFK timeout\n", __func__);
7373 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++;
7374 dm->error.map.wl_rfk_timeout = true;
7375 wl->rfk_info.state = BTC_WRFK_STOP;
7376 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
7377 _run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK);
7378 }
7379 }
7380
_update_bt_scbd(struct rtw89_dev * rtwdev,bool only_update)7381 static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update)
7382 {
7383 const struct rtw89_chip_info *chip = rtwdev->chip;
7384 struct rtw89_btc *btc = &rtwdev->btc;
7385 struct rtw89_btc_cx *cx = &btc->cx;
7386 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
7387 u32 val;
7388 bool status_change = false;
7389
7390 if (!chip->scbd)
7391 return;
7392
7393 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
7394
7395 val = _read_scbd(rtwdev);
7396 if (val == BTC_SCB_INV_VALUE) {
7397 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7398 "[BTC], %s(): return by invalid scbd value\n",
7399 __func__);
7400 return;
7401 }
7402
7403 if (!(val & BTC_BSCB_ON))
7404 bt->enable.now = 0;
7405 else
7406 bt->enable.now = 1;
7407
7408 if (bt->enable.now != bt->enable.last)
7409 status_change = true;
7410
7411 /* reset bt info if bt re-enable */
7412 if (bt->enable.now && !bt->enable.last) {
7413 _reset_btc_var(rtwdev, BTC_RESET_BTINFO);
7414 cx->cnt_bt[BTC_BCNT_REENABLE]++;
7415 bt->enable.now = 1;
7416 }
7417
7418 bt->enable.last = bt->enable.now;
7419 bt->scbd = val;
7420 bt->mbx_avl = !!(val & BTC_BSCB_ACT);
7421
7422 if (bt->whql_test != !!(val & BTC_BSCB_WHQL))
7423 status_change = true;
7424
7425 bt->whql_test = !!(val & BTC_BSCB_WHQL);
7426 bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE;
7427 bt->link_info.a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT);
7428
7429 bt->lna_constrain = !!(val & BTC_BSCB_BT_LNAB0) +
7430 !!(val & BTC_BSCB_BT_LNAB1) * 2 + 4;
7431
7432 /* if rfk run 1->0 */
7433 if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN))
7434 status_change = true;
7435
7436 bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN);
7437 bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ);
7438 bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
7439 bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT);
7440 if (bt->run_patch_code != !!(val & BTC_BSCB_PATCH_CODE))
7441 status_change = true;
7442 bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
7443
7444 if (!only_update && status_change)
7445 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
7446 }
7447
7448 #define BTC_BTINFO_PWR_LEN 5
_update_bt_txpwr_info(struct rtw89_dev * rtwdev,u8 * buf,u32 len)7449 static void _update_bt_txpwr_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
7450 {
7451 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt;
7452 struct rtw89_btc_bt_link_info *b = &bt->link_info;
7453
7454 if (len != BTC_BTINFO_PWR_LEN)
7455 return;
7456
7457 if (!memcmp(bt->txpwr_info, buf, sizeof(bt->txpwr_info))) {
7458 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7459 "[BTC], %s return by info duplicate!\n", __func__);
7460 return;
7461 }
7462
7463 memcpy(bt->txpwr_info, buf, BTC_BTINFO_MAX);
7464 memcpy(&b->bt_txpwr_desc, &buf[2], sizeof(b->bt_txpwr_desc));
7465 }
7466
_chk_wl_rfk_request(struct rtw89_dev * rtwdev)7467 static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev)
7468 {
7469 struct rtw89_btc *btc = &rtwdev->btc;
7470 struct rtw89_btc_cx *cx = &btc->cx;
7471 struct rtw89_btc_bt_info *bt = &cx->bt;
7472
7473 _update_bt_scbd(rtwdev, true);
7474
7475 cx->cnt_wl[BTC_WCNT_RFK_REQ]++;
7476
7477 if ((bt->rfk_info.map.run || bt->rfk_info.map.req) &&
7478 !bt->rfk_info.map.timeout) {
7479 cx->cnt_wl[BTC_WCNT_RFK_REJECT]++;
7480 } else {
7481 cx->cnt_wl[BTC_WCNT_RFK_GO]++;
7482 return true;
7483 }
7484 return false;
7485 }
7486
7487 static
_run_coex(struct rtw89_dev * rtwdev,enum btc_reason_and_action reason)7488 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
7489 {
7490 struct rtw89_btc *btc = &rtwdev->btc;
7491 const struct rtw89_btc_ver *ver = btc->ver;
7492 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7493 struct rtw89_btc_cx *cx = &btc->cx;
7494 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7495 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
7496 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
7497 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
7498 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
7499 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
7500 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
7501 u8 mode, igno_bt, always_freerun;
7502
7503 lockdep_assert_wiphy(rtwdev->hw->wiphy);
7504
7505 dm->run_reason = reason;
7506 _update_dm_step(rtwdev, reason);
7507 _update_btc_state_map(rtwdev);
7508
7509 if (ver->fwlrole == 0)
7510 mode = wl_rinfo->link_mode;
7511 else if (ver->fwlrole == 1)
7512 mode = wl_rinfo_v1->link_mode;
7513 else if (ver->fwlrole == 2)
7514 mode = wl_rinfo_v2->link_mode;
7515 else if (ver->fwlrole == 7)
7516 mode = wl_rinfo_v7->link_mode;
7517 else if (ver->fwlrole == 8)
7518 mode = wl_rinfo_v8->link_mode;
7519 else
7520 return;
7521
7522 if (ver->fcxctrl == 7) {
7523 igno_bt = btc->ctrl.ctrl_v7.igno_bt;
7524 always_freerun = btc->ctrl.ctrl_v7.always_freerun;
7525 } else {
7526 igno_bt = btc->ctrl.ctrl.igno_bt;
7527 always_freerun = btc->ctrl.ctrl.always_freerun;
7528 }
7529
7530 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
7531 __func__, reason, mode);
7532 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
7533 __func__, dm->wl_only, dm->bt_only);
7534
7535 /* Be careful to change the following function sequence!! */
7536 if (btc->manual_ctrl) {
7537 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7538 "[BTC], %s(): return for Manual CTRL!!\n",
7539 __func__);
7540 return;
7541 }
7542
7543 if (igno_bt &&
7544 (reason == BTC_RSN_UPDATE_BT_INFO ||
7545 reason == BTC_RSN_UPDATE_BT_SCBD)) {
7546 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7547 "[BTC], %s(): return for Stop Coex DM!!\n",
7548 __func__);
7549 return;
7550 }
7551
7552 if (!wl->status.map.init_ok) {
7553 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7554 "[BTC], %s(): return for WL init fail!!\n",
7555 __func__);
7556 return;
7557 }
7558
7559 if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
7560 wl->status.map.lps_pre == wl->status.map.lps) {
7561 if (reason == BTC_RSN_NTFY_POWEROFF ||
7562 reason == BTC_RSN_NTFY_RADIO_STATE) {
7563 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7564 "[BTC], %s(): return for WL rf off state no change!!\n",
7565 __func__);
7566 return;
7567 }
7568 if (wl->status.map.rf_off == 1 ||
7569 wl->status.map.lps == BTC_LPS_RF_OFF) {
7570 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7571 "[BTC], %s(): return for WL rf off state!!\n",
7572 __func__);
7573 return;
7574 }
7575 }
7576
7577 dm->freerun = false;
7578 dm->cnt_dm[BTC_DCNT_RUN]++;
7579 dm->fddt_train = BTC_FDDT_DISABLE;
7580 bt->scan_rx_low_pri = false;
7581 igno_bt = false;
7582
7583 dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */
7584
7585 if (always_freerun) {
7586 _action_freerun(rtwdev);
7587 igno_bt = true;
7588 goto exit;
7589 }
7590
7591 if (dm->wl_only) {
7592 _action_wl_only(rtwdev);
7593 igno_bt = true;
7594 goto exit;
7595 }
7596
7597 if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) {
7598 _action_wl_off(rtwdev, mode);
7599 igno_bt = true;
7600 goto exit;
7601 }
7602
7603 if (reason == BTC_RSN_NTFY_INIT) {
7604 _action_wl_init(rtwdev);
7605 goto exit;
7606 }
7607
7608 if (!cx->bt.enable.now && !cx->other.type) {
7609 _action_bt_off(rtwdev);
7610 goto exit;
7611 }
7612
7613 if (cx->bt.whql_test) {
7614 _action_bt_whql(rtwdev);
7615 goto exit;
7616 }
7617
7618 if (wl->rfk_info.state != BTC_WRFK_STOP) {
7619 _action_wl_rfk(rtwdev);
7620 goto exit;
7621 }
7622
7623 if (wl->status.val & btc_scanning_map.val && !wl->rfk_info.con_rfk) {
7624 _action_wl_scan(rtwdev);
7625 bt->scan_rx_low_pri = true;
7626 goto exit;
7627 }
7628
7629 switch (mode) {
7630 case BTC_WLINK_NOLINK:
7631 _action_wl_nc(rtwdev);
7632 break;
7633 case BTC_WLINK_2G_STA:
7634 if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
7635 bt->scan_rx_low_pri = true;
7636 _action_wl_2g_sta(rtwdev);
7637 break;
7638 case BTC_WLINK_2G_AP:
7639 bt->scan_rx_low_pri = true;
7640 _action_wl_2g_ap(rtwdev);
7641 break;
7642 case BTC_WLINK_2G_GO:
7643 bt->scan_rx_low_pri = true;
7644 _action_wl_2g_go(rtwdev);
7645 break;
7646 case BTC_WLINK_2G_GC:
7647 bt->scan_rx_low_pri = true;
7648 _action_wl_2g_gc(rtwdev);
7649 break;
7650 case BTC_WLINK_2G_SCC:
7651 bt->scan_rx_low_pri = true;
7652 if (ver->fwlrole == 0)
7653 _action_wl_2g_scc(rtwdev);
7654 else if (ver->fwlrole == 1)
7655 _action_wl_2g_scc_v1(rtwdev);
7656 else if (ver->fwlrole == 2 || ver->fwlrole == 7)
7657 _action_wl_2g_scc_v2(rtwdev);
7658 else if (ver->fwlrole == 8)
7659 _action_wl_2g_scc_v8(rtwdev);
7660 break;
7661 case BTC_WLINK_2G_MCC:
7662 bt->scan_rx_low_pri = true;
7663 _action_wl_2g_mcc(rtwdev);
7664 break;
7665 case BTC_WLINK_25G_MCC:
7666 bt->scan_rx_low_pri = true;
7667 _action_wl_25g_mcc(rtwdev);
7668 break;
7669 case BTC_WLINK_5G:
7670 _action_wl_5g(rtwdev);
7671 break;
7672 case BTC_WLINK_2G_NAN:
7673 _action_wl_2g_nan(rtwdev);
7674 break;
7675 default:
7676 _action_wl_other(rtwdev);
7677 break;
7678 }
7679
7680 exit:
7681 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__);
7682 if (ver->fcxctrl == 7)
7683 btc->ctrl.ctrl_v7.igno_bt = igno_bt;
7684 else
7685 btc->ctrl.ctrl.igno_bt = igno_bt;
7686 _action_common(rtwdev);
7687 }
7688
rtw89_btc_ntfy_poweron(struct rtw89_dev * rtwdev)7689 void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
7690 {
7691 struct rtw89_btc *btc = &rtwdev->btc;
7692
7693 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
7694 btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++;
7695 }
7696
rtw89_btc_ntfy_poweroff(struct rtw89_dev * rtwdev)7697 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
7698 {
7699 struct rtw89_btc *btc = &rtwdev->btc;
7700 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7701
7702 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
7703 btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
7704
7705 btc->cx.wl.status.map.rf_off = 1;
7706 btc->cx.wl.status.map.busy = 0;
7707 wl->status.map.lps = BTC_LPS_OFF;
7708
7709 _write_scbd(rtwdev, BTC_WSCB_ALL, false);
7710 _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
7711
7712 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
7713
7714 btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
7715 }
7716
_set_init_info(struct rtw89_dev * rtwdev)7717 static void _set_init_info(struct rtw89_dev *rtwdev)
7718 {
7719 const struct rtw89_chip_info *chip = rtwdev->chip;
7720 struct rtw89_btc *btc = &rtwdev->btc;
7721 const struct rtw89_btc_ver *ver = btc->ver;
7722 struct rtw89_btc_dm *dm = &btc->dm;
7723 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7724
7725 if (ver->fcxinit == 7) {
7726 dm->init_info.init_v7.wl_only = (u8)dm->wl_only;
7727 dm->init_info.init_v7.bt_only = (u8)dm->bt_only;
7728 dm->init_info.init_v7.wl_init_ok = (u8)wl->status.map.init_ok;
7729 dm->init_info.init_v7.cx_other = btc->cx.other.type;
7730 dm->init_info.init_v7.wl_guard_ch = chip->afh_guard_ch;
7731 dm->init_info.init_v7.module = btc->mdinfo.md_v7;
7732 } else {
7733 dm->init_info.init.wl_only = (u8)dm->wl_only;
7734 dm->init_info.init.bt_only = (u8)dm->bt_only;
7735 dm->init_info.init.wl_init_ok = (u8)wl->status.map.init_ok;
7736 dm->init_info.init.dbcc_en = rtwdev->dbcc_en;
7737 dm->init_info.init.cx_other = btc->cx.other.type;
7738 dm->init_info.init.wl_guard_ch = chip->afh_guard_ch;
7739 dm->init_info.init.module = btc->mdinfo.md;
7740 }
7741 }
7742
rtw89_btc_ntfy_init(struct rtw89_dev * rtwdev,u8 mode)7743 void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
7744 {
7745 struct rtw89_btc *btc = &rtwdev->btc;
7746 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7747 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7748 const struct rtw89_chip_info *chip = rtwdev->chip;
7749 const struct rtw89_btc_ver *ver = btc->ver;
7750
7751 _reset_btc_var(rtwdev, BTC_RESET_ALL);
7752 btc->dm.run_reason = BTC_RSN_NONE;
7753 btc->dm.run_action = BTC_ACT_NONE;
7754 if (ver->fcxctrl == 7)
7755 btc->ctrl.ctrl_v7.igno_bt = true;
7756 else
7757 btc->ctrl.ctrl.igno_bt = true;
7758
7759 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7760 "[BTC], %s(): mode=%d\n", __func__, mode);
7761
7762 wl->coex_mode = mode;
7763 dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
7764 dm->wl_only = mode == BTC_MODE_WL ? 1 : 0;
7765 dm->bt_only = mode == BTC_MODE_BT ? 1 : 0;
7766 wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0;
7767
7768 chip->ops->btc_set_rfe(rtwdev);
7769 chip->ops->btc_init_cfg(rtwdev);
7770
7771 if (!wl->status.map.init_ok) {
7772 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7773 "[BTC], %s(): return for WL init fail!!\n",
7774 __func__);
7775 dm->error.map.init = true;
7776 return;
7777 }
7778
7779 _write_scbd(rtwdev,
7780 BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
7781 _update_bt_scbd(rtwdev, true);
7782 if (rtw89_mac_get_ctrl_path(rtwdev)) {
7783 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7784 "[BTC], %s(): PTA owner warning!!\n",
7785 __func__);
7786 dm->error.map.pta_owner = true;
7787 }
7788
7789 _set_init_info(rtwdev);
7790 _set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR);
7791 btc_fw_set_monreg(rtwdev);
7792 rtw89_btc_fw_set_slots(rtwdev);
7793 _fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
7794 _fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
7795
7796 _run_coex(rtwdev, BTC_RSN_NTFY_INIT);
7797 }
7798
rtw89_btc_ntfy_scan_start(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)7799 void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
7800 {
7801 struct rtw89_btc *btc = &rtwdev->btc;
7802 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7803
7804 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7805 "[BTC], %s(): phy_idx=%d, band=%d\n",
7806 __func__, phy_idx, band);
7807
7808 if (phy_idx >= RTW89_PHY_NUM)
7809 return;
7810
7811 btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
7812 wl->status.map.scan = true;
7813 wl->scan_info.band[phy_idx] = band;
7814 wl->scan_info.phy_map |= BIT(phy_idx);
7815 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
7816
7817 if (rtwdev->dbcc_en) {
7818 wl->dbcc_info.scan_band[phy_idx] = band;
7819 _update_dbcc_band(rtwdev, phy_idx);
7820 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7821 }
7822
7823 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START);
7824 }
7825
rtw89_btc_ntfy_scan_finish(struct rtw89_dev * rtwdev,u8 phy_idx)7826 void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
7827 {
7828 struct rtw89_btc *btc = &rtwdev->btc;
7829 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7830
7831 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7832 "[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
7833 btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
7834
7835 wl->status.map.scan = false;
7836 wl->scan_info.phy_map &= ~BIT(phy_idx);
7837 _fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
7838
7839 if (rtwdev->dbcc_en) {
7840 _update_dbcc_band(rtwdev, phy_idx);
7841 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7842 }
7843
7844 btc->dm.tdma_instant_excute = 1;
7845
7846 _run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
7847 }
7848
rtw89_btc_ntfy_switch_band(struct rtw89_dev * rtwdev,u8 phy_idx,u8 band)7849 void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
7850 {
7851 struct rtw89_btc *btc = &rtwdev->btc;
7852 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7853
7854 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7855 "[BTC], %s(): phy_idx=%d, band=%d\n",
7856 __func__, phy_idx, band);
7857
7858 if (phy_idx >= RTW89_PHY_NUM)
7859 return;
7860
7861 btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
7862
7863 if (rtwdev->dbcc_en) {
7864 wl->dbcc_info.scan_band[phy_idx] = band;
7865 _update_dbcc_band(rtwdev, phy_idx);
7866 _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7867 }
7868 _run_coex(rtwdev, BTC_RSN_NTFY_SWBAND);
7869 }
7870
rtw89_btc_ntfy_specific_packet(struct rtw89_dev * rtwdev,enum btc_pkt_type pkt_type)7871 void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev,
7872 enum btc_pkt_type pkt_type)
7873 {
7874 struct rtw89_btc *btc = &rtwdev->btc;
7875 struct rtw89_btc_cx *cx = &btc->cx;
7876 struct rtw89_btc_wl_info *wl = &cx->wl;
7877 struct rtw89_btc_bt_link_info *b = &cx->bt.link_info;
7878 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
7879 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
7880 u32 cnt;
7881 u32 delay = RTW89_COEX_ACT1_WORK_PERIOD;
7882 bool delay_work = false;
7883
7884 switch (pkt_type) {
7885 case PACKET_DHCP:
7886 cnt = ++cx->cnt_wl[BTC_WCNT_DHCP];
7887 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7888 "[BTC], %s(): DHCP cnt=%d\n", __func__, cnt);
7889 wl->status.map.connecting = true;
7890 delay_work = true;
7891 break;
7892 case PACKET_EAPOL:
7893 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
7894 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7895 "[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt);
7896 wl->status.map._4way = true;
7897 delay_work = true;
7898 if (hfp->exist || hid->exist)
7899 delay /= 2;
7900 break;
7901 case PACKET_EAPOL_END:
7902 cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
7903 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7904 "[BTC], %s(): EAPOL_End cnt=%d\n",
7905 __func__, cnt);
7906 wl->status.map._4way = false;
7907 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work);
7908 break;
7909 case PACKET_ARP:
7910 cnt = ++cx->cnt_wl[BTC_WCNT_ARP];
7911 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7912 "[BTC], %s(): ARP cnt=%d\n", __func__, cnt);
7913 return;
7914 case PACKET_ICMP:
7915 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7916 "[BTC], %s(): ICMP pkt\n", __func__);
7917 return;
7918 default:
7919 rtw89_debug(rtwdev, RTW89_DBG_BTC,
7920 "[BTC], %s(): unknown packet type %d\n",
7921 __func__, pkt_type);
7922 return;
7923 }
7924
7925 if (delay_work) {
7926 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work);
7927 wiphy_delayed_work_queue(rtwdev->hw->wiphy,
7928 &rtwdev->coex_act1_work, delay);
7929 }
7930
7931 btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
7932 _run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET);
7933 }
7934
rtw89_btc_ntfy_eapol_packet_work(struct wiphy * wiphy,struct wiphy_work * work)7935 void rtw89_btc_ntfy_eapol_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7936 {
7937 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7938 btc.eapol_notify_work);
7939
7940 lockdep_assert_wiphy(wiphy);
7941
7942 rtw89_leave_ps_mode(rtwdev);
7943 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL);
7944 }
7945
rtw89_btc_ntfy_arp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)7946 void rtw89_btc_ntfy_arp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7947 {
7948 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7949 btc.arp_notify_work);
7950
7951 lockdep_assert_wiphy(wiphy);
7952
7953 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP);
7954 }
7955
rtw89_btc_ntfy_dhcp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)7956 void rtw89_btc_ntfy_dhcp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7957 {
7958 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7959 btc.dhcp_notify_work);
7960
7961 lockdep_assert_wiphy(wiphy);
7962
7963 rtw89_leave_ps_mode(rtwdev);
7964 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP);
7965 }
7966
rtw89_btc_ntfy_icmp_packet_work(struct wiphy * wiphy,struct wiphy_work * work)7967 void rtw89_btc_ntfy_icmp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7968 {
7969 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7970 btc.icmp_notify_work);
7971
7972 lockdep_assert_wiphy(wiphy);
7973
7974 rtw89_leave_ps_mode(rtwdev);
7975 rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP);
7976 }
7977
_update_bt_rssi_level(struct rtw89_dev * rtwdev,u8 rssi)7978 static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi)
7979 {
7980 const struct rtw89_chip_info *chip = rtwdev->chip;
7981 struct rtw89_btc *btc = &rtwdev->btc;
7982 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
7983 u8 *rssi_st, rssi_th, rssi_level = 0;
7984 u8 i;
7985
7986 /* for rssi locate in which {40, 36, 31, 28}
7987 * if rssi >= 40% (-60dBm) --> rssi_level = 4
7988 * if 36% <= rssi < 40% --> rssi_level = 3
7989 * if 31% <= rssi < 36% --> rssi_level = 2
7990 * if 28% <= rssi < 31% --> rssi_level = 1
7991 * if rssi < 28% --> rssi_level = 0
7992 */
7993
7994 /* check if rssi across bt_rssi_thres boundary */
7995 for (i = 0; i < BTC_BT_RSSI_THMAX; i++) {
7996 rssi_th = chip->bt_rssi_thres[i];
7997 rssi_st = &bt->link_info.rssi_state[i];
7998
7999 *rssi_st = _update_rssi_state(rtwdev, *rssi_st, rssi, rssi_th);
8000
8001 if (BTC_RSSI_HIGH(*rssi_st)) {
8002 rssi_level = BTC_BT_RSSI_THMAX - i;
8003 break;
8004 }
8005 }
8006 return rssi_level;
8007 }
8008
_update_zb_coex_tbl(struct rtw89_dev * rtwdev)8009 static void _update_zb_coex_tbl(struct rtw89_dev *rtwdev)
8010 {
8011 u8 mode = rtwdev->btc.cx.wl.role_info.link_mode;
8012 u32 zb_tbl0 = 0xda5a5a5a, zb_tbl1 = 0xda5a5a5a;
8013
8014 if (mode == BTC_WLINK_5G || rtwdev->btc.dm.freerun) {
8015 zb_tbl0 = 0xffffffff;
8016 zb_tbl1 = 0xffffffff;
8017 } else if (mode == BTC_WLINK_25G_MCC) {
8018 zb_tbl0 = 0xffffffff; /* for E5G slot */
8019 zb_tbl1 = 0xda5a5a5a; /* for E2G slot */
8020 }
8021 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_0, zb_tbl0);
8022 rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_1, zb_tbl1);
8023 }
8024
8025 #define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4)
8026
_update_bt_info(struct rtw89_dev * rtwdev,u8 * buf,u32 len)8027 static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
8028 {
8029 const struct rtw89_chip_info *chip = rtwdev->chip;
8030 struct rtw89_btc *btc = &rtwdev->btc;
8031 struct rtw89_btc_cx *cx = &btc->cx;
8032 struct rtw89_btc_bt_info *bt = &cx->bt;
8033 struct rtw89_btc_bt_link_info *b = &bt->link_info;
8034 struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
8035 struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
8036 struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
8037 struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc;
8038 union btc_btinfo btinfo;
8039
8040 if (buf[BTC_BTINFO_L1] != 6)
8041 return;
8042
8043 if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) {
8044 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8045 "[BTC], %s(): return by bt-info duplicate!!\n",
8046 __func__);
8047 cx->cnt_bt[BTC_BCNT_INFOSAME]++;
8048 return;
8049 }
8050
8051 memcpy(bt->raw_info, buf, BTC_BTINFO_MAX);
8052
8053 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8054 "[BTC], %s(): bt_info[2]=0x%02x\n",
8055 __func__, bt->raw_info[2]);
8056
8057 b->profile_cnt.last = b->profile_cnt.now;
8058 b->profile_cnt.now = 0;
8059 hid->type = 0;
8060
8061 /* parse raw info low-Byte2 */
8062 btinfo.val = bt->raw_info[BTC_BTINFO_L2];
8063 b->status.map.connect = btinfo.lb2.connect;
8064 b->status.map.sco_busy = btinfo.lb2.sco_busy;
8065 b->status.map.acl_busy = btinfo.lb2.acl_busy;
8066 b->status.map.inq_pag = btinfo.lb2.inq_pag;
8067 bt->inq_pag.now = btinfo.lb2.inq_pag;
8068 cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
8069
8070 hfp->exist = btinfo.lb2.hfp;
8071 b->profile_cnt.now += (u8)hfp->exist;
8072 hid->exist = btinfo.lb2.hid;
8073 b->profile_cnt.now += (u8)hid->exist;
8074 a2dp->exist = btinfo.lb2.a2dp;
8075 b->profile_cnt.now += (u8)a2dp->exist;
8076 pan->exist = btinfo.lb2.pan;
8077 b->profile_cnt.now += (u8)pan->exist;
8078 btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK);
8079
8080 /* parse raw info low-Byte3 */
8081 btinfo.val = bt->raw_info[BTC_BTINFO_L3];
8082 if (btinfo.lb3.retry != 0)
8083 cx->cnt_bt[BTC_BCNT_RETRY]++;
8084 b->cqddr = btinfo.lb3.cqddr;
8085 cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
8086 bt->inq = btinfo.lb3.inq;
8087 cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
8088 bt->pag = btinfo.lb3.pag;
8089
8090 b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
8091 /* parse raw info high-Byte0 */
8092 btinfo.val = bt->raw_info[BTC_BTINFO_H0];
8093 /* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/
8094 b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi);
8095 bt->rssi_level = _update_bt_rssi_level(rtwdev, b->rssi);
8096 btc->dm.trx_info.bt_rssi = bt->rssi_level;
8097
8098 /* parse raw info high-Byte1 */
8099 btinfo.val = bt->raw_info[BTC_BTINFO_H1];
8100 b->status.map.ble_connect = btinfo.hb1.ble_connect;
8101 if (btinfo.hb1.ble_connect) {
8102 if (hid->exist)
8103 hid->type |= BTC_HID_BLE;
8104 else if (btinfo.hb1.voice)
8105 hid->type |= BTC_HID_RCU_VOICE;
8106 else
8107 hid->type |= BTC_HID_RCU;
8108 }
8109
8110 cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
8111 bt->reinit = btinfo.hb1.reinit;
8112 cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
8113 b->relink.now = btinfo.hb1.relink;
8114 cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
8115 bt->igno_wl = btinfo.hb1.igno_wl;
8116
8117 if (bt->igno_wl && !cx->wl.status.map.rf_off)
8118 _set_bt_ignore_wlan_act(rtwdev, false);
8119
8120 bt->ble_scan_en = btinfo.hb1.ble_scan;
8121
8122 cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
8123 b->role_sw = btinfo.hb1.role_sw;
8124
8125 b->multi_link.now = btinfo.hb1.multi_link;
8126
8127 /* parse raw info high-Byte2 */
8128 btinfo.val = bt->raw_info[BTC_BTINFO_H2];
8129 pan->active = !!btinfo.hb2.pan_active;
8130
8131 cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
8132 b->afh_update = btinfo.hb2.afh_update;
8133 a2dp->active = btinfo.hb2.a2dp_active;
8134 b->slave_role = btinfo.hb2.slave;
8135 hid->slot_info = btinfo.hb2.hid_slot;
8136 hid->pair_cnt = btinfo.hb2.hid_cnt;
8137 if (!b->status.map.ble_connect || hid->pair_cnt > 1)
8138 hid->type |= (hid->slot_info == BTC_HID_218 ?
8139 BTC_HID_218 : BTC_HID_418);
8140 /* parse raw info high-Byte3 */
8141 btinfo.val = bt->raw_info[BTC_BTINFO_H3];
8142 a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
8143
8144 if (b->tx_3m != (u32)btinfo.hb3.tx_3m)
8145 cx->cnt_bt[BTC_BCNT_RATECHG]++;
8146 b->tx_3m = (u32)btinfo.hb3.tx_3m;
8147
8148 a2dp->sink = btinfo.hb3.a2dp_sink;
8149
8150 if (!a2dp->exist_last && a2dp->exist) {
8151 a2dp->vendor_id = 0;
8152 a2dp->flush_time = 0;
8153 a2dp->play_latency = 1;
8154 wiphy_delayed_work_queue(rtwdev->hw->wiphy,
8155 &rtwdev->coex_bt_devinfo_work,
8156 RTW89_COEX_BT_DEVINFO_WORK_PERIOD);
8157 }
8158
8159 _run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
8160 }
8161
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)8162 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev,
8163 struct rtw89_vif_link *rtwvif_link,
8164 struct rtw89_sta_link *rtwsta_link,
8165 enum btc_role_state state)
8166 {
8167 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
8168 rtwvif_link->chanctx_idx);
8169 struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
8170 struct ieee80211_bss_conf *bss_conf;
8171 struct ieee80211_link_sta *link_sta;
8172 struct rtw89_btc *btc = &rtwdev->btc;
8173 const struct rtw89_btc_ver *ver = btc->ver;
8174 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8175 struct rtw89_btc_wl_link_info r = {0};
8176 struct rtw89_btc_wl_link_info *wlinfo = NULL;
8177 u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type;
8178
8179 rcu_read_lock();
8180
8181 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
8182
8183 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
8184 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8185 "[BTC], role is STA=%d\n",
8186 vif->type == NL80211_IFTYPE_STATION);
8187 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif_link->port);
8188 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
8189 chan->band_type, chan->channel, chan->band_width);
8190 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
8191 state == BTC_ROLE_MSTS_STA_CONN_END);
8192 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8193 "[BTC], bcn_period=%d dtim_period=%d\n",
8194 bss_conf->beacon_int, bss_conf->dtim_period);
8195
8196 if (rtwsta_link) {
8197 link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
8198
8199 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
8200 rtwsta_link->mac_id);
8201
8202 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8203 "[BTC], STA support HE=%d VHT=%d HT=%d\n",
8204 link_sta->he_cap.has_he,
8205 link_sta->vht_cap.vht_supported,
8206 link_sta->ht_cap.ht_supported);
8207 if (link_sta->he_cap.has_he)
8208 mode |= BIT(BTC_WL_MODE_HE);
8209 if (link_sta->vht_cap.vht_supported)
8210 mode |= BIT(BTC_WL_MODE_VHT);
8211 if (link_sta->ht_cap.ht_supported)
8212 mode |= BIT(BTC_WL_MODE_HT);
8213
8214 r.mode = mode;
8215 }
8216
8217 if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) {
8218 rcu_read_unlock();
8219 return;
8220 }
8221
8222 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8223 "[BTC], wifi_role=%d\n", rtwvif_link->wifi_role);
8224
8225 r.role = rtwvif_link->wifi_role;
8226 r.phy = rtwvif_link->phy_idx;
8227 r.pid = rtwvif_link->port;
8228 r.active = true;
8229 r.connected = MLME_LINKED;
8230 r.bcn_period = bss_conf->beacon_int;
8231 r.dtim_period = bss_conf->dtim_period;
8232 r.band = chan->band_type;
8233 r.ch = chan->channel;
8234 r.bw = chan->band_width;
8235 r.chdef.band = chan->band_type;
8236 r.chdef.center_ch = chan->channel;
8237 r.chdef.bw = chan->band_width;
8238 r.chdef.chan = chan->primary_channel;
8239 ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr);
8240
8241 rcu_read_unlock();
8242
8243 if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION)
8244 r.mac_id = rtwsta_link->mac_id;
8245
8246 btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
8247
8248 wlinfo = &wl->link_info[r.pid];
8249
8250 if (ver->fwlrole == 0) {
8251 *wlinfo = r;
8252 _update_wl_info(rtwdev);
8253 } else if (ver->fwlrole == 1) {
8254 *wlinfo = r;
8255 _update_wl_info_v1(rtwdev);
8256 } else if (ver->fwlrole == 2) {
8257 *wlinfo = r;
8258 _update_wl_info_v2(rtwdev);
8259 } else if (ver->fwlrole == 7) {
8260 *wlinfo = r;
8261 _update_wl_info_v7(rtwdev, r.pid);
8262 } else if (ver->fwlrole == 8) {
8263 rlink_id = rtwvif_link->mac_idx;
8264 wlinfo = &wl->rlink_info[r.pid][rlink_id];
8265 *wlinfo = r;
8266 link_mode_ori = wl->role_info_v8.link_mode;
8267 pta_req_mac_ori = wl->pta_req_mac;
8268 _update_wl_info_v8(rtwdev, r.pid, rlink_id, state);
8269
8270 if (wl->role_info_v8.link_mode != link_mode_ori) {
8271 wl->role_info_v8.link_mode_chg = 1;
8272 if (ver->fcxinit == 7)
8273 wa_type = btc->mdinfo.md_v7.wa_type;
8274 else
8275 wa_type = btc->mdinfo.md.wa_type;
8276
8277 if (wa_type & BTC_WA_HFP_ZB)
8278 _update_zb_coex_tbl(rtwdev);
8279 }
8280
8281 if (wl->pta_req_mac != pta_req_mac_ori)
8282 wl->pta_reg_mac_chg = 1;
8283 }
8284
8285 if (wlinfo->role == RTW89_WIFI_ROLE_STATION &&
8286 wlinfo->connected == MLME_NO_LINK)
8287 btc->dm.leak_ap = 0;
8288
8289 if (state == BTC_ROLE_MSTS_STA_CONN_START)
8290 wl->status.map.connecting = 1;
8291 else
8292 wl->status.map.connecting = 0;
8293
8294 if (state == BTC_ROLE_MSTS_STA_DIS_CONN ||
8295 state == BTC_ROLE_MSTS_STA_CONN_END)
8296 wl->status.map._4way = false;
8297
8298 _run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
8299 }
8300
rtw89_btc_ntfy_radio_state(struct rtw89_dev * rtwdev,enum btc_rfctrl rf_state)8301 void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state)
8302 {
8303 const struct rtw89_chip_info *chip = rtwdev->chip;
8304 struct rtw89_btc *btc = &rtwdev->btc;
8305 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8306 u32 val;
8307
8308 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
8309 __func__, rf_state);
8310 btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
8311
8312 switch (rf_state) {
8313 case BTC_RFCTRL_WL_OFF:
8314 wl->status.map.rf_off = 1;
8315 wl->status.map.lps = BTC_LPS_OFF;
8316 wl->status.map.busy = 0;
8317 break;
8318 case BTC_RFCTRL_FW_CTRL:
8319 wl->status.map.rf_off = 0;
8320 wl->status.map.lps = BTC_LPS_RF_OFF;
8321 wl->status.map.busy = 0;
8322 break;
8323 case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */
8324 wl->status.map.rf_off = 0;
8325 wl->status.map.lps = BTC_LPS_RF_ON;
8326 wl->status.map.busy = 0;
8327 break;
8328 case BTC_RFCTRL_WL_ON:
8329 default:
8330 wl->status.map.rf_off = 0;
8331 wl->status.map.lps = BTC_LPS_OFF;
8332 break;
8333 }
8334
8335 if (rf_state == BTC_RFCTRL_WL_ON) {
8336 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, true);
8337 val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG;
8338 _write_scbd(rtwdev, val, true);
8339 _update_bt_scbd(rtwdev, true);
8340 chip->ops->btc_init_cfg(rtwdev);
8341 } else {
8342 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false);
8343 if (rf_state == BTC_RFCTRL_FW_CTRL)
8344 _write_scbd(rtwdev, BTC_WSCB_ACTIVE, false);
8345 else if (rf_state == BTC_RFCTRL_WL_OFF)
8346 _write_scbd(rtwdev, BTC_WSCB_ALL, false);
8347 else
8348 _write_scbd(rtwdev, BTC_WSCB_ACTIVE, false);
8349
8350 if (rf_state == BTC_RFCTRL_LPS_WL_ON &&
8351 wl->status.map.lps_pre != BTC_LPS_OFF)
8352 _update_bt_scbd(rtwdev, true);
8353 }
8354
8355 btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
8356 btc->dm.tdma_instant_excute = 1;
8357
8358 _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
8359 wl->status.map.rf_off_pre = wl->status.map.rf_off;
8360 wl->status.map.lps_pre = wl->status.map.lps;
8361 }
8362
_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_path,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)8363 static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path,
8364 enum btc_wl_rfk_type type,
8365 enum btc_wl_rfk_state state)
8366 {
8367 struct rtw89_btc *btc = &rtwdev->btc;
8368 struct rtw89_btc_cx *cx = &btc->cx;
8369 struct rtw89_btc_wl_info *wl = &cx->wl;
8370 bool result = BTC_WRFK_REJECT;
8371
8372 wl->rfk_info.type = type;
8373 wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path);
8374 wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path);
8375 wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path);
8376
8377 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8378 "[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
8379 __func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
8380 type, state);
8381
8382 switch (state) {
8383 case BTC_WRFK_START:
8384 result = _chk_wl_rfk_request(rtwdev);
8385 wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP;
8386
8387 _write_scbd(rtwdev, BTC_WSCB_WLRFK, result);
8388
8389 btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
8390 break;
8391 case BTC_WRFK_ONESHOT_START:
8392 case BTC_WRFK_ONESHOT_STOP:
8393 if (wl->rfk_info.state == BTC_WRFK_STOP) {
8394 result = BTC_WRFK_REJECT;
8395 } else {
8396 result = BTC_WRFK_ALLOW;
8397 wl->rfk_info.state = state;
8398 }
8399 break;
8400 case BTC_WRFK_STOP:
8401 result = BTC_WRFK_ALLOW;
8402 wl->rfk_info.state = BTC_WRFK_STOP;
8403
8404 _write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
8405 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_rfk_chk_work);
8406 break;
8407 default:
8408 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8409 "[BTC], %s() warning state=%d\n", __func__, state);
8410 break;
8411 }
8412
8413 if (result == BTC_WRFK_ALLOW) {
8414 if (wl->rfk_info.state == BTC_WRFK_START ||
8415 wl->rfk_info.state == BTC_WRFK_STOP)
8416 _run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK);
8417
8418 if (wl->rfk_info.state == BTC_WRFK_START)
8419 wiphy_delayed_work_queue(rtwdev->hw->wiphy,
8420 &rtwdev->coex_rfk_chk_work,
8421 RTW89_COEX_RFK_CHK_WORK_PERIOD);
8422 }
8423
8424 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8425 "[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
8426 __func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
8427
8428 return result == BTC_WRFK_ALLOW;
8429 }
8430
rtw89_btc_ntfy_wl_rfk(struct rtw89_dev * rtwdev,u8 phy_map,enum btc_wl_rfk_type type,enum btc_wl_rfk_state state)8431 void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
8432 enum btc_wl_rfk_type type,
8433 enum btc_wl_rfk_state state)
8434 {
8435 u8 band;
8436 bool allow;
8437 int ret;
8438
8439 lockdep_assert_wiphy(rtwdev->hw->wiphy);
8440
8441 band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map);
8442
8443 rtw89_debug(rtwdev, RTW89_DBG_RFK,
8444 "[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n",
8445 band == RTW89_BAND_2G ? "2G" :
8446 band == RTW89_BAND_5G ? "5G" : "6G",
8447 !!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)),
8448 type,
8449 FIELD_GET(BTC_RFK_PATH_MAP, phy_map),
8450 state == BTC_WRFK_STOP ? "RFK_STOP" :
8451 state == BTC_WRFK_START ? "RFK_START" :
8452 state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" :
8453 "ONE-SHOT_STOP");
8454
8455 if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) {
8456 _ntfy_wl_rfk(rtwdev, phy_map, type, state);
8457 return;
8458 }
8459
8460 ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false,
8461 rtwdev, phy_map, type, state);
8462 if (ret) {
8463 rtw89_warn(rtwdev, "RFK notify timeout\n");
8464 rtwdev->is_bt_iqk_timeout = true;
8465 }
8466 }
8467 EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk);
8468
8469 struct rtw89_btc_wl_sta_iter_data {
8470 struct rtw89_dev *rtwdev;
8471 u8 busy_all;
8472 u8 dir_all;
8473 u8 rssi_map_all;
8474 bool is_sta_change;
8475 bool is_traffic_change;
8476 };
8477
8478 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)8479 void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link,
8480 struct rtw89_sta_link *rtwsta_link,
8481 struct rtw89_btc_wl_sta_iter_data *iter_data)
8482 {
8483 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
8484 struct rtw89_dev *rtwdev = iter_data->rtwdev;
8485 struct rtw89_btc *btc = &rtwdev->btc;
8486 struct rtw89_btc_dm *dm = &btc->dm;
8487 const struct rtw89_btc_ver *ver = btc->ver;
8488 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8489 struct rtw89_btc_wl_link_info *link_info = NULL;
8490 struct rtw89_traffic_stats *link_info_t = NULL;
8491 struct rtw89_traffic_stats *stats = &rtwvif->stats;
8492 const struct rtw89_chip_info *chip = rtwdev->chip;
8493 struct rtw89_btc_wl_role_info *r;
8494 struct rtw89_btc_wl_role_info_v1 *r1;
8495 u32 last_tx_rate, last_rx_rate;
8496 u16 last_tx_lvl, last_rx_lvl;
8497 u8 port = rtwvif_link->port;
8498 u8 rssi;
8499 u8 busy = 0;
8500 u8 dir = 0;
8501 u8 rssi_map = 0;
8502 u8 i = 0;
8503 bool is_sta_change = false, is_traffic_change = false;
8504
8505 rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR;
8506 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
8507
8508 if (btc->ver->fwlrole != 8)
8509 link_info = &wl->link_info[port];
8510 else
8511 link_info = &wl->rlink_info[port][rtwvif_link->mac_idx];
8512
8513 link_info->stat.traffic = *stats;
8514 link_info_t = &link_info->stat.traffic;
8515
8516 if (link_info->connected == MLME_NO_LINK) {
8517 link_info->rx_rate_drop_cnt = 0;
8518 return;
8519 }
8520
8521 link_info->stat.rssi = rssi;
8522 for (i = 0; i < BTC_WL_RSSI_THMAX; i++) {
8523 link_info->rssi_state[i] =
8524 _update_rssi_state(rtwdev,
8525 link_info->rssi_state[i],
8526 link_info->stat.rssi,
8527 chip->wl_rssi_thres[i]);
8528 if (BTC_RSSI_LOW(link_info->rssi_state[i]))
8529 rssi_map |= BIT(i);
8530
8531 if (btc->ant_type == BTC_ANT_DEDICATED &&
8532 BTC_RSSI_CHANGE(link_info->rssi_state[i]))
8533 is_sta_change = true;
8534 }
8535 iter_data->rssi_map_all |= rssi_map;
8536
8537 last_tx_rate = link_info_t->tx_rate;
8538 last_rx_rate = link_info_t->rx_rate;
8539 last_tx_lvl = (u16)link_info_t->tx_tfc_lv;
8540 last_rx_lvl = (u16)link_info_t->rx_tfc_lv;
8541
8542 if (stats->tx_tfc_lv != RTW89_TFC_IDLE ||
8543 stats->rx_tfc_lv != RTW89_TFC_IDLE)
8544 busy = 1;
8545
8546 if (stats->tx_tfc_lv > stats->rx_tfc_lv)
8547 dir = RTW89_TFC_UL;
8548 else
8549 dir = RTW89_TFC_DL;
8550
8551 link_info = &wl->link_info[port];
8552 if (link_info->busy != busy || link_info->dir != dir) {
8553 is_sta_change = true;
8554 link_info->busy = busy;
8555 link_info->dir = dir;
8556 }
8557
8558 iter_data->busy_all |= busy;
8559 iter_data->dir_all |= BIT(dir);
8560
8561 if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
8562 last_rx_rate > RTW89_HW_RATE_CCK2 &&
8563 link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
8564 link_info->rx_rate_drop_cnt++;
8565
8566 if (last_tx_rate != rtwsta_link->ra_report.hw_rate ||
8567 last_rx_rate != rtwsta_link->rx_hw_rate ||
8568 last_tx_lvl != link_info_t->tx_tfc_lv ||
8569 last_rx_lvl != link_info_t->rx_tfc_lv)
8570 is_traffic_change = true;
8571
8572 link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate;
8573 link_info_t->rx_rate = rtwsta_link->rx_hw_rate;
8574
8575 if (link_info->role == RTW89_WIFI_ROLE_STATION ||
8576 link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) {
8577 dm->trx_info.tx_rate = link_info_t->tx_rate;
8578 dm->trx_info.rx_rate = link_info_t->rx_rate;
8579 }
8580
8581 if (ver->fwlrole == 0) {
8582 r = &wl->role_info;
8583 r->active_role[port].tx_lvl = stats->tx_tfc_lv;
8584 r->active_role[port].rx_lvl = stats->rx_tfc_lv;
8585 r->active_role[port].tx_rate = rtwsta_link->ra_report.hw_rate;
8586 r->active_role[port].rx_rate = rtwsta_link->rx_hw_rate;
8587 } else if (ver->fwlrole == 1) {
8588 r1 = &wl->role_info_v1;
8589 r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv;
8590 r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv;
8591 r1->active_role_v1[port].tx_rate = rtwsta_link->ra_report.hw_rate;
8592 r1->active_role_v1[port].rx_rate = rtwsta_link->rx_hw_rate;
8593 }
8594
8595 dm->trx_info.tx_lvl = stats->tx_tfc_lv;
8596 dm->trx_info.rx_lvl = stats->rx_tfc_lv;
8597 dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate;
8598 dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate;
8599 dm->trx_info.tx_tp = link_info_t->tx_throughput;
8600 dm->trx_info.rx_tp = link_info_t->rx_throughput;
8601
8602 /* Trigger coex-run if 0x10980 reg-value is diff with coex setup */
8603 if ((dm->wl_btg_rx_rb != dm->wl_btg_rx &&
8604 dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) ||
8605 (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
8606 dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND))
8607 iter_data->is_sta_change = true;
8608
8609 if (is_sta_change)
8610 iter_data->is_sta_change = true;
8611
8612 if (is_traffic_change)
8613 iter_data->is_traffic_change = true;
8614 }
8615
rtw89_btc_ntfy_wl_sta_iter(void * data,struct ieee80211_sta * sta)8616 static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
8617 {
8618 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
8619 struct rtw89_btc_wl_sta_iter_data *iter_data =
8620 (struct rtw89_btc_wl_sta_iter_data *)data;
8621 struct rtw89_vif_link *rtwvif_link;
8622 struct rtw89_sta_link *rtwsta_link;
8623 unsigned int link_id;
8624
8625 rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
8626 rtwvif_link = rtwsta_link->rtwvif_link;
8627 __rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data);
8628 }
8629 }
8630
8631 #define BTC_NHM_CHK_INTVL 20
8632
rtw89_btc_ntfy_wl_sta(struct rtw89_dev * rtwdev)8633 void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
8634 {
8635 struct rtw89_btc *btc = &rtwdev->btc;
8636 struct rtw89_btc_dm *dm = &btc->dm;
8637 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8638 struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev};
8639 u8 i;
8640
8641 ieee80211_iterate_stations_atomic(rtwdev->hw,
8642 rtw89_btc_ntfy_wl_sta_iter,
8643 &data);
8644
8645 wl->rssi_level = 0;
8646 btc->dm.cnt_notify[BTC_NCNT_WL_STA]++;
8647 for (i = BTC_WL_RSSI_THMAX; i > 0; i--) {
8648 /* set RSSI level 4 ~ 0 if rssi bit map match */
8649 if (data.rssi_map_all & BIT(i - 1)) {
8650 wl->rssi_level = i;
8651 break;
8652 }
8653 }
8654
8655 if (dm->trx_info.wl_rssi != wl->rssi_level)
8656 dm->trx_info.wl_rssi = wl->rssi_level;
8657
8658 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n",
8659 __func__, !!wl->status.map.busy);
8660
8661 _write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy));
8662
8663 if (data.is_traffic_change)
8664 _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
8665 if (data.is_sta_change) {
8666 wl->status.map.busy = data.busy_all;
8667 wl->status.map.traffic_dir = data.dir_all;
8668 _run_coex(rtwdev, BTC_RSN_NTFY_WL_STA);
8669 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >=
8670 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) {
8671 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
8672 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
8673 } else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] <
8674 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) {
8675 btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
8676 btc->dm.cnt_notify[BTC_NCNT_WL_STA];
8677 }
8678 }
8679
rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev * rtwdev,u8 func)8680 static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func)
8681 {
8682 struct rtw89_btc *btc = &rtwdev->btc;
8683 const struct rtw89_btc_ver *ver = btc->ver;
8684
8685 switch (func) {
8686 case BTF_EVNT_RPT:
8687 case BTF_EVNT_BT_INFO:
8688 case BTF_EVNT_BT_SCBD:
8689 case BTF_EVNT_BT_REG:
8690 case BTF_EVNT_CX_RUNINFO:
8691 case BTF_EVNT_BT_PSD:
8692 return func;
8693 case BTF_EVNT_BT_DEV_INFO:
8694 if (ver->fwc2hfunc == 0)
8695 return BTF_EVNT_BUF_OVERFLOW;
8696 else
8697 return BTF_EVNT_BT_DEV_INFO;
8698 case BTF_EVNT_BT_LEAUDIO_INFO:
8699 if (ver->fwc2hfunc == 0)
8700 return BTF_EVNT_C2H_LOOPBACK;
8701 else if (ver->fwc2hfunc == 1)
8702 return BTF_EVNT_BUF_OVERFLOW;
8703 else if (ver->fwc2hfunc == 2)
8704 return func;
8705 else if (ver->fwc2hfunc == 3)
8706 return BTF_EVNT_BUF_OVERFLOW;
8707 else
8708 return BTF_EVNT_MAX;
8709 case BTF_EVNT_BUF_OVERFLOW:
8710 if (ver->fwc2hfunc == 0)
8711 return BTF_EVNT_MAX;
8712 else if (ver->fwc2hfunc == 1)
8713 return BTF_EVNT_C2H_LOOPBACK;
8714 else if (ver->fwc2hfunc == 2)
8715 return func;
8716 else if (ver->fwc2hfunc == 3)
8717 return BTF_EVNT_C2H_LOOPBACK;
8718 else
8719 return BTF_EVNT_MAX;
8720 case BTF_EVNT_C2H_LOOPBACK:
8721 if (ver->fwc2hfunc == 2)
8722 return func;
8723 else if (ver->fwc2hfunc == 3)
8724 return BTF_EVNT_BT_LEAUDIO_INFO;
8725 else
8726 return BTF_EVNT_MAX;
8727 case BTF_EVNT_BT_QUERY_TXPWR:
8728 if (ver->fwc2hfunc == 3)
8729 return func;
8730 else
8731 return BTF_EVNT_MAX;
8732 case BTF_EVNT_MAX:
8733 default:
8734 return BTF_EVNT_MAX;
8735 }
8736 }
8737
rtw89_btc_c2h_handle(struct rtw89_dev * rtwdev,struct sk_buff * skb,u32 len,u8 class,u8 func)8738 void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
8739 u32 len, u8 class, u8 func)
8740 {
8741 struct rtw89_btc *btc = &rtwdev->btc;
8742 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
8743 u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN];
8744
8745 len -= RTW89_C2H_HEADER_LEN;
8746
8747 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8748 "[BTC], %s(): C2H BT len:%d class:%d fun:%d\n",
8749 __func__, len, class, func);
8750
8751 if (class != BTFC_FW_EVENT)
8752 return;
8753
8754 func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func);
8755 pfwinfo->cnt_c2h++;
8756
8757 switch (func) {
8758 case BTF_EVNT_BUF_OVERFLOW:
8759 pfwinfo->event[func]++;
8760 break;
8761 case BTF_EVNT_RPT:
8762 pfwinfo->event[func]++;
8763 /* Don't need rtw89_leave_ps_mode() */
8764 btc_fw_event(rtwdev, func, buf, len);
8765 break;
8766 case BTF_EVNT_BT_INFO:
8767 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8768 "[BTC], handle C2H BT INFO with data %8ph\n", buf);
8769 btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++;
8770 _update_bt_info(rtwdev, buf, len);
8771 break;
8772 case BTF_EVNT_BT_SCBD:
8773 rtw89_debug(rtwdev, RTW89_DBG_BTC,
8774 "[BTC], handle C2H BT SCBD with data %8ph\n", buf);
8775 btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++;
8776 _update_bt_scbd(rtwdev, false);
8777 break;
8778 case BTF_EVNT_BT_PSD:
8779 break;
8780 case BTF_EVNT_BT_REG:
8781 btc->dbg.rb_done = true;
8782 btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf));
8783
8784 break;
8785 case BTF_EVNT_C2H_LOOPBACK:
8786 btc->dbg.rb_done = true;
8787 btc->dbg.rb_val = buf[0];
8788 break;
8789 case BTF_EVNT_CX_RUNINFO:
8790 btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
8791 break;
8792 case BTF_EVNT_BT_QUERY_TXPWR:
8793 btc->cx.cnt_bt[BTC_BCNT_BTTXPWR_UPDATE]++;
8794 _update_bt_txpwr_info(rtwdev, buf, len);
8795 }
8796 }
8797
8798 #define BTC_CX_FW_OFFLOAD 0
8799
_show_cx_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)8800 static int _show_cx_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
8801 {
8802 union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo;
8803 const struct rtw89_chip_info *chip = rtwdev->chip;
8804 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
8805 struct rtw89_hal *hal = &rtwdev->hal;
8806 struct rtw89_btc *btc = &rtwdev->btc;
8807 struct rtw89_btc_dm *dm = &btc->dm;
8808 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
8809 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8810 u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
8811 u8 cv, rfe, iso, ant_num, ant_single_pos;
8812 char *p = buf, *end = buf + bufsz;
8813
8814 if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
8815 return 0;
8816
8817 p += scnprintf(p, end - p,
8818 "\n========== [BTC COEX INFO (%s)] ==========\n",
8819 chip_id_str(chip->chip_id));
8820
8821 ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION);
8822 ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION);
8823 ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION);
8824 id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION);
8825 p += scnprintf(p, end - p, " %-15s : Coex:%d.%d.%d(branch:%d), ",
8826 "[coex_version]", ver_main, ver_sub, ver_hotfix,
8827 id_branch);
8828
8829 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
8830 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex);
8831 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex);
8832 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex);
8833 p += scnprintf(p, end - p, "WL_FW_coex:%d.%d.%d(branch:%d)",
8834 ver_main, ver_sub, ver_hotfix, id_branch);
8835
8836 ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired);
8837 ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired);
8838 ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
8839 p += scnprintf(p, end - p, "(%s, desired:%d.%d.%d), ",
8840 (wl->ver_info.fw_coex >= chip->wlcx_desired ?
8841 "Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
8842
8843 p += scnprintf(p, end - p, "BT_FW_coex:%d(%s, desired:%d)\n",
8844 bt->ver_info.fw_coex,
8845 (bt->ver_info.fw_coex >= ver->bt_desired ?
8846 "Match" : "Mismatch"), ver->bt_desired);
8847
8848 if (bt->enable.now && bt->ver_info.fw == 0)
8849 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true);
8850 else
8851 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false);
8852
8853 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw);
8854 ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw);
8855 ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw);
8856 id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw);
8857 p += scnprintf(p, end - p,
8858 " %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n",
8859 "[sub_module]",
8860 ver_main, ver_sub, ver_hotfix, id_branch,
8861 bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM");
8862
8863 if (ver->fcxinit == 7) {
8864 cv = md->md_v7.kt_ver;
8865 rfe = md->md_v7.rfe_type;
8866 iso = md->md_v7.ant.isolation;
8867 ant_num = md->md_v7.ant.num;
8868 ant_single_pos = md->md_v7.ant.single_pos;
8869 } else {
8870 cv = md->md.cv;
8871 rfe = md->md.rfe_type;
8872 iso = md->md.ant.isolation;
8873 ant_num = md->md.ant.num;
8874 ant_single_pos = md->md.ant.single_pos;
8875 }
8876
8877 p += scnprintf(p, end - p,
8878 " %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s",
8879 "[hw_info]", cv, rfe, iso, ant_num,
8880 ant_num > 1 ? "" :
8881 ant_single_pos ? "1Ant_Pos:S1, " : "1Ant_Pos:S0, ");
8882
8883 p += scnprintf(p, end - p,
8884 "3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n",
8885 btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss,
8886 hal->rx_nss);
8887
8888 return p - buf;
8889 }
8890
_show_wl_role_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)8891 static int _show_wl_role_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
8892 {
8893 struct rtw89_btc *btc = &rtwdev->btc;
8894 struct rtw89_btc_wl_link_info *plink = NULL;
8895 struct rtw89_traffic_stats *t;
8896 char *p = buf, *end = buf + bufsz;
8897 u8 i, j;
8898
8899 for (i = 0; i < btc->ver->max_role_num; i++) {
8900 for (j = 0; j < RTW89_MAC_NUM; j++) {
8901 if (btc->ver->fwlrole == 8)
8902 plink = &btc->cx.wl.rlink_info[i][j];
8903 else
8904 plink = &btc->cx.wl.link_info[i];
8905
8906 if (!plink->active)
8907 continue;
8908
8909 p += scnprintf(p, end - p,
8910 " [port_%d] : role=%d(phy-%d), connect=%s(client_cnt=%d), mode=%d, center_ch=%d, bw=%d",
8911 plink->pid, plink->role, plink->phy,
8912 id_to_mlme_state(plink->connected),
8913 plink->client_cnt - 1, plink->mode,
8914 plink->ch, plink->bw);
8915
8916 if (plink->connected == MLME_NO_LINK)
8917 continue;
8918
8919 p += scnprintf(p, end - p,
8920 ", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n",
8921 plink->mac_id, plink->tx_time, plink->tx_retry);
8922
8923 p += scnprintf(p, end - p,
8924 " [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
8925 plink->pid, 110 - plink->stat.rssi,
8926 plink->stat.rssi, plink->busy,
8927 plink->dir == RTW89_TFC_UL ? "UL" : "DL");
8928
8929 t = &plink->stat.traffic;
8930
8931 p += scnprintf(p, end - p,
8932 "tx[rate:%d/busy_level:%d], ",
8933 t->tx_rate, t->tx_tfc_lv);
8934
8935 p += scnprintf(p, end - p,
8936 "rx[rate:%d/busy_level:%d/drop:%d]\n",
8937 t->rx_rate,
8938 t->rx_tfc_lv, plink->rx_rate_drop_cnt);
8939 }
8940 }
8941 return p - buf;
8942 }
8943
_show_wl_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)8944 static int _show_wl_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
8945 {
8946 struct rtw89_btc *btc = &rtwdev->btc;
8947 const struct rtw89_btc_ver *ver = btc->ver;
8948 struct rtw89_btc_cx *cx = &btc->cx;
8949 struct rtw89_btc_wl_info *wl = &cx->wl;
8950 struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
8951 struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
8952 struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
8953 struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
8954 struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
8955 char *p = buf, *end = buf + bufsz;
8956 u8 mode;
8957
8958 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
8959 return 0;
8960
8961 p += scnprintf(p, end - p, "========== [WL Status] ==========\n");
8962
8963 if (ver->fwlrole == 0)
8964 mode = wl_rinfo->link_mode;
8965 else if (ver->fwlrole == 1)
8966 mode = wl_rinfo_v1->link_mode;
8967 else if (ver->fwlrole == 2)
8968 mode = wl_rinfo_v2->link_mode;
8969 else if (ver->fwlrole == 7)
8970 mode = wl_rinfo_v7->link_mode;
8971 else if (ver->fwlrole == 8)
8972 mode = wl_rinfo_v8->link_mode;
8973 else
8974 goto out;
8975
8976 p += scnprintf(p, end - p, " %-15s : link_mode:%s, ", "[status]",
8977 id_to_linkmode(mode));
8978
8979 p += scnprintf(p, end - p,
8980 "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ",
8981 wl->status.map.rf_off, wl->status.map.lps,
8982 wl->status.map.scan ? "Y" : "N",
8983 wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
8984
8985 p += scnprintf(p, end - p,
8986 "connecting:%s, roam:%s, 4way:%s, init_ok:%s\n",
8987 wl->status.map.connecting ? "Y" : "N",
8988 wl->status.map.roaming ? "Y" : "N",
8989 wl->status.map._4way ? "Y" : "N",
8990 wl->status.map.init_ok ? "Y" : "N");
8991
8992 p += _show_wl_role_info(rtwdev, p, end - p);
8993
8994 out:
8995 return p - buf;
8996 }
8997
8998 enum btc_bt_a2dp_type {
8999 BTC_A2DP_LEGACY = 0,
9000 BTC_A2DP_TWS_SNIFF = 1,
9001 BTC_A2DP_TWS_RELAY = 2,
9002 };
9003
_show_bt_profile_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9004 static int _show_bt_profile_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9005 {
9006 struct rtw89_btc *btc = &rtwdev->btc;
9007 struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
9008 struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
9009 struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
9010 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
9011 struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
9012 char *p = buf, *end = buf + bufsz;
9013
9014 if (hfp.exist) {
9015 p += scnprintf(p, end - p,
9016 " %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
9017 "[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"),
9018 bt_linfo->sut_pwr_level[0],
9019 bt_linfo->golden_rx_shift[0]);
9020 }
9021
9022 if (hid.exist) {
9023 p += scnprintf(p, end - p,
9024 "\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n",
9025 "[HID]",
9026 hid.type & BTC_HID_218 ? "2/18," : "",
9027 hid.type & BTC_HID_418 ? "4/18," : "",
9028 hid.type & BTC_HID_BLE ? "BLE," : "",
9029 hid.type & BTC_HID_RCU ? "RCU," : "",
9030 hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "",
9031 hid.pair_cnt, bt_linfo->sut_pwr_level[1],
9032 bt_linfo->golden_rx_shift[1]);
9033 }
9034
9035 if (a2dp.exist) {
9036 p += scnprintf(p, end - p,
9037 " %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
9038 "[A2DP]",
9039 a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS",
9040 a2dp.bitpool, a2dp.flush_time);
9041
9042 p += scnprintf(p, end - p,
9043 "vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n",
9044 a2dp.vendor_id, a2dp.device_name,
9045 bt_linfo->sut_pwr_level[2],
9046 bt_linfo->golden_rx_shift[2]);
9047 }
9048
9049 if (pan.exist) {
9050 p += scnprintf(p, end - p,
9051 " %-15s : sut_pwr:%d, golden-rx:%d\n",
9052 "[PAN]",
9053 bt_linfo->sut_pwr_level[3],
9054 bt_linfo->golden_rx_shift[3]);
9055 }
9056
9057 return p - buf;
9058 }
9059
_show_bt_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9060 static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9061 {
9062 struct rtw89_btc *btc = &rtwdev->btc;
9063 const struct rtw89_btc_ver *ver = btc->ver;
9064 struct rtw89_btc_cx *cx = &btc->cx;
9065 struct rtw89_btc_bt_info *bt = &cx->bt;
9066 struct rtw89_btc_wl_info *wl = &cx->wl;
9067 u32 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
9068 struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
9069 union rtw89_btc_module_info *md = &btc->mdinfo;
9070 s8 br_dbm = bt->link_info.bt_txpwr_desc.br_dbm;
9071 s8 le_dbm = bt->link_info.bt_txpwr_desc.le_dbm;
9072 char *p = buf, *end = buf + bufsz;
9073 u8 *afh = bt_linfo->afh_map;
9074 u8 *afh_le = bt_linfo->afh_map_le;
9075 u8 bt_pos;
9076
9077 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
9078 return 0;
9079
9080 if (ver->fcxinit == 7)
9081 bt_pos = md->md_v7.bt_pos;
9082 else
9083 bt_pos = md->md.bt_pos;
9084
9085 p += scnprintf(p, end - p, "========== [BT Status] ==========\n");
9086
9087 p += scnprintf(p, end - p,
9088 " %-15s : enable:%s, btg:%s%s, connect:%s, ",
9089 "[status]", bt->enable.now ? "Y" : "N",
9090 bt->btg_type ? "Y" : "N",
9091 (bt->enable.now && (bt->btg_type != bt_pos) ?
9092 "(efuse-mismatch!!)" : ""),
9093 (bt_linfo->status.map.connect ? "Y" : "N"));
9094
9095 p += scnprintf(p, end - p,
9096 "igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n",
9097 bt->igno_wl ? "Y" : "N",
9098 bt->mbx_avl ? "Y" : "N", bt->rfk_info.val);
9099
9100 p += scnprintf(p, end - p, " %-15s : profile:%s%s%s%s%s ",
9101 "[profile]",
9102 (bt_linfo->profile_cnt.now == 0) ? "None," : "",
9103 bt_linfo->hfp_desc.exist ? "HFP," : "",
9104 bt_linfo->hid_desc.exist ? "HID," : "",
9105 bt_linfo->a2dp_desc.exist ?
9106 (bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "",
9107 bt_linfo->pan_desc.exist ? "PAN," : "");
9108
9109 p += scnprintf(p, end - p,
9110 "multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n",
9111 bt_linfo->multi_link.now ? "Y" : "N",
9112 bt_linfo->slave_role ? "Slave" : "Master",
9113 bt_linfo->status.map.ble_connect ? "Y" : "N",
9114 bt_linfo->cqddr ? "Y" : "N",
9115 bt_linfo->a2dp_desc.active ? "Y" : "N",
9116 bt_linfo->pan_desc.active ? "Y" : "N");
9117
9118 p += scnprintf(p, end - p,
9119 " %-15s : rssi:%ddBm(lvl:%d), tx_rate:%dM, %s%s%s",
9120 "[link]", bt_linfo->rssi - 100,
9121 bt->rssi_level,
9122 bt_linfo->tx_3m ? 3 : 2,
9123 bt_linfo->status.map.inq_pag ? " inq-page!!" : "",
9124 bt_linfo->status.map.acl_busy ? " acl_busy!!" : "",
9125 bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : "");
9126
9127 p += scnprintf(p, end - p,
9128 "%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
9129 bt_linfo->relink.now ? " ReLink!!" : "",
9130 afh[0], afh[1], afh[2], afh[3], afh[4],
9131 afh[5], afh[6], afh[7], afh[8], afh[9]);
9132
9133 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
9134 p += scnprintf(p, end - p,
9135 "LE[%02x%02x_%02x_%02x%02x]",
9136 afh_le[0], afh_le[1], afh_le[2],
9137 afh_le[3], afh_le[4]);
9138
9139 p += scnprintf(p, end - p, "wl_ch_map[en:%d/ch:%d/bw:%d]\n",
9140 wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw);
9141
9142 p += scnprintf(p, end - p,
9143 " %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
9144 "[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY],
9145 cx->cnt_bt[BTC_BCNT_RELINK],
9146 cx->cnt_bt[BTC_BCNT_RATECHG],
9147 cx->cnt_bt[BTC_BCNT_REINIT],
9148 cx->cnt_bt[BTC_BCNT_REENABLE]);
9149
9150 p += scnprintf(p, end - p,
9151 "role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n",
9152 cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH],
9153 cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ],
9154 cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]);
9155
9156 p += _show_bt_profile_info(rtwdev, p, end - p);
9157
9158 p += scnprintf(p, end - p,
9159 " %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n",
9160 "[bt_info]", bt->raw_info[2], bt->raw_info[3],
9161 bt->raw_info[4], bt->raw_info[5], bt->raw_info[6],
9162 bt->raw_info[7],
9163 bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
9164 cx->cnt_bt[BTC_BCNT_INFOUPDATE],
9165 cx->cnt_bt[BTC_BCNT_INFOSAME]);
9166
9167 p += scnprintf(p, end - p,
9168 " %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)",
9169 "[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX],
9170 cx->cnt_bt[BTC_BCNT_HIPRI_TX],
9171 cx->cnt_bt[BTC_BCNT_LOPRI_RX],
9172 cx->cnt_bt[BTC_BCNT_LOPRI_TX],
9173 cx->cnt_bt[BTC_BCNT_POLUT]);
9174
9175 if (!bt->scan_info_update) {
9176 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, true);
9177 p += scnprintf(p, end - p, "\n");
9178 } else {
9179 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, false);
9180 if (ver->fcxbtscan == 1) {
9181 p += scnprintf(p, end - p,
9182 "(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)",
9183 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win),
9184 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl),
9185 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win),
9186 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl),
9187 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win),
9188 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl),
9189 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win),
9190 le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl));
9191 } else if (ver->fcxbtscan == 2) {
9192 p += scnprintf(p, end - p,
9193 "(BG:%d-%d/INIT:%d-%d/LE:%d-%d)",
9194 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win),
9195 le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl),
9196 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win),
9197 le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl),
9198 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win),
9199 le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl));
9200 }
9201 p += scnprintf(p, end - p, "\n");
9202 }
9203
9204 if (ver_main >= 9 && bt_linfo->profile_cnt.now)
9205 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_TX_PWR_LVL, true);
9206 else
9207 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_TX_PWR_LVL, false);
9208
9209 if (cx->cnt_bt[BTC_BCNT_BTTXPWR_UPDATE]) {
9210 p += scnprintf(p, end - p,
9211 " %-15s : br_index:0x%x, le_index:0x%x",
9212 "[bt_txpwr_lvl]",
9213 bt->link_info.bt_txpwr_desc.br_gain_index,
9214 bt->link_info.bt_txpwr_desc.le_gain_index);
9215 p += scnprintf(p, end - p, ", br_dbm:%d dBm", br_dbm);
9216 p += scnprintf(p, end - p, ", le_dbm:%d dBm", le_dbm);
9217 } else {
9218 p += scnprintf(p, end - p,
9219 " %-15s : br_index:NA, le_index:NA, br_dbm:%d dBm[def], le_dbm:%d dBm[def]",
9220 "[bt_txpwr_lvl]",
9221 bt->link_info.bt_txpwr_desc.br_dbm,
9222 bt->link_info.bt_txpwr_desc.le_dbm);
9223 }
9224 p += scnprintf(p, end - p, "\n");
9225
9226 if (bt_linfo->profile_cnt.now || bt_linfo->status.map.ble_connect)
9227 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, true);
9228 else
9229 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, false);
9230
9231 if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
9232 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, true);
9233 else
9234 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, false);
9235
9236 if (bt_linfo->a2dp_desc.exist &&
9237 (bt_linfo->a2dp_desc.flush_time == 0 ||
9238 bt_linfo->a2dp_desc.vendor_id == 0 ||
9239 bt_linfo->a2dp_desc.play_latency == 1))
9240 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, true);
9241 else
9242 rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, false);
9243
9244 return p - buf;
9245 }
9246
9247 #define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e
9248 #define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
9249 #define CASE_BTC_POLICY_STR(e) \
9250 case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
9251 #define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e
9252 #define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e
9253 #define CASE_BTC_INIT(e) case BTC_MODE_## e: return #e
9254 #define CASE_BTC_ANTPATH_STR(e) case BTC_ANT_##e: return #e
9255 #define CASE_BTC_POLUT_STR(e) case BTC_PLT_## e: return #e
9256 #define CASE_BTC_REGTYPE_STR(e) case REG_## e: return #e
9257 #define CASE_BTC_GDBG_STR(e) case BTC_DBG_## e: return #e
9258
id_to_polut(u32 id)9259 static const char *id_to_polut(u32 id)
9260 {
9261 switch (id) {
9262 CASE_BTC_POLUT_STR(NONE);
9263 CASE_BTC_POLUT_STR(GNT_BT_TX);
9264 CASE_BTC_POLUT_STR(GNT_BT_RX);
9265 CASE_BTC_POLUT_STR(GNT_WL);
9266 CASE_BTC_POLUT_STR(BT);
9267 CASE_BTC_POLUT_STR(ALL);
9268 default:
9269 return "unknown";
9270 }
9271 }
9272
id_to_regtype(u32 id)9273 static const char *id_to_regtype(u32 id)
9274 {
9275 switch (id) {
9276 CASE_BTC_REGTYPE_STR(MAC);
9277 CASE_BTC_REGTYPE_STR(BB);
9278 CASE_BTC_REGTYPE_STR(RF);
9279 CASE_BTC_REGTYPE_STR(BT_RF);
9280 CASE_BTC_REGTYPE_STR(BT_MODEM);
9281 CASE_BTC_REGTYPE_STR(BT_BLUEWIZE);
9282 CASE_BTC_REGTYPE_STR(BT_VENDOR);
9283 CASE_BTC_REGTYPE_STR(BT_LE);
9284 default:
9285 return "unknown";
9286 }
9287 }
9288
id_to_gdbg(u32 id)9289 static const char *id_to_gdbg(u32 id)
9290 {
9291 switch (id) {
9292 CASE_BTC_GDBG_STR(GNT_BT);
9293 CASE_BTC_GDBG_STR(GNT_WL);
9294 CASE_BTC_GDBG_STR(BCN_EARLY);
9295 CASE_BTC_GDBG_STR(WL_NULL0);
9296 CASE_BTC_GDBG_STR(WL_NULL1);
9297 CASE_BTC_GDBG_STR(WL_RXISR);
9298 CASE_BTC_GDBG_STR(TDMA_ENTRY);
9299 CASE_BTC_GDBG_STR(A2DP_EMPTY);
9300 CASE_BTC_GDBG_STR(BT_RETRY);
9301 CASE_BTC_GDBG_STR(BT_RELINK);
9302 CASE_BTC_GDBG_STR(SLOT_WL);
9303 CASE_BTC_GDBG_STR(SLOT_BT);
9304 CASE_BTC_GDBG_STR(WL_ERR);
9305 CASE_BTC_GDBG_STR(WL_OK);
9306 CASE_BTC_GDBG_STR(SLOT_B2W);
9307 CASE_BTC_GDBG_STR(SLOT_W1);
9308 CASE_BTC_GDBG_STR(SLOT_W2);
9309 CASE_BTC_GDBG_STR(SLOT_W2B);
9310 CASE_BTC_GDBG_STR(SLOT_B1);
9311 CASE_BTC_GDBG_STR(SLOT_B2);
9312 CASE_BTC_GDBG_STR(SLOT_B3);
9313 CASE_BTC_GDBG_STR(SLOT_B4);
9314 CASE_BTC_GDBG_STR(SLOT_LK);
9315 CASE_BTC_GDBG_STR(SLOT_E2G);
9316 CASE_BTC_GDBG_STR(SLOT_E5G);
9317 CASE_BTC_GDBG_STR(SLOT_EBT);
9318 CASE_BTC_GDBG_STR(SLOT_WLK);
9319 CASE_BTC_GDBG_STR(SLOT_B1FDD);
9320 CASE_BTC_GDBG_STR(BT_CHANGE);
9321 CASE_BTC_GDBG_STR(WL_CCA);
9322 CASE_BTC_GDBG_STR(BT_LEAUDIO);
9323 CASE_BTC_GDBG_STR(USER_DEF);
9324 default:
9325 return "unknown";
9326 }
9327 }
9328
steps_to_str(u16 step)9329 static const char *steps_to_str(u16 step)
9330 {
9331 switch (step) {
9332 CASE_BTC_RSN_STR(NONE);
9333 CASE_BTC_RSN_STR(NTFY_INIT);
9334 CASE_BTC_RSN_STR(NTFY_SWBAND);
9335 CASE_BTC_RSN_STR(NTFY_WL_STA);
9336 CASE_BTC_RSN_STR(NTFY_RADIO_STATE);
9337 CASE_BTC_RSN_STR(UPDATE_BT_SCBD);
9338 CASE_BTC_RSN_STR(NTFY_WL_RFK);
9339 CASE_BTC_RSN_STR(UPDATE_BT_INFO);
9340 CASE_BTC_RSN_STR(NTFY_SCAN_START);
9341 CASE_BTC_RSN_STR(NTFY_SCAN_FINISH);
9342 CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET);
9343 CASE_BTC_RSN_STR(NTFY_POWEROFF);
9344 CASE_BTC_RSN_STR(NTFY_ROLE_INFO);
9345 CASE_BTC_RSN_STR(CMD_SET_COEX);
9346 CASE_BTC_RSN_STR(ACT1_WORK);
9347 CASE_BTC_RSN_STR(BT_DEVINFO_WORK);
9348 CASE_BTC_RSN_STR(RFK_CHK_WORK);
9349
9350 CASE_BTC_ACT_STR(NONE);
9351 CASE_BTC_ACT_STR(WL_ONLY);
9352 CASE_BTC_ACT_STR(WL_5G);
9353 CASE_BTC_ACT_STR(WL_OTHER);
9354 CASE_BTC_ACT_STR(WL_IDLE);
9355 CASE_BTC_ACT_STR(WL_NC);
9356 CASE_BTC_ACT_STR(WL_RFK);
9357 CASE_BTC_ACT_STR(WL_INIT);
9358 CASE_BTC_ACT_STR(WL_OFF);
9359 CASE_BTC_ACT_STR(FREERUN);
9360 CASE_BTC_ACT_STR(BT_WHQL);
9361 CASE_BTC_ACT_STR(BT_RFK);
9362 CASE_BTC_ACT_STR(BT_OFF);
9363 CASE_BTC_ACT_STR(BT_IDLE);
9364 CASE_BTC_ACT_STR(BT_HFP);
9365 CASE_BTC_ACT_STR(BT_HID);
9366 CASE_BTC_ACT_STR(BT_A2DP);
9367 CASE_BTC_ACT_STR(BT_A2DPSINK);
9368 CASE_BTC_ACT_STR(BT_PAN);
9369 CASE_BTC_ACT_STR(BT_A2DP_HID);
9370 CASE_BTC_ACT_STR(BT_A2DP_PAN);
9371 CASE_BTC_ACT_STR(BT_PAN_HID);
9372 CASE_BTC_ACT_STR(BT_A2DP_PAN_HID);
9373 CASE_BTC_ACT_STR(WL_25G_MCC);
9374 CASE_BTC_ACT_STR(WL_2G_MCC);
9375 CASE_BTC_ACT_STR(WL_2G_SCC);
9376 CASE_BTC_ACT_STR(WL_2G_AP);
9377 CASE_BTC_ACT_STR(WL_2G_GO);
9378 CASE_BTC_ACT_STR(WL_2G_GC);
9379 CASE_BTC_ACT_STR(WL_2G_NAN);
9380
9381 CASE_BTC_POLICY_STR(OFF_BT);
9382 CASE_BTC_POLICY_STR(OFF_WL);
9383 CASE_BTC_POLICY_STR(OFF_EQ0);
9384 CASE_BTC_POLICY_STR(OFF_EQ1);
9385 CASE_BTC_POLICY_STR(OFF_EQ2);
9386 CASE_BTC_POLICY_STR(OFF_EQ3);
9387 CASE_BTC_POLICY_STR(OFF_EQ4);
9388 CASE_BTC_POLICY_STR(OFF_EQ5);
9389 CASE_BTC_POLICY_STR(OFF_BWB0);
9390 CASE_BTC_POLICY_STR(OFF_BWB1);
9391 CASE_BTC_POLICY_STR(OFF_BWB2);
9392 CASE_BTC_POLICY_STR(OFF_BWB3);
9393 CASE_BTC_POLICY_STR(OFF_WL2);
9394 CASE_BTC_POLICY_STR(OFFB_BWB0);
9395 CASE_BTC_POLICY_STR(OFFE_DEF);
9396 CASE_BTC_POLICY_STR(OFFE_DEF2);
9397 CASE_BTC_POLICY_STR(OFFE_2GBWISOB);
9398 CASE_BTC_POLICY_STR(OFFE_2GISOB);
9399 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB);
9400 CASE_BTC_POLICY_STR(OFFE_WL);
9401 CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2);
9402 CASE_BTC_POLICY_STR(FIX_TD3030);
9403 CASE_BTC_POLICY_STR(FIX_TD5050);
9404 CASE_BTC_POLICY_STR(FIX_TD2030);
9405 CASE_BTC_POLICY_STR(FIX_TD4010);
9406 CASE_BTC_POLICY_STR(FIX_TD7010);
9407 CASE_BTC_POLICY_STR(FIX_TD2060);
9408 CASE_BTC_POLICY_STR(FIX_TD3060);
9409 CASE_BTC_POLICY_STR(FIX_TD2080);
9410 CASE_BTC_POLICY_STR(FIX_TDW1B1);
9411 CASE_BTC_POLICY_STR(FIX_TD4010ISO);
9412 CASE_BTC_POLICY_STR(FIX_TD4010ISO_DL);
9413 CASE_BTC_POLICY_STR(FIX_TD4010ISO_UL);
9414 CASE_BTC_POLICY_STR(PFIX_TD3030);
9415 CASE_BTC_POLICY_STR(PFIX_TD5050);
9416 CASE_BTC_POLICY_STR(PFIX_TD2030);
9417 CASE_BTC_POLICY_STR(PFIX_TD2060);
9418 CASE_BTC_POLICY_STR(PFIX_TD3070);
9419 CASE_BTC_POLICY_STR(PFIX_TD2080);
9420 CASE_BTC_POLICY_STR(PFIX_TDW1B1);
9421 CASE_BTC_POLICY_STR(AUTO_TD50B1);
9422 CASE_BTC_POLICY_STR(AUTO_TD60B1);
9423 CASE_BTC_POLICY_STR(AUTO_TD20B1);
9424 CASE_BTC_POLICY_STR(AUTO_TDW1B1);
9425 CASE_BTC_POLICY_STR(PAUTO_TD50B1);
9426 CASE_BTC_POLICY_STR(PAUTO_TD60B1);
9427 CASE_BTC_POLICY_STR(PAUTO_TD20B1);
9428 CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
9429 CASE_BTC_POLICY_STR(AUTO2_TD3050);
9430 CASE_BTC_POLICY_STR(AUTO2_TD3070);
9431 CASE_BTC_POLICY_STR(AUTO2_TD5050);
9432 CASE_BTC_POLICY_STR(AUTO2_TD6060);
9433 CASE_BTC_POLICY_STR(AUTO2_TD2080);
9434 CASE_BTC_POLICY_STR(AUTO2_TDW1B4);
9435 CASE_BTC_POLICY_STR(PAUTO2_TD3050);
9436 CASE_BTC_POLICY_STR(PAUTO2_TD3070);
9437 CASE_BTC_POLICY_STR(PAUTO2_TD5050);
9438 CASE_BTC_POLICY_STR(PAUTO2_TD6060);
9439 CASE_BTC_POLICY_STR(PAUTO2_TD2080);
9440 CASE_BTC_POLICY_STR(PAUTO2_TDW1B4);
9441 default:
9442 return "unknown step";
9443 }
9444 }
9445
id_to_slot(u32 id)9446 static const char *id_to_slot(u32 id)
9447 {
9448 switch (id) {
9449 CASE_BTC_SLOT_STR(OFF);
9450 CASE_BTC_SLOT_STR(B2W);
9451 CASE_BTC_SLOT_STR(W1);
9452 CASE_BTC_SLOT_STR(W2);
9453 CASE_BTC_SLOT_STR(W2B);
9454 CASE_BTC_SLOT_STR(B1);
9455 CASE_BTC_SLOT_STR(B2);
9456 CASE_BTC_SLOT_STR(B3);
9457 CASE_BTC_SLOT_STR(B4);
9458 CASE_BTC_SLOT_STR(LK);
9459 CASE_BTC_SLOT_STR(BLK);
9460 CASE_BTC_SLOT_STR(E2G);
9461 CASE_BTC_SLOT_STR(E5G);
9462 CASE_BTC_SLOT_STR(EBT);
9463 CASE_BTC_SLOT_STR(ENULL);
9464 CASE_BTC_SLOT_STR(WLK);
9465 CASE_BTC_SLOT_STR(W1FDD);
9466 CASE_BTC_SLOT_STR(B1FDD);
9467 default:
9468 return "unknown";
9469 }
9470 }
9471
id_to_evt(u32 id)9472 static const char *id_to_evt(u32 id)
9473 {
9474 switch (id) {
9475 CASE_BTC_EVT_STR(TDMA_ENTRY);
9476 CASE_BTC_EVT_STR(WL_TMR);
9477 CASE_BTC_EVT_STR(B1_TMR);
9478 CASE_BTC_EVT_STR(B2_TMR);
9479 CASE_BTC_EVT_STR(B3_TMR);
9480 CASE_BTC_EVT_STR(B4_TMR);
9481 CASE_BTC_EVT_STR(W2B_TMR);
9482 CASE_BTC_EVT_STR(B2W_TMR);
9483 CASE_BTC_EVT_STR(BCN_EARLY);
9484 CASE_BTC_EVT_STR(A2DP_EMPTY);
9485 CASE_BTC_EVT_STR(LK_END);
9486 CASE_BTC_EVT_STR(RX_ISR);
9487 CASE_BTC_EVT_STR(RX_FC0);
9488 CASE_BTC_EVT_STR(RX_FC1);
9489 CASE_BTC_EVT_STR(BT_RELINK);
9490 CASE_BTC_EVT_STR(BT_RETRY);
9491 CASE_BTC_EVT_STR(E2G);
9492 CASE_BTC_EVT_STR(E5G);
9493 CASE_BTC_EVT_STR(EBT);
9494 CASE_BTC_EVT_STR(ENULL);
9495 CASE_BTC_EVT_STR(DRV_WLK);
9496 CASE_BTC_EVT_STR(BCN_OK);
9497 CASE_BTC_EVT_STR(BT_CHANGE);
9498 CASE_BTC_EVT_STR(EBT_EXTEND);
9499 CASE_BTC_EVT_STR(E2G_NULL1);
9500 CASE_BTC_EVT_STR(B1FDD_TMR);
9501 default:
9502 return "unknown";
9503 }
9504 }
9505
id_to_mode(u8 id)9506 static const char *id_to_mode(u8 id)
9507 {
9508 switch (id) {
9509 CASE_BTC_INIT(NORMAL);
9510 CASE_BTC_INIT(WL);
9511 CASE_BTC_INIT(BT);
9512 CASE_BTC_INIT(WLOFF);
9513 default:
9514 return "unknown";
9515 }
9516 }
9517
id_to_ant(u32 id)9518 static const char *id_to_ant(u32 id)
9519 {
9520 switch (id) {
9521 CASE_BTC_ANTPATH_STR(WPOWERON);
9522 CASE_BTC_ANTPATH_STR(WINIT);
9523 CASE_BTC_ANTPATH_STR(WONLY);
9524 CASE_BTC_ANTPATH_STR(WOFF);
9525 CASE_BTC_ANTPATH_STR(W2G);
9526 CASE_BTC_ANTPATH_STR(W5G);
9527 CASE_BTC_ANTPATH_STR(W25G);
9528 CASE_BTC_ANTPATH_STR(FREERUN);
9529 CASE_BTC_ANTPATH_STR(WRFK);
9530 CASE_BTC_ANTPATH_STR(BRFK);
9531 CASE_BTC_ANTPATH_STR(MAX);
9532 default:
9533 return "unknown";
9534 }
9535 }
9536
9537 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)9538 int scnprintf_segment(char *buf, size_t bufsz, const char *prefix, const u16 *data,
9539 u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
9540 {
9541 char *p = buf, *end = buf + bufsz;
9542 u8 cur_index;
9543 u8 i;
9544
9545 for (i = 0; i < len ; i++) {
9546 if ((i % seg_len) == 0)
9547 p += scnprintf(p, end - p, " %-15s : ", prefix);
9548 cur_index = (start_idx + i) % ring_len;
9549 if (i % 3 == 0)
9550 p += scnprintf(p, end - p, "-> %-20s",
9551 steps_to_str(*(data + cur_index)));
9552 else if (i % 3 == 1)
9553 p += scnprintf(p, end - p, "-> %-15s",
9554 steps_to_str(*(data + cur_index)));
9555 else
9556 p += scnprintf(p, end - p, "-> %-13s",
9557 steps_to_str(*(data + cur_index)));
9558 if (i == (len - 1) || (i % seg_len) == (seg_len - 1))
9559 p += scnprintf(p, end - p, "\n");
9560 }
9561
9562 return p - buf;
9563 }
9564
_show_dm_step(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9565 static int _show_dm_step(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9566 {
9567 struct rtw89_btc *btc = &rtwdev->btc;
9568 struct rtw89_btc_dm *dm = &btc->dm;
9569 char *p = buf, *end = buf + bufsz;
9570 u8 start_idx;
9571 u8 len;
9572
9573 len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos;
9574 start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0;
9575
9576 p += scnprintf_segment(p, end - p, "[dm_steps]", dm->dm_step.step, len,
9577 6, start_idx, ARRAY_SIZE(dm->dm_step.step));
9578
9579 return p - buf;
9580 }
9581
_show_dm_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9582 static int _show_dm_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9583 {
9584 struct rtw89_btc *btc = &rtwdev->btc;
9585 const struct rtw89_btc_ver *ver = btc->ver;
9586 struct rtw89_btc_dm *dm = &btc->dm;
9587 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9588 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
9589 char *p = buf, *end = buf + bufsz;
9590 u8 igno_bt;
9591
9592 if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
9593 return 0;
9594
9595 p += scnprintf(p, end - p,
9596 "========== [Mechanism Status %s] ==========\n",
9597 (btc->manual_ctrl ? "(Manual)" : "(Auto)"));
9598
9599 p += scnprintf(p, end - p,
9600 " %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, init_mode:%s, run_cnt:%d\n",
9601 "[status]",
9602 btc->ant_type == BTC_ANT_SHARED ? "shared" : "dedicated",
9603 steps_to_str(dm->run_reason),
9604 steps_to_str(dm->run_action | BTC_ACT_EXT_BIT),
9605 id_to_ant(FIELD_GET(GENMASK(7, 0), dm->set_ant_path)),
9606 id_to_mode(wl->coex_mode),
9607 dm->cnt_dm[BTC_DCNT_RUN]);
9608
9609 p += _show_dm_step(rtwdev, p, end - p);
9610
9611 if (ver->fcxctrl == 7)
9612 igno_bt = btc->ctrl.ctrl_v7.igno_bt;
9613 else
9614 igno_bt = btc->ctrl.ctrl.igno_bt;
9615
9616 p += scnprintf(p, end - p,
9617 " %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ",
9618 "[dm_flag]", dm->wl_only, dm->bt_only, igno_bt,
9619 dm->freerun, btc->lps, dm->wl_mimo_ps);
9620
9621 p += scnprintf(p, end - p, "leak_ap:%d, fw_offload:%s%s\n",
9622 dm->leak_ap,
9623 (BTC_CX_FW_OFFLOAD ? "Y" : "N"),
9624 (dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
9625 "" : "(Mismatch!!)"));
9626
9627 if (dm->rf_trx_para.wl_tx_power == 0xff)
9628 p += scnprintf(p, end - p,
9629 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ",
9630 "[trx_ctrl]", wl->rssi_level,
9631 dm->trx_para_level);
9632
9633 else
9634 p += scnprintf(p, end - p,
9635 " %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ",
9636 "[trx_ctrl]", wl->rssi_level,
9637 dm->trx_para_level,
9638 dm->rf_trx_para.wl_tx_power);
9639
9640 p += scnprintf(p, end - p,
9641 "wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n",
9642 dm->rf_trx_para.wl_rx_gain,
9643 dm->rf_trx_para.bt_tx_power,
9644 dm->rf_trx_para.bt_rx_gain,
9645 (bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx);
9646
9647 p += scnprintf(p, end - p,
9648 " %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n",
9649 "[dm_ctrl]", dm->wl_tx_limit.enable,
9650 dm->wl_tx_limit.tx_time,
9651 dm->wl_tx_limit.tx_retry, btc->bt_req_len,
9652 bt->scan_rx_low_pri);
9653
9654 return p - buf;
9655 }
9656
_show_error(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9657 static int _show_error(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9658 {
9659 struct rtw89_btc *btc = &rtwdev->btc;
9660 const struct rtw89_btc_ver *ver = btc->ver;
9661 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9662 union rtw89_btc_fbtc_cysta_info *pcysta;
9663 char *p = buf, *end = buf + bufsz;
9664 u32 except_cnt, exception_map;
9665
9666 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
9667 if (ver->fcxcysta == 2) {
9668 pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
9669 except_cnt = le32_to_cpu(pcysta->v2.except_cnt);
9670 exception_map = le32_to_cpu(pcysta->v2.exception);
9671 } else if (ver->fcxcysta == 3) {
9672 pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
9673 except_cnt = le32_to_cpu(pcysta->v3.except_cnt);
9674 exception_map = le32_to_cpu(pcysta->v3.except_map);
9675 } else if (ver->fcxcysta == 4) {
9676 pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
9677 except_cnt = pcysta->v4.except_cnt;
9678 exception_map = le32_to_cpu(pcysta->v4.except_map);
9679 } else if (ver->fcxcysta == 5) {
9680 pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
9681 except_cnt = pcysta->v5.except_cnt;
9682 exception_map = le32_to_cpu(pcysta->v5.except_map);
9683 } else if (ver->fcxcysta == 7) {
9684 pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
9685 except_cnt = pcysta->v7.except_cnt;
9686 exception_map = le32_to_cpu(pcysta->v7.except_map);
9687 } else {
9688 return 0;
9689 }
9690
9691 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 &&
9692 !pfwinfo->len_mismch && !pfwinfo->fver_mismch)
9693 return 0;
9694
9695 p += scnprintf(p, end - p, " %-15s : ", "[error]");
9696
9697 if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
9698 p += scnprintf(p, end - p,
9699 "overflow-cnt: %d, ",
9700 pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
9701 }
9702
9703 if (pfwinfo->len_mismch) {
9704 p += scnprintf(p, end - p,
9705 "len-mismatch: 0x%x, ",
9706 pfwinfo->len_mismch);
9707 }
9708
9709 if (pfwinfo->fver_mismch) {
9710 p += scnprintf(p, end - p,
9711 "fver-mismatch: 0x%x, ",
9712 pfwinfo->fver_mismch);
9713 }
9714
9715 /* cycle statistics exceptions */
9716 if (exception_map || except_cnt) {
9717 p += scnprintf(p, end - p,
9718 "exception-type: 0x%x, exception-cnt = %d",
9719 exception_map, except_cnt);
9720 }
9721 p += scnprintf(p, end - p, "\n");
9722
9723 return p - buf;
9724 }
9725
_show_fbtc_tdma(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9726 static int _show_fbtc_tdma(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9727 {
9728 struct rtw89_btc *btc = &rtwdev->btc;
9729 const struct rtw89_btc_ver *ver = btc->ver;
9730 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9731 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9732 struct rtw89_btc_fbtc_tdma *t = NULL;
9733 char *p = buf, *end = buf + bufsz;
9734
9735 pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
9736 if (!pcinfo->valid)
9737 return 0;
9738
9739 if (ver->fcxtdma == 1)
9740 t = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
9741 else
9742 t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma;
9743
9744 p += scnprintf(p, end - p,
9745 " %-15s : ", "[tdma_policy]");
9746 p += scnprintf(p, end - p,
9747 "type:%d, rx_flow_ctrl:%d, tx_pause:%d, ",
9748 (u32)t->type,
9749 t->rxflctrl, t->txpause);
9750
9751 p += scnprintf(p, end - p,
9752 "wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ",
9753 t->wtgle_n, t->leak_n, t->ext_ctrl);
9754
9755 p += scnprintf(p, end - p,
9756 "policy_type:%d",
9757 (u32)btc->policy_type);
9758
9759 p += scnprintf(p, end - p, "\n");
9760
9761 return p - buf;
9762 }
9763
_show_fbtc_slots(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9764 static int _show_fbtc_slots(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9765 {
9766 struct rtw89_btc *btc = &rtwdev->btc;
9767 struct rtw89_btc_dm *dm = &btc->dm;
9768 char *p = buf, *end = buf + bufsz;
9769 u16 dur, cxtype;
9770 u32 tbl;
9771 u8 i = 0;
9772
9773 for (i = 0; i < CXST_MAX; i++) {
9774 if (btc->ver->fcxslots == 1) {
9775 dur = le16_to_cpu(dm->slot_now.v1[i].dur);
9776 tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl);
9777 cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype);
9778 } else if (btc->ver->fcxslots == 7) {
9779 dur = le16_to_cpu(dm->slot_now.v7[i].dur);
9780 tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl);
9781 cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype);
9782 } else {
9783 return 0;
9784 }
9785
9786 if (i % 5 == 0)
9787 p += scnprintf(p, end - p,
9788 " %-15s : %5s[%03d/0x%x/%d]",
9789 "[slot_list]",
9790 id_to_slot((u32)i),
9791 dur, tbl, cxtype);
9792 else
9793 p += scnprintf(p, end - p,
9794 ", %5s[%03d/0x%x/%d]",
9795 id_to_slot((u32)i),
9796 dur, tbl, cxtype);
9797
9798 if (i % 5 == 4)
9799 p += scnprintf(p, end - p, "\n");
9800 }
9801
9802 return p - buf;
9803 }
9804
_show_fbtc_cysta_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9805 static int _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9806 {
9807 struct rtw89_btc *btc = &rtwdev->btc;
9808 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9809 struct rtw89_btc_dm *dm = &btc->dm;
9810 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
9811 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9812 struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL;
9813 union rtw89_btc_fbtc_rxflct r;
9814 u16 cycle, c_begin, c_end, store_index;
9815 char *p = buf, *end = buf + bufsz;
9816 u8 i, cnt = 0, slot_pair;
9817
9818 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9819 if (!pcinfo->valid)
9820 return 0;
9821
9822 pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
9823 p += scnprintf(p, end - p,
9824 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
9825 "[cycle_cnt]",
9826 le16_to_cpu(pcysta_le32->cycles),
9827 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]),
9828 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]),
9829 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]),
9830 le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK]));
9831
9832 for (i = 0; i < CXST_MAX; i++) {
9833 if (!le32_to_cpu(pcysta_le32->slot_cnt[i]))
9834 continue;
9835 p += scnprintf(p, end - p, ", %s:%d", id_to_slot((u32)i),
9836 le32_to_cpu(pcysta_le32->slot_cnt[i]));
9837 }
9838
9839 if (dm->tdma_now.rxflctrl) {
9840 p += scnprintf(p, end - p, ", leak_rx:%d",
9841 le32_to_cpu(pcysta_le32->leakrx_cnt));
9842 }
9843
9844 if (le32_to_cpu(pcysta_le32->collision_cnt)) {
9845 p += scnprintf(p, end - p, ", collision:%d",
9846 le32_to_cpu(pcysta_le32->collision_cnt));
9847 }
9848
9849 if (le32_to_cpu(pcysta_le32->skip_cnt)) {
9850 p += scnprintf(p, end - p, ", skip:%d",
9851 le32_to_cpu(pcysta_le32->skip_cnt));
9852 }
9853 p += scnprintf(p, end - p, "\n");
9854
9855 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9856 "[cycle_time]",
9857 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]),
9858 le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]),
9859 le16_to_cpu(pcysta_le32->tavg_lk) / 1000,
9860 le16_to_cpu(pcysta_le32->tavg_lk) % 1000);
9861 p += scnprintf(p, end - p, ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
9862 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]),
9863 le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]),
9864 le16_to_cpu(pcysta_le32->tmax_lk) / 1000,
9865 le16_to_cpu(pcysta_le32->tmax_lk) % 1000);
9866 p += scnprintf(p, end - p, ", maxdiff_t[wl:%d/bt:%d]\n",
9867 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]),
9868 le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT]));
9869
9870 if (le16_to_cpu(pcysta_le32->cycles) <= 1)
9871 goto out;
9872
9873 /* 1 cycle record 1 wl-slot and 1 bt-slot */
9874 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
9875
9876 if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair)
9877 c_begin = 1;
9878 else
9879 c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1;
9880
9881 c_end = le16_to_cpu(pcysta_le32->cycles);
9882
9883 for (cycle = c_begin; cycle <= c_end; cycle++) {
9884 cnt++;
9885 store_index = ((cycle - 1) % slot_pair) * 2;
9886
9887 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1)
9888 p += scnprintf(p, end - p,
9889 " %-15s : ->b%02d->w%02d",
9890 "[cycle_step]",
9891 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
9892 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
9893 else
9894 p += scnprintf(p, end - p,
9895 "->b%02d->w%02d",
9896 le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
9897 le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
9898 if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
9899 p += scnprintf(p, end - p, "\n");
9900 }
9901
9902 if (a2dp->exist) {
9903 p += scnprintf(p, end - p,
9904 " %-15s : a2dp_ept:%d, a2dp_late:%d",
9905 "[a2dp_t_sta]",
9906 le16_to_cpu(pcysta_le32->a2dpept),
9907 le16_to_cpu(pcysta_le32->a2dpeptto));
9908
9909 p += scnprintf(p, end - p,
9910 ", avg_t:%d, max_t:%d",
9911 le16_to_cpu(pcysta_le32->tavg_a2dpept),
9912 le16_to_cpu(pcysta_le32->tmax_a2dpept));
9913 r.val = dm->tdma_now.rxflctrl;
9914
9915 if (r.type && r.tgln_n) {
9916 p += scnprintf(p, end - p,
9917 ", cycle[PSTDMA:%d/TDMA:%d], ",
9918 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]),
9919 le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF]));
9920
9921 p += scnprintf(p, end - p,
9922 "avg_t[PSTDMA:%d/TDMA:%d], ",
9923 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]),
9924 le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF]));
9925
9926 p += scnprintf(p, end - p,
9927 "max_t[PSTDMA:%d/TDMA:%d]",
9928 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]),
9929 le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF]));
9930 }
9931 p += scnprintf(p, end - p, "\n");
9932 }
9933
9934 out:
9935 return p - buf;
9936 }
9937
_show_fbtc_cysta_v3(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)9938 static int _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9939 {
9940 struct rtw89_btc *btc = &rtwdev->btc;
9941 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
9942 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9943 struct rtw89_btc_dm *dm = &btc->dm;
9944 struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx;
9945 struct rtw89_btc_fbtc_cysta_v3 *pcysta;
9946 struct rtw89_btc_rpt_cmn_info *pcinfo;
9947 u8 i, cnt = 0, slot_pair, divide_cnt;
9948 u16 cycle, c_begin, c_end, store_index;
9949 char *p = buf, *end = buf + bufsz;
9950
9951 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9952 if (!pcinfo->valid)
9953 return 0;
9954
9955 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
9956 p += scnprintf(p, end - p,
9957 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
9958 "[cycle_cnt]",
9959 le16_to_cpu(pcysta->cycles),
9960 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
9961 le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
9962 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
9963 le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
9964
9965 for (i = 0; i < CXST_MAX; i++) {
9966 if (!le32_to_cpu(pcysta->slot_cnt[i]))
9967 continue;
9968
9969 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
9970 le32_to_cpu(pcysta->slot_cnt[i]));
9971 }
9972
9973 if (dm->tdma_now.rxflctrl)
9974 p += scnprintf(p, end - p, ", leak_rx:%d",
9975 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
9976
9977 if (le32_to_cpu(pcysta->collision_cnt))
9978 p += scnprintf(p, end - p, ", collision:%d",
9979 le32_to_cpu(pcysta->collision_cnt));
9980
9981 if (le32_to_cpu(pcysta->skip_cnt))
9982 p += scnprintf(p, end - p, ", skip:%d",
9983 le32_to_cpu(pcysta->skip_cnt));
9984
9985 p += scnprintf(p, end - p, "\n");
9986
9987 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9988 "[cycle_time]",
9989 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
9990 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
9991 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
9992 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
9993 p += scnprintf(p, end - p,
9994 ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
9995 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
9996 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
9997 le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
9998 le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
9999 p += scnprintf(p, end - p,
10000 ", maxdiff_t[wl:%d/bt:%d]\n",
10001 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
10002 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
10003
10004 cycle = le16_to_cpu(pcysta->cycles);
10005 if (cycle <= 1)
10006 goto out;
10007
10008 /* 1 cycle record 1 wl-slot and 1 bt-slot */
10009 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10010
10011 if (cycle <= slot_pair)
10012 c_begin = 1;
10013 else
10014 c_begin = cycle - slot_pair + 1;
10015
10016 c_end = cycle;
10017
10018 if (a2dp->exist)
10019 divide_cnt = 3;
10020 else
10021 divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
10022
10023 for (cycle = c_begin; cycle <= c_end; cycle++) {
10024 cnt++;
10025 store_index = ((cycle - 1) % slot_pair) * 2;
10026
10027 if (cnt % divide_cnt == 1)
10028 p += scnprintf(p, end - p, " %-15s : ",
10029 "[cycle_step]");
10030
10031 p += scnprintf(p, end - p, "->b%02d",
10032 le16_to_cpu(pcysta->slot_step_time[store_index]));
10033 if (a2dp->exist) {
10034 a2dp_trx = &pcysta->a2dp_trx[store_index];
10035 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10036 a2dp_trx->empty_cnt,
10037 a2dp_trx->retry_cnt,
10038 a2dp_trx->tx_rate ? 3 : 2,
10039 a2dp_trx->tx_cnt,
10040 a2dp_trx->ack_cnt,
10041 a2dp_trx->nack_cnt);
10042 }
10043 p += scnprintf(p, end - p, "->w%02d",
10044 le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
10045 if (a2dp->exist) {
10046 a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
10047 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10048 a2dp_trx->empty_cnt,
10049 a2dp_trx->retry_cnt,
10050 a2dp_trx->tx_rate ? 3 : 2,
10051 a2dp_trx->tx_cnt,
10052 a2dp_trx->ack_cnt,
10053 a2dp_trx->nack_cnt);
10054 }
10055 if (cnt % divide_cnt == 0 || cnt == c_end)
10056 p += scnprintf(p, end - p, "\n");
10057 }
10058
10059 if (a2dp->exist) {
10060 p += scnprintf(p, end - p,
10061 " %-15s : a2dp_ept:%d, a2dp_late:%d",
10062 "[a2dp_t_sta]",
10063 le16_to_cpu(pcysta->a2dp_ept.cnt),
10064 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
10065
10066 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10067 le16_to_cpu(pcysta->a2dp_ept.tavg),
10068 le16_to_cpu(pcysta->a2dp_ept.tmax));
10069
10070 p += scnprintf(p, end - p, "\n");
10071 }
10072
10073 out:
10074 return p - buf;
10075 }
10076
_show_fbtc_cysta_v4(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10077 static int _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10078 {
10079 struct rtw89_btc *btc = &rtwdev->btc;
10080 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
10081 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10082 struct rtw89_btc_dm *dm = &btc->dm;
10083 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
10084 struct rtw89_btc_fbtc_cysta_v4 *pcysta;
10085 struct rtw89_btc_rpt_cmn_info *pcinfo;
10086 u8 i, cnt = 0, slot_pair, divide_cnt;
10087 u16 cycle, c_begin, c_end, store_index;
10088 char *p = buf, *end = buf + bufsz;
10089
10090 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10091 if (!pcinfo->valid)
10092 return 0;
10093
10094 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
10095 p += scnprintf(p, end - p,
10096 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
10097 "[cycle_cnt]",
10098 le16_to_cpu(pcysta->cycles),
10099 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
10100 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
10101 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
10102 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
10103
10104 for (i = 0; i < CXST_MAX; i++) {
10105 if (!le16_to_cpu(pcysta->slot_cnt[i]))
10106 continue;
10107
10108 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
10109 le16_to_cpu(pcysta->slot_cnt[i]));
10110 }
10111
10112 if (dm->tdma_now.rxflctrl)
10113 p += scnprintf(p, end - p, ", leak_rx:%d",
10114 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
10115
10116 if (pcysta->collision_cnt)
10117 p += scnprintf(p, end - p, ", collision:%d",
10118 pcysta->collision_cnt);
10119
10120 if (le16_to_cpu(pcysta->skip_cnt))
10121 p += scnprintf(p, end - p, ", skip:%d",
10122 le16_to_cpu(pcysta->skip_cnt));
10123
10124 p += scnprintf(p, end - p, "\n");
10125
10126 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
10127 "[cycle_time]",
10128 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
10129 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
10130 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
10131 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
10132 p += scnprintf(p, end - p,
10133 ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
10134 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
10135 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
10136 le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
10137 le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
10138 p += scnprintf(p, end - p,
10139 ", maxdiff_t[wl:%d/bt:%d]\n",
10140 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
10141 le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
10142
10143 cycle = le16_to_cpu(pcysta->cycles);
10144 if (cycle <= 1)
10145 goto out;
10146
10147 /* 1 cycle record 1 wl-slot and 1 bt-slot */
10148 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10149
10150 if (cycle <= slot_pair)
10151 c_begin = 1;
10152 else
10153 c_begin = cycle - slot_pair + 1;
10154
10155 c_end = cycle;
10156
10157 if (a2dp->exist)
10158 divide_cnt = 3;
10159 else
10160 divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
10161
10162 for (cycle = c_begin; cycle <= c_end; cycle++) {
10163 cnt++;
10164 store_index = ((cycle - 1) % slot_pair) * 2;
10165
10166 if (cnt % divide_cnt == 1)
10167 p += scnprintf(p, end - p, " %-15s : ",
10168 "[cycle_step]");
10169
10170 p += scnprintf(p, end - p, "->b%02d",
10171 le16_to_cpu(pcysta->slot_step_time[store_index]));
10172 if (a2dp->exist) {
10173 a2dp_trx = &pcysta->a2dp_trx[store_index];
10174 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10175 a2dp_trx->empty_cnt,
10176 a2dp_trx->retry_cnt,
10177 a2dp_trx->tx_rate ? 3 : 2,
10178 a2dp_trx->tx_cnt,
10179 a2dp_trx->ack_cnt,
10180 a2dp_trx->nack_cnt);
10181 }
10182 p += scnprintf(p, end - p, "->w%02d",
10183 le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
10184 if (a2dp->exist) {
10185 a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
10186 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10187 a2dp_trx->empty_cnt,
10188 a2dp_trx->retry_cnt,
10189 a2dp_trx->tx_rate ? 3 : 2,
10190 a2dp_trx->tx_cnt,
10191 a2dp_trx->ack_cnt,
10192 a2dp_trx->nack_cnt);
10193 }
10194 if (cnt % divide_cnt == 0 || cnt == c_end)
10195 p += scnprintf(p, end - p, "\n");
10196 }
10197
10198 if (a2dp->exist) {
10199 p += scnprintf(p, end - p,
10200 " %-15s : a2dp_ept:%d, a2dp_late:%d",
10201 "[a2dp_t_sta]",
10202 le16_to_cpu(pcysta->a2dp_ept.cnt),
10203 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
10204
10205 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10206 le16_to_cpu(pcysta->a2dp_ept.tavg),
10207 le16_to_cpu(pcysta->a2dp_ept.tmax));
10208
10209 p += scnprintf(p, end - p, "\n");
10210 }
10211
10212 out:
10213 return p - buf;
10214 }
10215
_show_fbtc_cysta_v5(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10216 static int _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10217 {
10218 struct rtw89_btc *btc = &rtwdev->btc;
10219 struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
10220 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10221 struct rtw89_btc_dm *dm = &btc->dm;
10222 struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
10223 struct rtw89_btc_fbtc_cysta_v5 *pcysta;
10224 struct rtw89_btc_rpt_cmn_info *pcinfo;
10225 u8 i, cnt = 0, slot_pair, divide_cnt;
10226 u16 cycle, c_begin, c_end, store_index;
10227 char *p = buf, *end = buf + bufsz;
10228
10229 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10230 if (!pcinfo->valid)
10231 return 0;
10232
10233 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
10234 p += scnprintf(p, end - p,
10235 " %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
10236 "[cycle_cnt]",
10237 le16_to_cpu(pcysta->cycles),
10238 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
10239 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
10240 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
10241 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
10242
10243 for (i = 0; i < CXST_MAX; i++) {
10244 if (!le16_to_cpu(pcysta->slot_cnt[i]))
10245 continue;
10246
10247 p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
10248 le16_to_cpu(pcysta->slot_cnt[i]));
10249 }
10250
10251 if (dm->tdma_now.rxflctrl)
10252 p += scnprintf(p, end - p, ", leak_rx:%d",
10253 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
10254
10255 if (pcysta->collision_cnt)
10256 p += scnprintf(p, end - p, ", collision:%d",
10257 pcysta->collision_cnt);
10258
10259 if (le16_to_cpu(pcysta->skip_cnt))
10260 p += scnprintf(p, end - p, ", skip:%d",
10261 le16_to_cpu(pcysta->skip_cnt));
10262
10263 p += scnprintf(p, end - p, "\n");
10264
10265 p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
10266 "[cycle_time]",
10267 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
10268 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
10269 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
10270 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
10271 p += scnprintf(p, end - p,
10272 ", max_t[wl:%d/bt:%d/lk:%d.%03d]\n",
10273 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
10274 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
10275 le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
10276 le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
10277
10278 cycle = le16_to_cpu(pcysta->cycles);
10279 if (cycle <= 1)
10280 goto out;
10281
10282 /* 1 cycle record 1 wl-slot and 1 bt-slot */
10283 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10284
10285 if (cycle <= slot_pair)
10286 c_begin = 1;
10287 else
10288 c_begin = cycle - slot_pair + 1;
10289
10290 c_end = cycle;
10291
10292 if (a2dp->exist)
10293 divide_cnt = 3;
10294 else
10295 divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
10296
10297 if (c_begin > c_end)
10298 goto out;
10299
10300 for (cycle = c_begin; cycle <= c_end; cycle++) {
10301 cnt++;
10302 store_index = ((cycle - 1) % slot_pair) * 2;
10303
10304 if (cnt % divide_cnt == 1)
10305 p += scnprintf(p, end - p, " %-15s : ",
10306 "[cycle_step]");
10307
10308 p += scnprintf(p, end - p, "->b%02d",
10309 le16_to_cpu(pcysta->slot_step_time[store_index]));
10310 if (a2dp->exist) {
10311 a2dp_trx = &pcysta->a2dp_trx[store_index];
10312 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10313 a2dp_trx->empty_cnt,
10314 a2dp_trx->retry_cnt,
10315 a2dp_trx->tx_rate ? 3 : 2,
10316 a2dp_trx->tx_cnt,
10317 a2dp_trx->ack_cnt,
10318 a2dp_trx->nack_cnt);
10319 }
10320 p += scnprintf(p, end - p, "->w%02d",
10321 le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
10322 if (a2dp->exist) {
10323 a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
10324 p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10325 a2dp_trx->empty_cnt,
10326 a2dp_trx->retry_cnt,
10327 a2dp_trx->tx_rate ? 3 : 2,
10328 a2dp_trx->tx_cnt,
10329 a2dp_trx->ack_cnt,
10330 a2dp_trx->nack_cnt);
10331 }
10332 if (cnt % divide_cnt == 0 || cnt == c_end)
10333 p += scnprintf(p, end - p, "\n");
10334 }
10335
10336 if (a2dp->exist) {
10337 p += scnprintf(p, end - p,
10338 " %-15s : a2dp_ept:%d, a2dp_late:%d",
10339 "[a2dp_t_sta]",
10340 le16_to_cpu(pcysta->a2dp_ept.cnt),
10341 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
10342
10343 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10344 le16_to_cpu(pcysta->a2dp_ept.tavg),
10345 le16_to_cpu(pcysta->a2dp_ept.tmax));
10346
10347 p += scnprintf(p, end - p, "\n");
10348 }
10349
10350 out:
10351 return p - buf;
10352 }
10353
_show_fbtc_cysta_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10354 static int _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10355 {
10356 struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt;
10357 struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc;
10358 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
10359 struct rtw89_btc_fbtc_cysta_v7 *pcysta = NULL;
10360 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
10361 struct rtw89_btc_rpt_cmn_info *pcinfo;
10362 char *p = buf, *end = buf + bufsz;
10363 u16 cycle, c_begin, c_end, s_id;
10364 u8 i, cnt = 0, divide_cnt;
10365 u8 slot_pair;
10366
10367 pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10368 if (!pcinfo->valid)
10369 return 0;
10370
10371 pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
10372 p += scnprintf(p, end - p, "\n %-15s : cycle:%d", "[slot_stat]",
10373 le16_to_cpu(pcysta->cycles));
10374
10375 for (i = 0; i < CXST_MAX; i++) {
10376 if (!le16_to_cpu(pcysta->slot_cnt[i]))
10377 continue;
10378 p += scnprintf(p, end - p, ", %s:%d",
10379 id_to_slot(i),
10380 le16_to_cpu(pcysta->slot_cnt[i]));
10381 }
10382
10383 if (dm->tdma_now.rxflctrl)
10384 p += scnprintf(p, end - p, ", leak_rx:%d",
10385 le32_to_cpu(pcysta->leak_slot.cnt_rximr));
10386
10387 if (pcysta->collision_cnt)
10388 p += scnprintf(p, end - p, ", collision:%d",
10389 pcysta->collision_cnt);
10390
10391 if (pcysta->skip_cnt)
10392 p += scnprintf(p, end - p, ", skip:%d",
10393 le16_to_cpu(pcysta->skip_cnt));
10394
10395 p += scnprintf(p, end - p,
10396 "\n\r %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
10397 "[cycle_stat]",
10398 le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
10399 le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
10400 le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
10401 le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
10402 p += scnprintf(p, end - p,
10403 ", max_t[wl:%d/bt:%d(>%dms:%d)/lk:%d.%03d]",
10404 le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
10405 le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
10406 dm->bt_slot_flood, dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD],
10407 le16_to_cpu(pcysta->leak_slot.tamx) / 1000,
10408 le16_to_cpu(pcysta->leak_slot.tamx) % 1000);
10409 p += scnprintf(p, end - p, ", bcn[all:%d/ok:%d/in_bt:%d/in_bt_ok:%d]",
10410 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
10411 le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
10412 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
10413 le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
10414
10415 if (a2dp->exist) {
10416 p += scnprintf(p, end - p,
10417 "\n\r %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)",
10418 "[a2dp_stat]",
10419 le16_to_cpu(pcysta->a2dp_ept.cnt),
10420 le16_to_cpu(pcysta->a2dp_ept.cnt_timeout),
10421 a2dp->no_empty_streak_2s,
10422 a2dp->no_empty_streak_max);
10423
10424 p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10425 le16_to_cpu(pcysta->a2dp_ept.tavg),
10426 le16_to_cpu(pcysta->a2dp_ept.tmax));
10427 }
10428
10429 if (le16_to_cpu(pcysta->cycles) <= 1)
10430 goto out;
10431
10432 /* 1 cycle = 1 wl-slot + 1 bt-slot */
10433 slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10434
10435 if (le16_to_cpu(pcysta->cycles) <= slot_pair)
10436 c_begin = 1;
10437 else
10438 c_begin = le16_to_cpu(pcysta->cycles) - slot_pair + 1;
10439
10440 c_end = le16_to_cpu(pcysta->cycles);
10441
10442 if (a2dp->exist)
10443 divide_cnt = 2;
10444 else
10445 divide_cnt = 6;
10446
10447 if (c_begin > c_end)
10448 goto out;
10449
10450 for (cycle = c_begin; cycle <= c_end; cycle++) {
10451 cnt++;
10452 s_id = ((cycle - 1) % slot_pair) * 2;
10453
10454 if (cnt % divide_cnt == 1) {
10455 if (a2dp->exist)
10456 p += scnprintf(p, end - p, "\n\r %-15s : ",
10457 "[slotT_wermtan]");
10458 else
10459 p += scnprintf(p, end - p, "\n\r %-15s : ",
10460 "[slotT_rxerr]");
10461 }
10462
10463 p += scnprintf(p, end - p, "->b%d",
10464 le16_to_cpu(pcysta->slot_step_time[s_id]));
10465
10466 if (a2dp->exist)
10467 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)",
10468 pcysta->wl_rx_err_ratio[s_id],
10469 pcysta->a2dp_trx[s_id].empty_cnt,
10470 pcysta->a2dp_trx[s_id].retry_cnt,
10471 (pcysta->a2dp_trx[s_id].tx_rate ? 3 : 2),
10472 pcysta->a2dp_trx[s_id].tx_cnt,
10473 pcysta->a2dp_trx[s_id].ack_cnt,
10474 pcysta->a2dp_trx[s_id].nack_cnt);
10475 else
10476 p += scnprintf(p, end - p, "(%d)",
10477 pcysta->wl_rx_err_ratio[s_id]);
10478
10479 p += scnprintf(p, end - p, "->w%d",
10480 le16_to_cpu(pcysta->slot_step_time[s_id + 1]));
10481
10482 if (a2dp->exist)
10483 p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)",
10484 pcysta->wl_rx_err_ratio[s_id + 1],
10485 pcysta->a2dp_trx[s_id + 1].empty_cnt,
10486 pcysta->a2dp_trx[s_id + 1].retry_cnt,
10487 (pcysta->a2dp_trx[s_id + 1].tx_rate ? 3 : 2),
10488 pcysta->a2dp_trx[s_id + 1].tx_cnt,
10489 pcysta->a2dp_trx[s_id + 1].ack_cnt,
10490 pcysta->a2dp_trx[s_id + 1].nack_cnt);
10491 else
10492 p += scnprintf(p, end - p, "(%d)",
10493 pcysta->wl_rx_err_ratio[s_id + 1]);
10494 }
10495
10496 out:
10497 return p - buf;
10498 }
10499
_show_fbtc_nullsta(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10500 static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10501 {
10502 struct rtw89_btc *btc = &rtwdev->btc;
10503 const struct rtw89_btc_ver *ver = btc->ver;
10504 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10505 struct rtw89_btc_rpt_cmn_info *pcinfo;
10506 union rtw89_btc_fbtc_cynullsta_info *ns;
10507 char *p = buf, *end = buf + bufsz;
10508 u8 i = 0;
10509
10510 if (!btc->dm.tdma_now.rxflctrl)
10511 return 0;
10512
10513 pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
10514 if (!pcinfo->valid)
10515 return 0;
10516
10517 ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
10518 if (ver->fcxnullsta == 1) {
10519 for (i = 0; i < 2; i++) {
10520 p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]");
10521 p += scnprintf(p, end - p, "null-%d", i);
10522 p += scnprintf(p, end - p, "[ok:%d/",
10523 le32_to_cpu(ns->v1.result[i][1]));
10524 p += scnprintf(p, end - p, "fail:%d/",
10525 le32_to_cpu(ns->v1.result[i][0]));
10526 p += scnprintf(p, end - p, "on_time:%d/",
10527 le32_to_cpu(ns->v1.result[i][2]));
10528 p += scnprintf(p, end - p, "retry:%d/",
10529 le32_to_cpu(ns->v1.result[i][3]));
10530 p += scnprintf(p, end - p, "avg_t:%d.%03d/",
10531 le32_to_cpu(ns->v1.avg_t[i]) / 1000,
10532 le32_to_cpu(ns->v1.avg_t[i]) % 1000);
10533 p += scnprintf(p, end - p, "max_t:%d.%03d]",
10534 le32_to_cpu(ns->v1.max_t[i]) / 1000,
10535 le32_to_cpu(ns->v1.max_t[i]) % 1000);
10536 }
10537 } else if (ver->fcxnullsta == 7) {
10538 for (i = 0; i < 2; i++) {
10539 p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]");
10540 p += scnprintf(p, end - p, "null-%d", i);
10541 p += scnprintf(p, end - p, "[Tx:%d/",
10542 le32_to_cpu(ns->v7.result[i][4]));
10543 p += scnprintf(p, end - p, "[ok:%d/",
10544 le32_to_cpu(ns->v7.result[i][1]));
10545 p += scnprintf(p, end - p, "fail:%d/",
10546 le32_to_cpu(ns->v7.result[i][0]));
10547 p += scnprintf(p, end - p, "on_time:%d/",
10548 le32_to_cpu(ns->v7.result[i][2]));
10549 p += scnprintf(p, end - p, "retry:%d/",
10550 le32_to_cpu(ns->v7.result[i][3]));
10551 p += scnprintf(p, end - p, "avg_t:%d.%03d/",
10552 le32_to_cpu(ns->v7.tavg[i]) / 1000,
10553 le32_to_cpu(ns->v7.tavg[i]) % 1000);
10554 p += scnprintf(p, end - p, "max_t:%d.%03d]",
10555 le32_to_cpu(ns->v7.tmax[i]) / 1000,
10556 le32_to_cpu(ns->v7.tmax[i]) % 1000);
10557 }
10558 } else {
10559 for (i = 0; i < 2; i++) {
10560 p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]");
10561 p += scnprintf(p, end - p, "null-%d", i);
10562 p += scnprintf(p, end - p, "[Tx:%d/",
10563 le32_to_cpu(ns->v2.result[i][4]));
10564 p += scnprintf(p, end - p, "[ok:%d/",
10565 le32_to_cpu(ns->v2.result[i][1]));
10566 p += scnprintf(p, end - p, "fail:%d/",
10567 le32_to_cpu(ns->v2.result[i][0]));
10568 p += scnprintf(p, end - p, "on_time:%d/",
10569 le32_to_cpu(ns->v2.result[i][2]));
10570 p += scnprintf(p, end - p, "retry:%d/",
10571 le32_to_cpu(ns->v2.result[i][3]));
10572 p += scnprintf(p, end - p, "avg_t:%d.%03d/",
10573 le32_to_cpu(ns->v2.avg_t[i]) / 1000,
10574 le32_to_cpu(ns->v2.avg_t[i]) % 1000);
10575 p += scnprintf(p, end - p, "max_t:%d.%03d]",
10576 le32_to_cpu(ns->v2.max_t[i]) / 1000,
10577 le32_to_cpu(ns->v2.max_t[i]) % 1000);
10578 }
10579 }
10580
10581 return p - buf;
10582 }
10583
_show_fbtc_step_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10584 static int _show_fbtc_step_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10585 {
10586 struct rtw89_btc *btc = &rtwdev->btc;
10587 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10588 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10589 struct rtw89_btc_fbtc_steps_v2 *pstep = NULL;
10590 const struct rtw89_btc_ver *ver = btc->ver;
10591 char *p = buf, *end = buf + bufsz;
10592 u8 type, val, cnt = 0, state = 0;
10593 bool outloop = false;
10594 u16 i, diff_t, n_start = 0, n_stop = 0;
10595 u16 pos_old, pos_new, trace_step;
10596
10597 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
10598 if (!pcinfo->valid)
10599 return 0;
10600
10601 pstep = &pfwinfo->rpt_fbtc_step.finfo.v2;
10602 pos_old = le16_to_cpu(pstep->pos_old);
10603 pos_new = le16_to_cpu(pstep->pos_new);
10604
10605 if (pcinfo->req_fver != pstep->fver)
10606 return 0;
10607
10608 /* store step info by using ring instead of FIFO*/
10609 do {
10610 switch (state) {
10611 case 0:
10612 if (ver->fcxctrl == 7 || ver->fcxctrl == 1)
10613 trace_step = 50;
10614 else
10615 trace_step = btc->ctrl.ctrl.trace_step;
10616
10617 n_start = pos_old;
10618 if (pos_new >= pos_old)
10619 n_stop = pos_new;
10620 else
10621 n_stop = trace_step - 1;
10622
10623 state = 1;
10624 break;
10625 case 1:
10626 for (i = n_start; i <= n_stop; i++) {
10627 type = pstep->step[i].type;
10628 val = pstep->step[i].val;
10629 diff_t = le16_to_cpu(pstep->step[i].difft);
10630
10631 if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
10632 continue;
10633
10634 if (cnt % 10 == 0)
10635 p += scnprintf(p, end - p,
10636 " %-15s : ", "[steps]");
10637
10638 p += scnprintf(p, end - p,
10639 "-> %s(%02d)(%02d)",
10640 (type == CXSTEP_SLOT ? "SLT" :
10641 "EVT"), (u32)val, diff_t);
10642 if (cnt % 10 == 9)
10643 p += scnprintf(p, end - p, "\n");
10644 cnt++;
10645 }
10646
10647 state = 2;
10648 break;
10649 case 2:
10650 if (pos_new < pos_old && n_start != 0) {
10651 n_start = 0;
10652 n_stop = pos_new;
10653 state = 1;
10654 } else {
10655 outloop = true;
10656 }
10657 break;
10658 }
10659 } while (!outloop);
10660
10661 return p - buf;
10662 }
10663
_show_fbtc_step_v3(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10664 static int _show_fbtc_step_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10665 {
10666 struct rtw89_btc *btc = &rtwdev->btc;
10667 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10668 struct rtw89_btc_rpt_cmn_info *pcinfo;
10669 struct rtw89_btc_fbtc_steps_v3 *pstep;
10670 u32 i, n_begin, n_end, array_idx, cnt = 0;
10671 char *p = buf, *end = buf + bufsz;
10672 u8 type, val;
10673 u16 diff_t;
10674
10675 if ((pfwinfo->rpt_en_map &
10676 rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0)
10677 return 0;
10678
10679 pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
10680 if (!pcinfo->valid)
10681 return 0;
10682
10683 pstep = &pfwinfo->rpt_fbtc_step.finfo.v3;
10684 if (pcinfo->req_fver != pstep->fver)
10685 return 0;
10686
10687 if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP)
10688 n_begin = 1;
10689 else
10690 n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1;
10691
10692 n_end = le32_to_cpu(pstep->cnt);
10693
10694 if (n_begin > n_end)
10695 return 0;
10696
10697 /* restore step info by using ring instead of FIFO */
10698 for (i = n_begin; i <= n_end; i++) {
10699 array_idx = (i - 1) % FCXDEF_STEP;
10700 type = pstep->step[array_idx].type;
10701 val = pstep->step[array_idx].val;
10702 diff_t = le16_to_cpu(pstep->step[array_idx].difft);
10703
10704 if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
10705 continue;
10706
10707 if (cnt % 10 == 0)
10708 p += scnprintf(p, end - p, " %-15s : ", "[steps]");
10709
10710 p += scnprintf(p, end - p, "-> %s(%02d)",
10711 (type == CXSTEP_SLOT ?
10712 id_to_slot((u32)val) :
10713 id_to_evt((u32)val)), diff_t);
10714
10715 if (cnt % 10 == 9)
10716 p += scnprintf(p, end - p, "\n");
10717
10718 cnt++;
10719 }
10720
10721 return p - buf;
10722 }
10723
_show_fw_dm_msg(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10724 static int _show_fw_dm_msg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10725 {
10726 struct rtw89_btc *btc = &rtwdev->btc;
10727 const struct rtw89_btc_ver *ver = btc->ver;
10728 char *p = buf, *end = buf + bufsz;
10729
10730 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
10731 goto out;
10732
10733 p += _show_error(rtwdev, p, end - p);
10734 p += _show_fbtc_tdma(rtwdev, p, end - p);
10735 p += _show_fbtc_slots(rtwdev, p, end - p);
10736
10737 if (ver->fcxcysta == 2)
10738 p += _show_fbtc_cysta_v2(rtwdev, p, end - p);
10739 else if (ver->fcxcysta == 3)
10740 p += _show_fbtc_cysta_v3(rtwdev, p, end - p);
10741 else if (ver->fcxcysta == 4)
10742 p += _show_fbtc_cysta_v4(rtwdev, p, end - p);
10743 else if (ver->fcxcysta == 5)
10744 p += _show_fbtc_cysta_v5(rtwdev, p, end - p);
10745 else if (ver->fcxcysta == 7)
10746 p += _show_fbtc_cysta_v7(rtwdev, p, end - p);
10747
10748 p += _show_fbtc_nullsta(rtwdev, p, end - p);
10749
10750 if (ver->fcxstep == 2)
10751 p += _show_fbtc_step_v2(rtwdev, p, end - p);
10752 else if (ver->fcxstep == 3)
10753 p += _show_fbtc_step_v3(rtwdev, p, end - p);
10754
10755 out:
10756 return p - buf;
10757 }
10758
_get_gnt(struct rtw89_dev * rtwdev,struct rtw89_mac_ax_coex_gnt * gnt_cfg)10759 static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg)
10760 {
10761 const struct rtw89_chip_info *chip = rtwdev->chip;
10762 struct rtw89_mac_ax_gnt *gnt;
10763 u32 val, status;
10764
10765 if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B ||
10766 chip->chip_id == RTL8851B || chip->chip_id == RTL8852BT) {
10767 rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
10768 rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status);
10769
10770 gnt = &gnt_cfg->band[0];
10771 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL);
10772 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA);
10773 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL);
10774 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA);
10775
10776 gnt = &gnt_cfg->band[1];
10777 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL);
10778 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA);
10779 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL);
10780 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA);
10781 } else if (chip->chip_id == RTL8852C) {
10782 val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL);
10783 status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1);
10784
10785 gnt = &gnt_cfg->band[0];
10786 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL);
10787 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0);
10788 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL);
10789 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0);
10790
10791 gnt = &gnt_cfg->band[1];
10792 gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL);
10793 gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1);
10794 gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL);
10795 gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1);
10796 } else {
10797 return;
10798 }
10799 }
10800
_show_gpio_dbg(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10801 static int _show_gpio_dbg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10802 {
10803 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
10804 const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
10805 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10806 union rtw89_btc_fbtc_gpio_dbg *gdbg = NULL;
10807 char *p = buf, *end = buf + bufsz;
10808 u8 *gpio_map, i;
10809 u32 en_map;
10810
10811 pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
10812 gdbg = &rtwdev->btc.fwinfo.rpt_fbtc_gpio_dbg.finfo;
10813 if (!pcinfo->valid) {
10814 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10815 "[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n",
10816 __func__);
10817 goto out;
10818 }
10819
10820 if (ver->fcxgpiodbg == 7) {
10821 en_map = le32_to_cpu(gdbg->v7.en_map);
10822 gpio_map = gdbg->v7.gpio_map;
10823 } else {
10824 en_map = le32_to_cpu(gdbg->v1.en_map);
10825 gpio_map = gdbg->v1.gpio_map;
10826 }
10827
10828 if (!en_map)
10829 goto out;
10830
10831 p += scnprintf(p, end - p, " %-15s : enable_map:0x%08x",
10832 "[gpio_dbg]", en_map);
10833
10834 for (i = 0; i < BTC_DBG_MAX1; i++) {
10835 if (!(en_map & BIT(i)))
10836 continue;
10837 p += scnprintf(p, end - p, ", %s->GPIO%d", id_to_gdbg(i),
10838 gpio_map[i]);
10839 }
10840 p += scnprintf(p, end - p, "\n");
10841
10842 out:
10843 return p - buf;
10844 }
10845
_show_mreg_v1(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10846 static int _show_mreg_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10847 {
10848 const struct rtw89_chip_info *chip = rtwdev->chip;
10849 struct rtw89_btc *btc = &rtwdev->btc;
10850 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10851 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10852 struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL;
10853 struct rtw89_btc_cx *cx = &btc->cx;
10854 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
10855 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
10856 struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
10857 struct rtw89_mac_ax_gnt gnt;
10858 char *p = buf, *end = buf + bufsz;
10859 u8 i = 0, type = 0, cnt = 0;
10860 u32 val, offset;
10861
10862 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
10863 return 0;
10864
10865 p += scnprintf(p, end - p, "========== [HW Status] ==========\n");
10866
10867 p += scnprintf(p, end - p,
10868 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
10869 "[scoreboard]", wl->scbd,
10870 cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
10871 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
10872 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
10873
10874 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
10875 _get_gnt(rtwdev, &gnt_cfg);
10876
10877 gnt = gnt_cfg.band[0];
10878 p += scnprintf(p, end - p,
10879 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
10880 "[gnt_status]",
10881 chip->chip_id == RTL8852C ? "HW" :
10882 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
10883 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
10884 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt);
10885
10886 gnt = gnt_cfg.band[1];
10887 p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
10888 gnt.gnt_wl_sw_en ? "SW" : "HW",
10889 gnt.gnt_wl,
10890 gnt.gnt_bt_sw_en ? "SW" : "HW",
10891 gnt.gnt_bt);
10892
10893 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
10894 if (!pcinfo->valid) {
10895 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10896 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
10897 __func__);
10898 goto out;
10899 }
10900
10901 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
10902 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10903 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
10904 __func__, pmreg->reg_num);
10905
10906 for (i = 0; i < pmreg->reg_num; i++) {
10907 type = (u8)le16_to_cpu(chip->mon_reg[i].type);
10908 offset = le32_to_cpu(chip->mon_reg[i].offset);
10909 val = le32_to_cpu(pmreg->mreg_val[i]);
10910
10911 if (cnt % 6 == 0)
10912 p += scnprintf(p, end - p,
10913 " %-15s : %d_0x%04x=0x%08x",
10914 "[reg]", (u32)type, offset, val);
10915 else
10916 p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x",
10917 (u32)type,
10918 offset, val);
10919 if (cnt % 6 == 5)
10920 p += scnprintf(p, end - p, "\n");
10921 cnt++;
10922
10923 if (i >= pmreg->reg_num)
10924 p += scnprintf(p, end - p, "\n");
10925 }
10926
10927 out:
10928 return p - buf;
10929 }
10930
_show_mreg_v2(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)10931 static int _show_mreg_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10932 {
10933 const struct rtw89_chip_info *chip = rtwdev->chip;
10934 struct rtw89_btc *btc = &rtwdev->btc;
10935 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10936 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10937 struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL;
10938 struct rtw89_btc_cx *cx = &btc->cx;
10939 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
10940 struct rtw89_btc_bt_info *bt = &btc->cx.bt;
10941 struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
10942 struct rtw89_mac_ax_gnt gnt;
10943 char *p = buf, *end = buf + bufsz;
10944 u8 i = 0, type = 0, cnt = 0;
10945 u32 val, offset;
10946
10947 if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
10948 return 0;
10949
10950 p += scnprintf(p, end - p, "========== [HW Status] ==========\n");
10951
10952 p += scnprintf(p, end - p,
10953 " %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
10954 "[scoreboard]", wl->scbd,
10955 cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
10956 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
10957 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
10958
10959 btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
10960 _get_gnt(rtwdev, &gnt_cfg);
10961
10962 gnt = gnt_cfg.band[0];
10963 p += scnprintf(p, end - p,
10964 " %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], polut_type:%s",
10965 "[gnt_status]",
10966 chip->chip_id == RTL8852C ? "HW" :
10967 btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
10968 gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
10969 gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt,
10970 id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
10971
10972 gnt = gnt_cfg.band[1];
10973 p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
10974 gnt.gnt_wl_sw_en ? "SW" : "HW",
10975 gnt.gnt_wl,
10976 gnt.gnt_bt_sw_en ? "SW" : "HW",
10977 gnt.gnt_bt);
10978
10979 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
10980 if (!pcinfo->valid) {
10981 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10982 "[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
10983 __func__);
10984 goto out;
10985 }
10986
10987 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
10988 rtw89_debug(rtwdev, RTW89_DBG_BTC,
10989 "[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
10990 __func__, pmreg->reg_num);
10991
10992 for (i = 0; i < pmreg->reg_num; i++) {
10993 type = (u8)le16_to_cpu(chip->mon_reg[i].type);
10994 offset = le32_to_cpu(chip->mon_reg[i].offset);
10995 val = le32_to_cpu(pmreg->mreg_val[i]);
10996
10997 if (cnt % 6 == 0)
10998 p += scnprintf(p, end - p,
10999 " %-15s : %d_0x%04x=0x%08x",
11000 "[reg]", (u32)type, offset, val);
11001 else
11002 p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x",
11003 (u32)type,
11004 offset, val);
11005 if (cnt % 6 == 5)
11006 p += scnprintf(p, end - p, "\n");
11007 cnt++;
11008
11009 if (i >= pmreg->reg_num)
11010 p += scnprintf(p, end - p, "\n");
11011 }
11012
11013 out:
11014 return p - buf;
11015 }
11016
_show_mreg_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11017 static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11018 {
11019 struct rtw89_btc *btc = &rtwdev->btc;
11020 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11021 struct rtw89_btc_fbtc_mreg_val_v7 *pmreg = NULL;
11022 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11023 struct rtw89_btc_cx *cx = &btc->cx;
11024 struct rtw89_btc_wl_info *wl = &cx->wl;
11025 struct rtw89_btc_bt_info *bt = &cx->bt;
11026 struct rtw89_mac_ax_gnt *gnt = NULL;
11027 struct rtw89_btc_dm *dm = &btc->dm;
11028 char *p = buf, *end = buf + bufsz;
11029 u8 i, type, cnt = 0;
11030 u32 val, offset;
11031
11032 if (!(dm->coex_info_map & BTC_COEX_INFO_MREG))
11033 return 0;
11034
11035 p += scnprintf(p, end - p, "\n\r========== [HW Status] ==========");
11036
11037 p += scnprintf(p, end - p,
11038 "\n\r %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)",
11039 "[scoreboard]", wl->scbd,
11040 cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
11041 bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
11042 cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
11043
11044 /* To avoid I/O if WL LPS or power-off */
11045 dm->pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
11046
11047 p += scnprintf(p, end - p,
11048 "\n\r %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s",
11049 "[gnt_status]",
11050 rtwdev->chip->para_ver & BTC_FEAT_PTA_ONOFF_CTRL ? "HW" :
11051 dm->pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
11052 wl->pta_req_mac,
11053 id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
11054
11055 gnt = &dm->gnt.band[RTW89_PHY_0];
11056
11057 p += scnprintf(p, end - p, ", phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]",
11058 gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl,
11059 gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt);
11060
11061 if (rtwdev->dbcc_en) {
11062 gnt = &dm->gnt.band[RTW89_PHY_1];
11063 p += scnprintf(p, end - p,
11064 ", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]",
11065 gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl,
11066 gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt);
11067 }
11068
11069 pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
11070 if (!pcinfo->valid)
11071 goto out;
11072
11073 pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
11074
11075 for (i = 0; i < pmreg->reg_num; i++) {
11076 type = (u8)le16_to_cpu(rtwdev->chip->mon_reg[i].type);
11077 offset = le32_to_cpu(rtwdev->chip->mon_reg[i].offset);
11078 val = le32_to_cpu(pmreg->mreg_val[i]);
11079
11080 if (cnt % 6 == 0)
11081 p += scnprintf(p, end - p,
11082 "\n\r %-15s : %s_0x%x=0x%x", "[reg]",
11083 id_to_regtype(type), offset, val);
11084 else
11085 p += scnprintf(p, end - p, ", %s_0x%x=0x%x",
11086 id_to_regtype(type), offset, val);
11087 cnt++;
11088 }
11089
11090 out:
11091 return p - buf;
11092 }
11093
_show_summary_v1(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11094 static int _show_summary_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11095 {
11096 struct rtw89_btc *btc = &rtwdev->btc;
11097 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11098 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11099 struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL;
11100 struct rtw89_btc_cx *cx = &btc->cx;
11101 struct rtw89_btc_dm *dm = &btc->dm;
11102 struct rtw89_btc_wl_info *wl = &cx->wl;
11103 struct rtw89_btc_bt_info *bt = &cx->bt;
11104 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11105 char *p = buf, *end = buf + bufsz;
11106 u8 i;
11107
11108 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11109 return 0;
11110
11111 p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11112
11113 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11114 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11115 prptctrl = &pfwinfo->rpt_ctrl.finfo.v1;
11116
11117 p += scnprintf(p, end - p,
11118 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
11119 "[summary]", pfwinfo->cnt_h2c,
11120 pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt,
11121 pfwinfo->cnt_c2h, prptctrl->c2h_cnt);
11122
11123 p += scnprintf(p, end - p,
11124 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
11125 pfwinfo->event[BTF_EVNT_RPT],
11126 prptctrl->rpt_cnt,
11127 prptctrl->rpt_enable, dm->error.val);
11128
11129 if (dm->error.map.wl_fw_hang)
11130 p += scnprintf(p, end - p, " (WL FW Hang!!)");
11131 p += scnprintf(p, end - p, "\n");
11132 p += scnprintf(p, end - p,
11133 " %-15s : send_ok:%d, send_fail:%d, recv:%d",
11134 "[mailbox]", prptctrl->mb_send_ok_cnt,
11135 prptctrl->mb_send_fail_cnt,
11136 prptctrl->mb_recv_cnt);
11137
11138 p += scnprintf(p, end - p,
11139 "(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n",
11140 prptctrl->mb_a2dp_empty_cnt,
11141 prptctrl->mb_a2dp_flct_cnt,
11142 prptctrl->mb_a2dp_full_cnt);
11143
11144 p += scnprintf(p, end - p,
11145 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
11146 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11147 cx->cnt_wl[BTC_WCNT_RFK_GO],
11148 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11149 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11150
11151 p += scnprintf(p, end - p,
11152 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
11153 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
11154 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
11155 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
11156 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
11157 prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
11158
11159 if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
11160 bt->rfk_info.map.timeout = 1;
11161 else
11162 bt->rfk_info.map.timeout = 0;
11163
11164 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
11165 } else {
11166 p += scnprintf(p, end - p,
11167 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
11168 "[summary]", pfwinfo->cnt_h2c,
11169 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
11170 pfwinfo->event[BTF_EVNT_RPT],
11171 btc->fwinfo.rpt_en_map);
11172 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n");
11173 }
11174
11175 for (i = 0; i < BTC_NCNT_NUM; i++)
11176 cnt_sum += dm->cnt_notify[i];
11177
11178 p += scnprintf(p, end - p,
11179 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11180 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11181 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11182
11183 p += scnprintf(p, end - p,
11184 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
11185 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11186 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11187 cnt[BTC_NCNT_WL_STA]);
11188
11189 p += scnprintf(p, end - p,
11190 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11191 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
11192 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
11193 cnt[BTC_NCNT_SPECIAL_PACKET]);
11194
11195 p += scnprintf(p, end - p,
11196 "timer=%d, control=%d, customerize=%d\n",
11197 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11198 cnt[BTC_NCNT_CUSTOMERIZE]);
11199
11200 return p - buf;
11201 }
11202
_show_summary_v4(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11203 static int _show_summary_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11204 {
11205 struct rtw89_btc *btc = &rtwdev->btc;
11206 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11207 struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl;
11208 struct rtw89_btc_rpt_cmn_info *pcinfo;
11209 struct rtw89_btc_cx *cx = &btc->cx;
11210 struct rtw89_btc_dm *dm = &btc->dm;
11211 struct rtw89_btc_wl_info *wl = &cx->wl;
11212 struct rtw89_btc_bt_info *bt = &cx->bt;
11213 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11214 char *p = buf, *end = buf + bufsz;
11215 u8 i;
11216
11217 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11218 return 0;
11219
11220 p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11221
11222 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11223 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11224 prptctrl = &pfwinfo->rpt_ctrl.finfo.v4;
11225
11226 p += scnprintf(p, end - p,
11227 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
11228 "[summary]", pfwinfo->cnt_h2c,
11229 pfwinfo->cnt_h2c_fail,
11230 le32_to_cpu(prptctrl->rpt_info.cnt_h2c),
11231 pfwinfo->cnt_c2h,
11232 le32_to_cpu(prptctrl->rpt_info.cnt_c2h));
11233
11234 p += scnprintf(p, end - p,
11235 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
11236 pfwinfo->event[BTF_EVNT_RPT],
11237 le32_to_cpu(prptctrl->rpt_info.cnt),
11238 le32_to_cpu(prptctrl->rpt_info.en),
11239 dm->error.val);
11240
11241 if (dm->error.map.wl_fw_hang)
11242 p += scnprintf(p, end - p, " (WL FW Hang!!)");
11243 p += scnprintf(p, end - p, "\n");
11244 p += scnprintf(p, end - p,
11245 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11246 "[mailbox]",
11247 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11248 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11249 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11250
11251 p += scnprintf(p, end - p,
11252 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
11253 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11254 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11255 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11256 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11257 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11258
11259 p += scnprintf(p, end - p,
11260 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
11261 "[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11262 cx->cnt_wl[BTC_WCNT_RFK_GO],
11263 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11264 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11265
11266 p += scnprintf(p, end - p,
11267 ", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
11268 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]),
11269 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]),
11270 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]),
11271 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]),
11272 le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL]));
11273
11274 if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
11275 bt->rfk_info.map.timeout = 1;
11276 else
11277 bt->rfk_info.map.timeout = 0;
11278
11279 dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
11280 } else {
11281 p += scnprintf(p, end - p,
11282 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
11283 "[summary]", pfwinfo->cnt_h2c,
11284 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
11285 pfwinfo->event[BTF_EVNT_RPT],
11286 btc->fwinfo.rpt_en_map);
11287 p += scnprintf(p, end - p, " (WL FW report invalid!!)\n");
11288 }
11289
11290 for (i = 0; i < BTC_NCNT_NUM; i++)
11291 cnt_sum += dm->cnt_notify[i];
11292
11293 p += scnprintf(p, end - p,
11294 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11295 "[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11296 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11297
11298 p += scnprintf(p, end - p,
11299 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
11300 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11301 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11302 cnt[BTC_NCNT_WL_STA]);
11303
11304 p += scnprintf(p, end - p,
11305 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11306 "[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
11307 cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
11308 cnt[BTC_NCNT_SPECIAL_PACKET]);
11309
11310 p += scnprintf(p, end - p,
11311 "timer=%d, control=%d, customerize=%d\n",
11312 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11313 cnt[BTC_NCNT_CUSTOMERIZE]);
11314
11315 return p - buf;
11316 }
11317
_show_summary_v5(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11318 static int _show_summary_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11319 {
11320 struct rtw89_btc *btc = &rtwdev->btc;
11321 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11322 struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl;
11323 struct rtw89_btc_rpt_cmn_info *pcinfo;
11324 struct rtw89_btc_cx *cx = &btc->cx;
11325 struct rtw89_btc_dm *dm = &btc->dm;
11326 struct rtw89_btc_wl_info *wl = &cx->wl;
11327 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11328 char *p = buf, *end = buf + bufsz;
11329 u8 i;
11330
11331 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11332 return 0;
11333
11334 p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11335
11336 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11337 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11338 prptctrl = &pfwinfo->rpt_ctrl.finfo.v5;
11339
11340 p += scnprintf(p, end - p,
11341 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
11342 "[summary]", pfwinfo->cnt_h2c,
11343 pfwinfo->cnt_h2c_fail,
11344 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11345 pfwinfo->cnt_c2h,
11346 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11347 le16_to_cpu(prptctrl->rpt_info.len_c2h));
11348
11349 p += scnprintf(p, end - p,
11350 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11351 pfwinfo->event[BTF_EVNT_RPT],
11352 le16_to_cpu(prptctrl->rpt_info.cnt),
11353 le32_to_cpu(prptctrl->rpt_info.en));
11354
11355 if (dm->error.map.wl_fw_hang)
11356 p += scnprintf(p, end - p, " (WL FW Hang!!)");
11357 p += scnprintf(p, end - p, "\n");
11358 p += scnprintf(p, end - p,
11359 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11360 "[mailbox]",
11361 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11362 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11363 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11364
11365 p += scnprintf(p, end - p,
11366 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
11367 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11368 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11369 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11370 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11371 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11372
11373 p += scnprintf(p, end - p,
11374 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
11375 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11376 cx->cnt_wl[BTC_WCNT_RFK_GO],
11377 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11378 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11379
11380 p += scnprintf(p, end - p,
11381 ", bt_rfk[req:%d]",
11382 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11383
11384 p += scnprintf(p, end - p,
11385 ", AOAC[RF_on:%d/RF_off:%d]",
11386 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11387 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11388 } else {
11389 p += scnprintf(p, end - p,
11390 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
11391 "[summary]", pfwinfo->cnt_h2c,
11392 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
11393 }
11394
11395 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
11396 pfwinfo->err[BTFRE_EXCEPTION]) {
11397 p += scnprintf(p, end - p, "\n");
11398 p += scnprintf(p, end - p,
11399 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
11400 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
11401 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
11402 pfwinfo->fver_mismch,
11403 pfwinfo->err[BTFRE_EXCEPTION],
11404 wl->status.map.lps, wl->status.map.rf_off);
11405 }
11406
11407 for (i = 0; i < BTC_NCNT_NUM; i++)
11408 cnt_sum += dm->cnt_notify[i];
11409
11410 p += scnprintf(p, end - p, "\n");
11411 p += scnprintf(p, end - p,
11412 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11413 "[notify_cnt]",
11414 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11415 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11416
11417 p += scnprintf(p, end - p,
11418 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11419 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11420 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11421 cnt[BTC_NCNT_WL_STA]);
11422
11423 p += scnprintf(p, end - p, "\n");
11424 p += scnprintf(p, end - p,
11425 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11426 "[notify_cnt]",
11427 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11428 cnt[BTC_NCNT_SWITCH_BAND],
11429 cnt[BTC_NCNT_SPECIAL_PACKET]);
11430
11431 p += scnprintf(p, end - p,
11432 "timer=%d, control=%d, customerize=%d",
11433 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11434 cnt[BTC_NCNT_CUSTOMERIZE]);
11435
11436 return p - buf;
11437 }
11438
_show_summary_v105(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11439 static int _show_summary_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11440 {
11441 struct rtw89_btc *btc = &rtwdev->btc;
11442 struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11443 struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl;
11444 struct rtw89_btc_rpt_cmn_info *pcinfo;
11445 struct rtw89_btc_cx *cx = &btc->cx;
11446 struct rtw89_btc_dm *dm = &btc->dm;
11447 struct rtw89_btc_wl_info *wl = &cx->wl;
11448 u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11449 char *p = buf, *end = buf + bufsz;
11450 u8 i;
11451
11452 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11453 return 0;
11454
11455 p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11456
11457 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11458 if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11459 prptctrl = &pfwinfo->rpt_ctrl.finfo.v105;
11460
11461 p += scnprintf(p, end - p,
11462 " %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
11463 "[summary]", pfwinfo->cnt_h2c,
11464 pfwinfo->cnt_h2c_fail,
11465 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11466 pfwinfo->cnt_c2h,
11467 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11468 le16_to_cpu(prptctrl->rpt_info.len_c2h));
11469
11470 p += scnprintf(p, end - p,
11471 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11472 pfwinfo->event[BTF_EVNT_RPT],
11473 le16_to_cpu(prptctrl->rpt_info.cnt),
11474 le32_to_cpu(prptctrl->rpt_info.en));
11475
11476 if (dm->error.map.wl_fw_hang)
11477 p += scnprintf(p, end - p, " (WL FW Hang!!)");
11478 p += scnprintf(p, end - p, "\n");
11479 p += scnprintf(p, end - p,
11480 " %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11481 "[mailbox]",
11482 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11483 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11484 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11485
11486 p += scnprintf(p, end - p,
11487 "A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
11488 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11489 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11490 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11491 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11492 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11493
11494 p += scnprintf(p, end - p,
11495 " %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
11496 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11497 cx->cnt_wl[BTC_WCNT_RFK_GO],
11498 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11499 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11500
11501 p += scnprintf(p, end - p,
11502 ", bt_rfk[req:%d]",
11503 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11504
11505 p += scnprintf(p, end - p,
11506 ", AOAC[RF_on:%d/RF_off:%d]",
11507 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11508 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11509 } else {
11510 p += scnprintf(p, end - p,
11511 " %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
11512 "[summary]", pfwinfo->cnt_h2c,
11513 pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
11514 }
11515
11516 if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
11517 pfwinfo->err[BTFRE_EXCEPTION]) {
11518 p += scnprintf(p, end - p, "\n");
11519 p += scnprintf(p, end - p,
11520 " %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
11521 "0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
11522 "[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
11523 pfwinfo->fver_mismch,
11524 pfwinfo->err[BTFRE_EXCEPTION],
11525 wl->status.map.lps, wl->status.map.rf_off);
11526 }
11527
11528 for (i = 0; i < BTC_NCNT_NUM; i++)
11529 cnt_sum += dm->cnt_notify[i];
11530
11531 p += scnprintf(p, end - p, "\n");
11532 p += scnprintf(p, end - p,
11533 " %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11534 "[notify_cnt]",
11535 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11536 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11537
11538 p += scnprintf(p, end - p,
11539 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11540 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11541 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11542 cnt[BTC_NCNT_WL_STA]);
11543
11544 p += scnprintf(p, end - p, "\n");
11545 p += scnprintf(p, end - p,
11546 " %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11547 "[notify_cnt]",
11548 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11549 cnt[BTC_NCNT_SWITCH_BAND],
11550 cnt[BTC_NCNT_SPECIAL_PACKET]);
11551
11552 p += scnprintf(p, end - p,
11553 "timer=%d, control=%d, customerize=%d",
11554 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11555 cnt[BTC_NCNT_CUSTOMERIZE]);
11556
11557 return p - buf;
11558 }
11559
_show_summary_v7(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11560 static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11561 {
11562 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
11563 struct rtw89_btc_fbtc_rpt_ctrl_v7 *prptctrl = NULL;
11564 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11565 struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
11566 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
11567 struct rtw89_btc_wl_info *wl = &cx->wl;
11568 u32 *cnt = rtwdev->btc.dm.cnt_notify;
11569 char *p = buf, *end = buf + bufsz;
11570 u32 cnt_sum = 0;
11571 u8 i;
11572
11573 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11574 return 0;
11575
11576 p += scnprintf(p, end - p, "%s",
11577 "\n\r========== [Statistics] ==========");
11578
11579 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11580 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
11581 !wl->status.map.rf_off) {
11582 prptctrl = &pfwinfo->rpt_ctrl.finfo.v7;
11583
11584 p += scnprintf(p, end - p,
11585 "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d),"
11586 "c2h_cnt=%d(fw_send:%d, len:%d, max:%d), ",
11587 "[summary]", pfwinfo->cnt_h2c,
11588 pfwinfo->cnt_h2c_fail,
11589 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11590 pfwinfo->cnt_c2h,
11591 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11592 le16_to_cpu(prptctrl->rpt_info.len_c2h),
11593 rtwdev->btc.ver->info_buf);
11594
11595 p += scnprintf(p, end - p,
11596 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11597 pfwinfo->event[BTF_EVNT_RPT],
11598 le16_to_cpu(prptctrl->rpt_info.cnt),
11599 le32_to_cpu(prptctrl->rpt_info.en));
11600
11601 if (dm->error.map.wl_fw_hang)
11602 p += scnprintf(p, end - p, " (WL FW Hang!!)");
11603
11604 p += scnprintf(p, end - p,
11605 "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11606 "[mailbox]",
11607 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11608 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11609 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11610
11611 p += scnprintf(p, end - p,
11612 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)",
11613 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11614 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11615 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11616 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11617 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11618
11619 p += scnprintf(p, end - p,
11620 "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
11621 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11622 cx->cnt_wl[BTC_WCNT_RFK_GO],
11623 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11624 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT],
11625 wl->rfk_info.proc_time);
11626
11627 p += scnprintf(p, end - p, ", bt_rfk[req:%d]",
11628 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11629
11630 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]",
11631 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11632 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11633 } else {
11634 p += scnprintf(p, end - p,
11635 "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)",
11636 "[summary]",
11637 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
11638 pfwinfo->cnt_c2h,
11639 wl->status.map.lps, wl->status.map.rf_off);
11640 }
11641
11642 for (i = 0; i < BTC_NCNT_NUM; i++)
11643 cnt_sum += dm->cnt_notify[i];
11644
11645 p += scnprintf(p, end - p,
11646 "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11647 "[notify_cnt]",
11648 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11649 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11650
11651 p += scnprintf(p, end - p,
11652 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11653 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11654 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11655 cnt[BTC_NCNT_WL_STA]);
11656
11657 p += scnprintf(p, end - p,
11658 "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
11659 "[notify_cnt]",
11660 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11661 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
11662 cnt[BTC_NCNT_SPECIAL_PACKET]);
11663
11664 p += scnprintf(p, end - p,
11665 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
11666 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
11667 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
11668 cnt[BTC_NCNT_COUNTRYCODE]);
11669
11670 return p - buf;
11671 }
11672
_show_summary_v8(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11673 static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11674 {
11675 struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
11676 struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11677 struct rtw89_btc_fbtc_rpt_ctrl_v8 *prptctrl = NULL;
11678 struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
11679 struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
11680 struct rtw89_btc_wl_info *wl = &cx->wl;
11681 u32 *cnt = rtwdev->btc.dm.cnt_notify;
11682 char *p = buf, *end = buf + bufsz;
11683 u32 cnt_sum = 0;
11684 u8 i;
11685
11686 if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11687 return 0;
11688
11689 p += scnprintf(p, end - p, "%s",
11690 "\n\r========== [Statistics] ==========");
11691
11692 pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11693 if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
11694 !wl->status.map.rf_off) {
11695 prptctrl = &pfwinfo->rpt_ctrl.finfo.v8;
11696
11697 p += scnprintf(p, end - p,
11698 "\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ",
11699 "[summary]", pfwinfo->cnt_h2c,
11700 pfwinfo->cnt_h2c_fail,
11701 le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11702 pfwinfo->cnt_c2h,
11703 le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11704 le16_to_cpu(prptctrl->rpt_info.len_c2h),
11705 (prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l,
11706 rtwdev->btc.ver->info_buf);
11707
11708 p += scnprintf(p, end - p,
11709 "rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11710 pfwinfo->event[BTF_EVNT_RPT],
11711 le16_to_cpu(prptctrl->rpt_info.cnt),
11712 le32_to_cpu(prptctrl->rpt_info.en));
11713
11714 if (dm->error.map.wl_fw_hang)
11715 p += scnprintf(p, end - p, " (WL FW Hang!!)");
11716
11717 p += scnprintf(p, end - p,
11718 "\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11719 "[mailbox]",
11720 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11721 le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11722 le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11723
11724 p += scnprintf(p, end - p,
11725 "A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)",
11726 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11727 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11728 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11729 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11730 le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11731
11732 p += scnprintf(p, end - p,
11733 "\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
11734 "[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11735 cx->cnt_wl[BTC_WCNT_RFK_GO],
11736 cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11737 cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT],
11738 wl->rfk_info.proc_time);
11739
11740 p += scnprintf(p, end - p, ", bt_rfk[req:%d]",
11741 le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11742
11743 p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]",
11744 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11745 le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11746 } else {
11747 p += scnprintf(p, end - p,
11748 "\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)",
11749 "[summary]",
11750 pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
11751 pfwinfo->cnt_c2h,
11752 wl->status.map.lps, wl->status.map.rf_off);
11753 }
11754
11755 for (i = 0; i < BTC_NCNT_NUM; i++)
11756 cnt_sum += dm->cnt_notify[i];
11757
11758 p += scnprintf(p, end - p,
11759 "\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11760 "[notify_cnt]",
11761 cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11762 cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11763
11764 p += scnprintf(p, end - p,
11765 "power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11766 cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11767 cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11768 cnt[BTC_NCNT_WL_STA]);
11769
11770 p += scnprintf(p, end - p,
11771 "\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
11772 "[notify_cnt]",
11773 cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11774 cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
11775 cnt[BTC_NCNT_SPECIAL_PACKET]);
11776
11777 p += scnprintf(p, end - p,
11778 "timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
11779 cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
11780 rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
11781 cnt[BTC_NCNT_COUNTRYCODE]);
11782
11783 return p - buf;
11784 }
11785
rtw89_btc_dump_info(struct rtw89_dev * rtwdev,char * buf,size_t bufsz)11786 ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11787 {
11788 struct rtw89_btc *btc = &rtwdev->btc;
11789 struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver;
11790 const struct rtw89_btc_ver *ver = btc->ver;
11791 struct rtw89_btc_dm *dm = &btc->dm;
11792 char *p = buf, *end = buf + bufsz;
11793
11794 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
11795
11796 p += scnprintf(p, end - p,
11797 "\n\n\n** Page:%3d/RunCNT:%3d **",
11798 dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO],
11799 dm->cnt_dm[BTC_DCNT_RUN]);
11800 p += scnprintf(p, end - p,
11801 "\n========== [BTC FEATURE SUB VER] ==========");
11802 p += scnprintf(p, end - p,
11803 "\n %-15s : fcxbtcrpt[%d/%d], fcxtdma[%d/%d], fcxslots[%d/%d], fcxcysta[%d/%d]",
11804 "[FW/DRV]", fwsubver->fcxbtcrpt, ver->fcxbtcrpt,
11805 fwsubver->fcxtdma, ver->fcxtdma, fwsubver->fcxslots,
11806 ver->fcxslots, fwsubver->fcxcysta, ver->fcxcysta);
11807 p += scnprintf(p, end - p,
11808 "\n %-15s : fcxstep[%d/%d], fcxnullsta[%d/%d], fcxmreg[%d/%d], fcxgpiodbg[%d/%d]",
11809 "[FW/DRV]", fwsubver->fcxstep, ver->fcxstep,
11810 fwsubver->fcxnullsta, ver->fcxnullsta, fwsubver->fcxmreg,
11811 ver->fcxmreg, fwsubver->fcxgpiodbg, ver->fcxgpiodbg);
11812 p += scnprintf(p, end - p,
11813 "\n %-15s : fcxbtver[%d/%d], fcxbtscan[%d/%d], fcxbtafh[%d/%d], fcxbtdevinfo[%d/%d]",
11814 "[FW/DRV]", fwsubver->fcxbtver, ver->fcxbtver,
11815 fwsubver->fcxbtscan, ver->fcxbtscan, fwsubver->fcxbtafh,
11816 ver->fcxbtafh, fwsubver->fcxbtdevinfo, ver->fcxbtdevinfo);
11817 p += scnprintf(p, end - p,
11818 "\n %-15s : fcxosi[%d/%d], fcxmlo[%d/%d],",
11819 "[FW/DRV]", fwsubver->fcxosi, ver->fcxosi,
11820 fwsubver->fcxmlo, ver->fcxmlo);
11821
11822 p += _show_cx_info(rtwdev, p, end - p);
11823 p += _show_wl_info(rtwdev, p, end - p);
11824 p += _show_bt_info(rtwdev, p, end - p);
11825 p += _show_dm_info(rtwdev, p, end - p);
11826 p += _show_fw_dm_msg(rtwdev, p, end - p);
11827
11828 if (ver->fcxmreg == 1)
11829 p += _show_mreg_v1(rtwdev, p, end - p);
11830 else if (ver->fcxmreg == 2)
11831 p += _show_mreg_v2(rtwdev, p, end - p);
11832 else if (ver->fcxmreg == 7)
11833 p += _show_mreg_v7(rtwdev, p, end - p);
11834
11835 p += _show_gpio_dbg(rtwdev, p, end - p);
11836
11837 if (ver->fcxbtcrpt == 1)
11838 p += _show_summary_v1(rtwdev, p, end - p);
11839 else if (ver->fcxbtcrpt == 4)
11840 p += _show_summary_v4(rtwdev, p, end - p);
11841 else if (ver->fcxbtcrpt == 5)
11842 p += _show_summary_v5(rtwdev, p, end - p);
11843 else if (ver->fcxbtcrpt == 105)
11844 p += _show_summary_v105(rtwdev, p, end - p);
11845 else if (ver->fcxbtcrpt == 7)
11846 p += _show_summary_v7(rtwdev, p, end - p);
11847 else if (ver->fcxbtcrpt == 8)
11848 p += _show_summary_v8(rtwdev, p, end - p);
11849
11850 return p - buf;
11851 }
11852
rtw89_coex_recognize_ver(struct rtw89_dev * rtwdev)11853 void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev)
11854 {
11855 const struct rtw89_chip_info *chip = rtwdev->chip;
11856 struct rtw89_btc *btc = &rtwdev->btc;
11857 const struct rtw89_btc_ver *btc_ver_def;
11858 const struct rtw89_fw_suit *fw_suit;
11859 u32 suit_ver_code;
11860 int i;
11861
11862 fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL);
11863 suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit);
11864
11865 for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) {
11866 btc_ver_def = &rtw89_btc_ver_defs[i];
11867
11868 if (chip->chip_id != btc_ver_def->chip_id)
11869 continue;
11870
11871 if (suit_ver_code >= btc_ver_def->fw_ver_code) {
11872 btc->ver = btc_ver_def;
11873 goto out;
11874 }
11875 }
11876
11877 btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX];
11878
11879 out:
11880 rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n",
11881 (int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code);
11882 }
11883
rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev * rtwdev,u32 ms)11884 void rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev *rtwdev, u32 ms)
11885 {
11886 struct rtw89_btc_bt_link_info *bt_linfo = &rtwdev->btc.cx.bt.link_info;
11887 struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
11888
11889 if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags))
11890 return;
11891
11892 if (!a2dp.exist)
11893 return;
11894
11895 fsleep(ms * 1000);
11896 }
11897 EXPORT_SYMBOL(rtw89_btc_ntfy_preserve_bt_time);
11898
rtw89_btc_ntfy_conn_rfk(struct rtw89_dev * rtwdev,bool state)11899 void rtw89_btc_ntfy_conn_rfk(struct rtw89_dev *rtwdev, bool state)
11900 {
11901 rtwdev->btc.cx.wl.rfk_info.con_rfk = state;
11902 }
11903 EXPORT_SYMBOL(rtw89_btc_ntfy_conn_rfk);
11904