Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/rtw89/coex.c
106275 views
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, 0x55555555, SLOT_MIX),
97
[CXST_WLK] = __DEF_FBTC_SLOT(250, 0xea5a5a5a, SLOT_MIX),
98
[CXST_W1FDD] = __DEF_FBTC_SLOT(50, 0xffffffff, SLOT_ISO),
99
[CXST_B1FDD] = __DEF_FBTC_SLOT(50, 0xffffdfff, SLOT_ISO),
100
};
101
102
static const u32 cxtbl[] = {
103
0xffffffff, /* 0 */
104
0xaaaaaaaa, /* 1 */
105
0xe5555555, /* 2 */
106
0xee555555, /* 3 */
107
0xd5555555, /* 4 */
108
0x5a5a5a5a, /* 5 */
109
0xfa5a5a5a, /* 6 */
110
0xda5a5a5a, /* 7 */
111
0xea5a5a5a, /* 8 */
112
0x6a5a5aaa, /* 9 */
113
0x6a5a6a5a, /* 10 */
114
0x6a5a6aaa, /* 11 */
115
0x6afa5afa, /* 12 */
116
0xaaaa5aaa, /* 13 */
117
0xaaffffaa, /* 14 */
118
0xaa5555aa, /* 15 */
119
0xfafafafa, /* 16 */
120
0xffffddff, /* 17 */
121
0xdaffdaff, /* 18 */
122
0xfafadafa, /* 19 */
123
0xea6a6a6a, /* 20 */
124
0xea55556a, /* 21 */
125
0xaafafafa, /* 22 */
126
0xfafaaafa, /* 23 */
127
0xfafffaff, /* 24 */
128
0xea6a5a5a, /* 25 */
129
0xfaff5aff, /* 26 */
130
0xffffdfff, /* 27 */
131
0xe6555555, /* 28 */
132
};
133
134
static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = {
135
/* firmware version must be in decreasing order for each chip */
136
{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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 */
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
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
_slot_set_dur(btc, CXST_EBT, dur_2);
4157
break;
4158
case BTC_CXP_OFFE_DEF2:
4159
_slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
4160
_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4161
s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4162
_slot_set_le(btc, CXST_EBT, s_def[CXST_EBT].dur,
4163
s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4164
_slot_set_le(btc, CXST_ENULL, s_def[CXST_ENULL].dur,
4165
s_def[CXST_ENULL].cxtbl, s_def[CXST_ENULL].cxtype);
4166
_slot_set_dur(btc, CXST_EBT, dur_2);
4167
break;
4168
case BTC_CXP_OFFE_2GBWMIXB:
4169
if (a2dp->exist)
4170
_slot_set(btc, CXST_E2G, 5, cxtbl[2], SLOT_MIX);
4171
else
4172
_slot_set(btc, CXST_E2G, 5, tbl_w1, SLOT_MIX);
4173
_slot_set_le(btc, CXST_EBT, cpu_to_le16(40),
4174
s_def[CXST_EBT].cxtbl, s_def[CXST_EBT].cxtype);
4175
_slot_set_dur(btc, CXST_EBT, dur_2);
4176
break;
4177
case BTC_CXP_OFFE_WL: /* for 4-way */
4178
_slot_set(btc, CXST_E2G, 5, cxtbl[1], SLOT_MIX);
4179
_slot_set(btc, CXST_EBT, 5, cxtbl[1], SLOT_MIX);
4180
break;
4181
default:
4182
break;
4183
}
4184
_slot_set_le(btc, CXST_E5G, s_def[CXST_E5G].dur,
4185
s_def[CXST_E5G].cxtbl, s_def[CXST_E5G].cxtype);
4186
_slot_set_le(btc, CXST_OFF, s_def[CXST_OFF].dur,
4187
s_def[CXST_OFF].cxtbl, s_def[CXST_OFF].cxtype);
4188
break;
4189
case BTC_CXP_FIX: /* TDMA Fix-Slot */
4190
_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4191
*t = t_def[CXTD_FIX];
4192
4193
switch (policy_type) {
4194
case BTC_CXP_FIX_TD3030:
4195
_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4196
_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4197
break;
4198
case BTC_CXP_FIX_TD5050:
4199
_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4200
_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
4201
break;
4202
case BTC_CXP_FIX_TD2030:
4203
_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4204
_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4205
break;
4206
case BTC_CXP_FIX_TD4010:
4207
_slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
4208
_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4209
break;
4210
case BTC_CXP_FIX_TD4010ISO:
4211
_slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
4212
_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4213
break;
4214
case BTC_CXP_FIX_TD4010ISO_DL:
4215
_slot_set(btc, CXST_W1, 40, cxtbl[25], SLOT_ISO);
4216
_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_ISO);
4217
break;
4218
case BTC_CXP_FIX_TD4010ISO_UL:
4219
_slot_set(btc, CXST_W1, 40, cxtbl[20], SLOT_ISO);
4220
_slot_set(btc, CXST_B1, 10, cxtbl[25], SLOT_MIX);
4221
break;
4222
case BTC_CXP_FIX_TD7010:
4223
_slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
4224
_slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
4225
break;
4226
case BTC_CXP_FIX_TD2060:
4227
_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4228
_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4229
break;
4230
case BTC_CXP_FIX_TD3060:
4231
_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4232
_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4233
break;
4234
case BTC_CXP_FIX_TD2080:
4235
_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4236
_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
4237
break;
4238
case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
4239
_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4240
tbl_w1, SLOT_ISO);
4241
_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4242
tbl_b1, SLOT_MIX);
4243
break;
4244
default:
4245
break;
4246
}
4247
break;
4248
case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
4249
_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4250
*t = t_def[CXTD_PFIX];
4251
4252
switch (policy_type) {
4253
case BTC_CXP_PFIX_TD3030:
4254
_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4255
_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4256
break;
4257
case BTC_CXP_PFIX_TD5050:
4258
_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4259
_slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
4260
break;
4261
case BTC_CXP_PFIX_TD2030:
4262
_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4263
_slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
4264
break;
4265
case BTC_CXP_PFIX_TD2060:
4266
_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4267
_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4268
break;
4269
case BTC_CXP_PFIX_TD3070:
4270
_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4271
_slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
4272
break;
4273
case BTC_CXP_PFIX_TD2080:
4274
_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4275
_slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
4276
break;
4277
case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */
4278
_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4279
tbl_w1, SLOT_ISO);
4280
_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4281
tbl_b1, SLOT_MIX);
4282
break;
4283
default:
4284
break;
4285
}
4286
break;
4287
case BTC_CXP_AUTO: /* TDMA Auto-Slot */
4288
_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4289
*t = t_def[CXTD_AUTO];
4290
4291
switch (policy_type) {
4292
case BTC_CXP_AUTO_TD50B1:
4293
_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4294
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4295
break;
4296
case BTC_CXP_AUTO_TD60B1:
4297
_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4298
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4299
break;
4300
case BTC_CXP_AUTO_TD20B1:
4301
_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4302
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4303
break;
4304
case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
4305
_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4306
tbl_w1, SLOT_ISO);
4307
_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4308
tbl_b1, SLOT_MIX);
4309
break;
4310
default:
4311
break;
4312
}
4313
break;
4314
case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
4315
_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4316
*t = t_def[CXTD_PAUTO];
4317
4318
switch (policy_type) {
4319
case BTC_CXP_PAUTO_TD50B1:
4320
_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4321
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4322
break;
4323
case BTC_CXP_PAUTO_TD60B1:
4324
_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4325
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4326
break;
4327
case BTC_CXP_PAUTO_TD20B1:
4328
_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4329
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4330
break;
4331
case BTC_CXP_PAUTO_TDW1B1:
4332
_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4333
tbl_w1, SLOT_ISO);
4334
_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4335
tbl_b1, SLOT_MIX);
4336
break;
4337
default:
4338
break;
4339
}
4340
break;
4341
case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
4342
_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4343
*t = t_def[CXTD_AUTO2];
4344
4345
switch (policy_type) {
4346
case BTC_CXP_AUTO2_TD3050:
4347
_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4348
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4349
_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4350
break;
4351
case BTC_CXP_AUTO2_TD3070:
4352
_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4353
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4354
_slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
4355
break;
4356
case BTC_CXP_AUTO2_TD5050:
4357
_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4358
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4359
_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4360
break;
4361
case BTC_CXP_AUTO2_TD6060:
4362
_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4363
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4364
_slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
4365
break;
4366
case BTC_CXP_AUTO2_TD2080:
4367
_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4368
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4369
_slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
4370
break;
4371
case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
4372
_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4373
tbl_w1, SLOT_ISO);
4374
_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4375
tbl_b1, SLOT_MIX);
4376
_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
4377
tbl_b4, SLOT_MIX);
4378
break;
4379
default:
4380
break;
4381
}
4382
break;
4383
case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
4384
_write_scbd(rtwdev, BTC_WSCB_TDMA, true);
4385
*t = t_def[CXTD_PAUTO2];
4386
4387
switch (policy_type) {
4388
case BTC_CXP_PAUTO2_TD3050:
4389
_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4390
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4391
_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4392
break;
4393
case BTC_CXP_PAUTO2_TD3070:
4394
_slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
4395
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4396
_slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
4397
break;
4398
case BTC_CXP_PAUTO2_TD5050:
4399
_slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
4400
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4401
_slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
4402
break;
4403
case BTC_CXP_PAUTO2_TD6060:
4404
_slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
4405
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4406
_slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
4407
break;
4408
case BTC_CXP_PAUTO2_TD2080:
4409
_slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
4410
_slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
4411
_slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
4412
break;
4413
case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
4414
_slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
4415
tbl_w1, SLOT_ISO);
4416
_slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
4417
tbl_b1, SLOT_MIX);
4418
_slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
4419
tbl_b4, SLOT_MIX);
4420
break;
4421
default:
4422
break;
4423
}
4424
break;
4425
}
4426
4427
if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) {
4428
null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) |
4429
FIELD_PREP(0xf0, dm->wl_scc.null_role2);
4430
_tdma_set_flctrl_role(btc, null_role);
4431
}
4432
4433
/* enter leak_slot after each null-1 */
4434
if (dm->leak_ap && dm->tdma.leak_n > 1)
4435
_tdma_set_lek(btc, 1);
4436
4437
if (dm->tdma_instant_excute) {
4438
btc->dm.tdma.option_ctrl |= BIT(0);
4439
btc->update_policy_force = true;
4440
}
4441
}
4442
EXPORT_SYMBOL(rtw89_btc_set_policy_v1);
4443
4444
static void _set_bt_plut(struct rtw89_dev *rtwdev, u8 phy_map,
4445
u8 tx_val, u8 rx_val)
4446
{
4447
struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
4448
struct rtw89_mac_ax_plt plt;
4449
4450
plt.tx = tx_val;
4451
plt.rx = rx_val;
4452
4453
if (rtwdev->btc.ver->fwlrole == 8) {
4454
plt.band = wl->pta_req_mac;
4455
if (wl->bt_polut_type[plt.band] == tx_val)
4456
return;
4457
4458
wl->bt_polut_type[plt.band] = tx_val;
4459
rtw89_mac_cfg_plt(rtwdev, &plt);
4460
} else {
4461
plt.band = RTW89_MAC_0;
4462
4463
if (phy_map & BTC_PHY_0)
4464
rtw89_mac_cfg_plt(rtwdev, &plt);
4465
4466
if (!rtwdev->dbcc_en)
4467
return;
4468
4469
plt.band = RTW89_MAC_1;
4470
if (phy_map & BTC_PHY_1)
4471
rtw89_mac_cfg_plt(rtwdev, &plt);
4472
}
4473
}
4474
4475
static void _set_ant_v0(struct rtw89_dev *rtwdev, bool force_exec,
4476
u8 phy_map, u8 type)
4477
{
4478
struct rtw89_btc *btc = &rtwdev->btc;
4479
struct rtw89_btc_dm *dm = &btc->dm;
4480
struct rtw89_btc_cx *cx = &btc->cx;
4481
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4482
struct rtw89_btc_bt_info *bt = &cx->bt;
4483
struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4484
u8 gnt_wl_ctrl, gnt_bt_ctrl, plt_ctrl, i, b2g = 0;
4485
bool dbcc_chg = false;
4486
u32 ant_path_type;
4487
4488
ant_path_type = ((phy_map << 8) + type);
4489
4490
if (btc->ver->fwlrole == 1)
4491
dbcc_chg = wl->role_info_v1.dbcc_chg;
4492
else if (btc->ver->fwlrole == 2)
4493
dbcc_chg = wl->role_info_v2.dbcc_chg;
4494
else if (btc->ver->fwlrole == 7)
4495
dbcc_chg = wl->role_info_v7.dbcc_chg;
4496
else if (btc->ver->fwlrole == 8)
4497
dbcc_chg = wl->role_info_v8.dbcc_chg;
4498
4499
if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
4500
btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
4501
btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || dbcc_chg)
4502
force_exec = FC_EXEC;
4503
4504
if (!force_exec && ant_path_type == dm->set_ant_path) {
4505
rtw89_debug(rtwdev, RTW89_DBG_BTC,
4506
"[BTC], %s(): return by no change!!\n",
4507
__func__);
4508
return;
4509
} else if (bt->rfk_info.map.run) {
4510
rtw89_debug(rtwdev, RTW89_DBG_BTC,
4511
"[BTC], %s(): return by bt rfk!!\n", __func__);
4512
return;
4513
} else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
4514
wl->rfk_info.state != BTC_WRFK_STOP) {
4515
rtw89_debug(rtwdev, RTW89_DBG_BTC,
4516
"[BTC], %s(): return by wl rfk!!\n", __func__);
4517
return;
4518
}
4519
4520
dm->set_ant_path = ant_path_type;
4521
4522
rtw89_debug(rtwdev,
4523
RTW89_DBG_BTC,
4524
"[BTC], %s(): path=0x%x, set_type=0x%x\n",
4525
__func__, phy_map, dm->set_ant_path & 0xff);
4526
4527
switch (type) {
4528
case BTC_ANT_WPOWERON:
4529
rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4530
break;
4531
case BTC_ANT_WINIT:
4532
if (bt->enable.now)
4533
_set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
4534
else
4535
_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4536
4537
rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4538
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_BT, BTC_PLT_BT);
4539
break;
4540
case BTC_ANT_WONLY:
4541
_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4542
rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4543
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4544
break;
4545
case BTC_ANT_WOFF:
4546
rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4547
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4548
break;
4549
case BTC_ANT_W2G:
4550
rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4551
if (rtwdev->dbcc_en) {
4552
for (i = 0; i < RTW89_PHY_NUM; i++) {
4553
b2g = (wl_dinfo->real_band[i] == RTW89_BAND_2G);
4554
4555
gnt_wl_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
4556
gnt_bt_ctrl = b2g ? BTC_GNT_HW : BTC_GNT_SW_HI;
4557
/* BT should control by GNT_BT if WL_2G at S0 */
4558
if (i == 1 &&
4559
wl_dinfo->real_band[0] == RTW89_BAND_2G &&
4560
wl_dinfo->real_band[1] == RTW89_BAND_5G)
4561
gnt_bt_ctrl = BTC_GNT_HW;
4562
_set_gnt(rtwdev, BIT(i), gnt_wl_ctrl, gnt_bt_ctrl);
4563
plt_ctrl = b2g ? BTC_PLT_BT : BTC_PLT_NONE;
4564
_set_bt_plut(rtwdev, BIT(i),
4565
plt_ctrl, plt_ctrl);
4566
}
4567
} else {
4568
_set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
4569
_set_bt_plut(rtwdev, BTC_PHY_ALL,
4570
BTC_PLT_BT, BTC_PLT_BT);
4571
}
4572
break;
4573
case BTC_ANT_W5G:
4574
rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4575
_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW);
4576
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4577
break;
4578
case BTC_ANT_W25G:
4579
rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4580
_set_gnt(rtwdev, phy_map, BTC_GNT_HW, BTC_GNT_HW);
4581
_set_bt_plut(rtwdev, BTC_PHY_ALL,
4582
BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
4583
break;
4584
case BTC_ANT_FREERUN:
4585
rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4586
_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI);
4587
_set_bt_plut(rtwdev, BTC_PHY_ALL, BTC_PLT_NONE, BTC_PLT_NONE);
4588
break;
4589
case BTC_ANT_WRFK:
4590
case BTC_ANT_WRFK2:
4591
rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_WL);
4592
_set_gnt(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO);
4593
_set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
4594
break;
4595
case BTC_ANT_BRFK:
4596
rtw89_chip_cfg_ctrl_path(rtwdev, BTC_CTRL_BY_BT);
4597
_set_gnt(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI);
4598
_set_bt_plut(rtwdev, phy_map, BTC_PLT_NONE, BTC_PLT_NONE);
4599
break;
4600
default:
4601
break;
4602
}
4603
}
4604
4605
static void _set_ant_v1(struct rtw89_dev *rtwdev, bool force_exec,
4606
u8 phy_map, u8 type)
4607
{
4608
struct rtw89_btc *btc = &rtwdev->btc;
4609
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4610
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4611
struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
4612
u32 ant_path_type = rtw89_get_antpath_type(phy_map, type);
4613
struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
4614
struct rtw89_btc_dm *dm = &btc->dm;
4615
u8 gwl = BTC_GNT_HW;
4616
4617
if (btc->dm.run_reason == BTC_RSN_NTFY_POWEROFF ||
4618
btc->dm.run_reason == BTC_RSN_NTFY_RADIO_STATE ||
4619
btc->dm.run_reason == BTC_RSN_CMD_SET_COEX || wl_rinfo->dbcc_chg)
4620
force_exec = FC_EXEC;
4621
4622
if (wl_rinfo->link_mode != BTC_WLINK_25G_MCC &&
4623
btc->dm.wl_btg_rx == 2)
4624
force_exec = FC_EXEC;
4625
4626
if (!force_exec && ant_path_type == dm->set_ant_path) {
4627
rtw89_debug(rtwdev, RTW89_DBG_BTC,
4628
"[BTC], %s(): return by no change!!\n",
4629
__func__);
4630
return;
4631
} else if (bt->rfk_info.map.run) {
4632
rtw89_debug(rtwdev, RTW89_DBG_BTC,
4633
"[BTC], %s(): return by bt rfk!!\n", __func__);
4634
return;
4635
} else if (btc->dm.run_reason != BTC_RSN_NTFY_WL_RFK &&
4636
wl->rfk_info.state != BTC_WRFK_STOP) {
4637
rtw89_debug(rtwdev, RTW89_DBG_BTC,
4638
"[BTC], %s(): return by wl rfk!!\n", __func__);
4639
return;
4640
}
4641
4642
dm->set_ant_path = ant_path_type;
4643
4644
rtw89_debug(rtwdev, RTW89_DBG_BTC,
4645
"[BTC], %s(): path=0x%x, set_type=0x%x\n",
4646
__func__, phy_map, dm->set_ant_path & 0xff);
4647
4648
switch (type) {
4649
case BTC_ANT_WINIT:
4650
/* To avoid BT MP driver case (bt_enable but no mailbox) */
4651
if (bt->enable.now && bt->run_patch_code)
4652
_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
4653
BTC_WLACT_SW_LO);
4654
else
4655
_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4656
BTC_WLACT_SW_HI);
4657
break;
4658
case BTC_ANT_WONLY:
4659
_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4660
BTC_WLACT_SW_HI);
4661
break;
4662
case BTC_ANT_WOFF:
4663
_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_LO, BTC_GNT_SW_HI,
4664
BTC_WLACT_SW_LO);
4665
break;
4666
case BTC_ANT_W2G:
4667
case BTC_ANT_W25G:
4668
if (wl_rinfo->dbcc_en) {
4669
if (wl_dinfo->real_band[RTW89_PHY_0] == RTW89_BAND_2G)
4670
gwl = BTC_GNT_HW;
4671
else
4672
gwl = BTC_GNT_SW_HI;
4673
_set_gnt_v1(rtwdev, BTC_PHY_0, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4674
4675
if (wl_dinfo->real_band[RTW89_PHY_1] == RTW89_BAND_2G)
4676
gwl = BTC_GNT_HW;
4677
else
4678
gwl = BTC_GNT_SW_HI;
4679
_set_gnt_v1(rtwdev, BTC_PHY_1, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4680
} else {
4681
gwl = BTC_GNT_HW;
4682
_set_gnt_v1(rtwdev, phy_map, gwl, BTC_GNT_HW, BTC_WLACT_HW);
4683
}
4684
break;
4685
case BTC_ANT_W5G:
4686
_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_HW, BTC_WLACT_HW);
4687
break;
4688
case BTC_ANT_FREERUN:
4689
_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_HI,
4690
BTC_WLACT_SW_LO);
4691
break;
4692
case BTC_ANT_WRFK:
4693
_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4694
BTC_WLACT_HW);
4695
break;
4696
case BTC_ANT_WRFK2:
4697
_set_gnt_v1(rtwdev, phy_map, BTC_GNT_SW_HI, BTC_GNT_SW_LO,
4698
BTC_WLACT_SW_HI); /* no BT-Tx */
4699
break;
4700
default:
4701
return;
4702
}
4703
4704
_set_bt_plut(rtwdev, phy_map, BTC_PLT_GNT_WL, BTC_PLT_GNT_WL);
4705
}
4706
4707
static void _set_ant(struct rtw89_dev *rtwdev, bool force_exec,
4708
u8 phy_map, u8 type)
4709
{
4710
if (rtwdev->chip->chip_id == RTL8922A)
4711
_set_ant_v1(rtwdev, force_exec, phy_map, type);
4712
else
4713
_set_ant_v0(rtwdev, force_exec, phy_map, type);
4714
}
4715
4716
static void _action_wl_only(struct rtw89_dev *rtwdev)
4717
{
4718
_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
4719
_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_ONLY);
4720
}
4721
4722
static void _action_wl_init(struct rtw89_dev *rtwdev)
4723
{
4724
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4725
4726
_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WINIT);
4727
_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_INIT);
4728
}
4729
4730
static void _action_wl_off(struct rtw89_dev *rtwdev, u8 mode)
4731
{
4732
struct rtw89_btc *btc = &rtwdev->btc;
4733
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4734
4735
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4736
4737
if (wl->status.map.rf_off || btc->dm.bt_only) {
4738
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_WOFF);
4739
} else if (wl->status.map.lps == BTC_LPS_RF_ON) {
4740
if (mode == BTC_WLINK_5G)
4741
_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
4742
else
4743
_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4744
}
4745
4746
if (mode == BTC_WLINK_5G) {
4747
_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OFF);
4748
} else if (wl->status.map.lps == BTC_LPS_RF_ON) {
4749
if (btc->cx.bt.link_info.a2dp_desc.active)
4750
_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
4751
else
4752
_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_WL_OFF);
4753
} else {
4754
_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_OFF);
4755
}
4756
}
4757
4758
static void _action_freerun(struct rtw89_dev *rtwdev)
4759
{
4760
struct rtw89_btc *btc = &rtwdev->btc;
4761
4762
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4763
4764
_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_FREERUN);
4765
_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_FREERUN);
4766
4767
btc->dm.freerun = true;
4768
}
4769
4770
static void _action_bt_whql(struct rtw89_dev *rtwdev)
4771
{
4772
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4773
4774
_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4775
_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_WHQL);
4776
}
4777
4778
static void _action_bt_off(struct rtw89_dev *rtwdev)
4779
{
4780
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
4781
4782
_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WONLY);
4783
_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_OFF);
4784
}
4785
4786
static void _action_bt_idle(struct rtw89_dev *rtwdev)
4787
{
4788
struct rtw89_btc *btc = &rtwdev->btc;
4789
struct rtw89_btc_bt_link_info *b = &btc->cx.bt.link_info;
4790
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4791
4792
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4793
4794
if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
4795
switch (btc->cx.state_map) {
4796
case BTC_WBUSY_BNOSCAN: /*wl-busy + bt idle*/
4797
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-idle */
4798
if (b->status.map.connect)
4799
_set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_IDLE);
4800
else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
4801
_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_DL, BTC_ACT_BT_IDLE);
4802
else
4803
_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO_UL, BTC_ACT_BT_IDLE);
4804
break;
4805
case BTC_WBUSY_BSCAN: /*wl-busy + bt-inq */
4806
_set_policy(rtwdev, BTC_CXP_PFIX_TD5050,
4807
BTC_ACT_BT_IDLE);
4808
break;
4809
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq */
4810
_set_policy(rtwdev, BTC_CXP_FIX_TD5050,
4811
BTC_ACT_BT_IDLE);
4812
break;
4813
case BTC_WLINKING: /* wl-connecting + bt-inq or bt-idle */
4814
_set_policy(rtwdev, BTC_CXP_FIX_TD7010,
4815
BTC_ACT_BT_IDLE);
4816
break;
4817
case BTC_WIDLE: /* wl-idle + bt-idle */
4818
_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_IDLE);
4819
break;
4820
}
4821
} else { /* dedicated-antenna */
4822
_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_BT_IDLE);
4823
}
4824
}
4825
4826
static void _action_bt_hfp(struct rtw89_dev *rtwdev)
4827
{
4828
struct rtw89_btc *btc = &rtwdev->btc;
4829
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4830
4831
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4832
4833
if (btc->ant_type == BTC_ANT_SHARED) {
4834
if (btc->cx.wl.status.map._4way) {
4835
_set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_BT_HFP);
4836
} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4837
btc->cx.bt.scan_rx_low_pri = true;
4838
_set_policy(rtwdev, BTC_CXP_OFF_BWB2, BTC_ACT_BT_HFP);
4839
} else {
4840
_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
4841
}
4842
} else {
4843
if (wl->bg_mode)
4844
_set_policy(rtwdev, BTC_CXP_OFF_BWB1, BTC_ACT_BT_HFP);
4845
else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
4846
_set_policy(rtwdev, BTC_CXP_OFF_EQ5, BTC_ACT_BT_HFP);
4847
else
4848
_set_policy(rtwdev, BTC_CXP_OFF_EQ2, BTC_ACT_BT_HFP);
4849
}
4850
}
4851
4852
static void _action_bt_hid(struct rtw89_dev *rtwdev)
4853
{
4854
const struct rtw89_chip_info *chip = rtwdev->chip;
4855
struct rtw89_btc *btc = &rtwdev->btc;
4856
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4857
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
4858
struct rtw89_btc_bt_hid_desc *hid = &bt->link_info.hid_desc;
4859
u16 policy_type = BTC_CXP_OFF_BT;
4860
4861
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4862
4863
if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
4864
if (wl->status.map._4way) {
4865
policy_type = BTC_CXP_OFF_WL;
4866
} else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL)) {
4867
btc->cx.bt.scan_rx_low_pri = true;
4868
if (hid->type & BTC_HID_BLE)
4869
policy_type = BTC_CXP_OFF_BWB0;
4870
else
4871
policy_type = BTC_CXP_OFF_BWB2;
4872
} else if (hid->type == BTC_HID_218) {
4873
bt->scan_rx_low_pri = true;
4874
policy_type = BTC_CXP_OFF_BWB2;
4875
} else if (chip->para_ver == 0x1) {
4876
policy_type = BTC_CXP_OFF_BWB3;
4877
} else {
4878
policy_type = BTC_CXP_OFF_BWB1;
4879
}
4880
} else { /* dedicated-antenna */
4881
if (wl->bg_mode)
4882
policy_type = BTC_CXP_OFF_BWB1;
4883
else if (wl->status.map.traffic_dir & BIT(RTW89_TFC_UL))
4884
policy_type = BTC_CXP_OFF_EQ4;
4885
else
4886
policy_type = BTC_CXP_OFF_EQ3;
4887
}
4888
4889
_set_policy(rtwdev, policy_type, BTC_ACT_BT_HID);
4890
}
4891
4892
static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
4893
{
4894
struct rtw89_btc *btc = &rtwdev->btc;
4895
struct rtw89_btc_dm *dm = &btc->dm;
4896
4897
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4898
4899
dm->slot_dur[CXST_W1] = 20;
4900
dm->slot_dur[CXST_B1] = BTC_B1_MAX;
4901
4902
switch (btc->cx.state_map) {
4903
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP */
4904
_set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
4905
break;
4906
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
4907
_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3050, BTC_ACT_BT_A2DP);
4908
break;
4909
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP */
4910
_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP);
4911
break;
4912
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP */
4913
case BTC_WLINKING: /* wl-connecting + bt-A2DP */
4914
if (btc->cx.wl.rfk_info.con_rfk)
4915
_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP);
4916
else
4917
_set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP);
4918
break;
4919
case BTC_WIDLE: /* wl-idle + bt-A2DP */
4920
_set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP);
4921
break;
4922
}
4923
}
4924
4925
static void _action_bt_a2dpsink(struct rtw89_dev *rtwdev)
4926
{
4927
struct rtw89_btc *btc = &rtwdev->btc;
4928
4929
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4930
4931
switch (btc->cx.state_map) {
4932
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2dp_Sink */
4933
_set_policy(rtwdev, BTC_CXP_PFIX_TD2030, BTC_ACT_BT_A2DPSINK);
4934
break;
4935
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2dp_Sink */
4936
_set_policy(rtwdev, BTC_CXP_PFIX_TD2060, BTC_ACT_BT_A2DPSINK);
4937
break;
4938
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2dp_Sink */
4939
_set_policy(rtwdev, BTC_CXP_FIX_TD2030, BTC_ACT_BT_A2DPSINK);
4940
break;
4941
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2dp_Sink */
4942
_set_policy(rtwdev, BTC_CXP_FIX_TD2060, BTC_ACT_BT_A2DPSINK);
4943
break;
4944
case BTC_WLINKING: /* wl-connecting + bt-A2dp_Sink */
4945
if (btc->cx.wl.rfk_info.con_rfk)
4946
_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DPSINK);
4947
else
4948
_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_A2DPSINK);
4949
break;
4950
case BTC_WIDLE: /* wl-idle + bt-A2dp_Sink */
4951
_set_policy(rtwdev, BTC_CXP_FIX_TD2080, BTC_ACT_BT_A2DPSINK);
4952
break;
4953
}
4954
}
4955
4956
static void _action_bt_pan(struct rtw89_dev *rtwdev)
4957
{
4958
struct rtw89_btc *btc = &rtwdev->btc;
4959
struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
4960
struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
4961
struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
4962
4963
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4964
4965
switch (btc->cx.state_map) {
4966
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN */
4967
if (a2dp.active || !pan.exist) {
4968
btc->dm.slot_dur[CXST_W1] = 80;
4969
btc->dm.slot_dur[CXST_B1] = 20;
4970
_set_policy(rtwdev, BTC_CXP_PFIX_TDW1B1, BTC_ACT_BT_PAN);
4971
} else {
4972
_set_policy(rtwdev, BTC_CXP_PFIX_TD5050, BTC_ACT_BT_PAN);
4973
}
4974
break;
4975
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN */
4976
_set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN);
4977
break;
4978
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN */
4979
_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN);
4980
break;
4981
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN */
4982
_set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN);
4983
break;
4984
case BTC_WLINKING: /* wl-connecting + bt-PAN */
4985
_set_policy(rtwdev, BTC_CXP_FIX_TD4010ISO, BTC_ACT_BT_PAN);
4986
break;
4987
case BTC_WIDLE: /* wl-idle + bt-pan */
4988
_set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN);
4989
break;
4990
}
4991
}
4992
4993
static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
4994
{
4995
struct rtw89_btc *btc = &rtwdev->btc;
4996
struct rtw89_btc_dm *dm = &btc->dm;
4997
4998
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
4999
5000
dm->slot_dur[CXST_W1] = 20;
5001
dm->slot_dur[CXST_B1] = BTC_B1_MAX;
5002
5003
switch (btc->cx.state_map) {
5004
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+HID */
5005
case BTC_WIDLE: /* wl-idle + bt-A2DP */
5006
_set_policy(rtwdev, BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
5007
break;
5008
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */
5009
_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_HID);
5010
break;
5011
5012
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+HID */
5013
_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_HID);
5014
break;
5015
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+HID */
5016
case BTC_WLINKING: /* wl-connecting + bt-A2DP+HID */
5017
if (btc->cx.wl.rfk_info.con_rfk)
5018
_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_BT_A2DP_HID);
5019
else
5020
_set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
5021
break;
5022
}
5023
}
5024
5025
static void _action_bt_a2dp_pan(struct rtw89_dev *rtwdev)
5026
{
5027
struct rtw89_btc *btc = &rtwdev->btc;
5028
5029
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5030
5031
switch (btc->cx.state_map) {
5032
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN */
5033
_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
5034
break;
5035
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN */
5036
_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
5037
break;
5038
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN */
5039
_set_policy(rtwdev, BTC_CXP_AUTO2_TD5050, BTC_ACT_BT_A2DP_PAN);
5040
break;
5041
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN */
5042
_set_policy(rtwdev, BTC_CXP_AUTO2_TD3070, BTC_ACT_BT_A2DP_PAN);
5043
break;
5044
case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN */
5045
_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050, BTC_ACT_BT_A2DP_PAN);
5046
break;
5047
case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN */
5048
_set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080, BTC_ACT_BT_A2DP_PAN);
5049
break;
5050
}
5051
}
5052
5053
static void _action_bt_pan_hid(struct rtw89_dev *rtwdev)
5054
{
5055
struct rtw89_btc *btc = &rtwdev->btc;
5056
5057
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5058
5059
switch (btc->cx.state_map) {
5060
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-PAN+HID */
5061
_set_policy(rtwdev, BTC_CXP_PFIX_TD3030, BTC_ACT_BT_PAN_HID);
5062
break;
5063
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-PAN+HID */
5064
_set_policy(rtwdev, BTC_CXP_PFIX_TD3070, BTC_ACT_BT_PAN_HID);
5065
break;
5066
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-PAN+HID */
5067
_set_policy(rtwdev, BTC_CXP_FIX_TD3030, BTC_ACT_BT_PAN_HID);
5068
break;
5069
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-PAN+HID */
5070
_set_policy(rtwdev, BTC_CXP_FIX_TD3060, BTC_ACT_BT_PAN_HID);
5071
break;
5072
case BTC_WLINKING: /* wl-connecting + bt-PAN+HID */
5073
_set_policy(rtwdev, BTC_CXP_FIX_TD4010, BTC_ACT_BT_PAN_HID);
5074
break;
5075
case BTC_WIDLE: /* wl-idle + bt-PAN+HID */
5076
_set_policy(rtwdev, BTC_CXP_PFIX_TD2080, BTC_ACT_BT_PAN_HID);
5077
break;
5078
}
5079
}
5080
5081
static void _action_bt_a2dp_pan_hid(struct rtw89_dev *rtwdev)
5082
{
5083
struct rtw89_btc *btc = &rtwdev->btc;
5084
5085
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5086
5087
switch (btc->cx.state_map) {
5088
case BTC_WBUSY_BNOSCAN: /* wl-busy + bt-A2DP+PAN+HID */
5089
_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
5090
BTC_ACT_BT_A2DP_PAN_HID);
5091
break;
5092
case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+PAN+HID */
5093
_set_policy(rtwdev, BTC_CXP_PAUTO2_TD3070,
5094
BTC_ACT_BT_A2DP_PAN_HID);
5095
break;
5096
case BTC_WSCAN_BSCAN: /* wl-scan + bt-inq + bt-A2DP+PAN+HID */
5097
_set_policy(rtwdev, BTC_CXP_AUTO2_TD3070,
5098
BTC_ACT_BT_A2DP_PAN_HID);
5099
break;
5100
case BTC_WSCAN_BNOSCAN: /* wl-scan + bt-A2DP+PAN+HID */
5101
case BTC_WLINKING: /* wl-connecting + bt-A2DP+PAN+HID */
5102
_set_policy(rtwdev, BTC_CXP_AUTO2_TD3050,
5103
BTC_ACT_BT_A2DP_PAN_HID);
5104
break;
5105
case BTC_WIDLE: /* wl-idle + bt-A2DP+PAN+HID */
5106
_set_policy(rtwdev, BTC_CXP_PAUTO2_TD2080,
5107
BTC_ACT_BT_A2DP_PAN_HID);
5108
break;
5109
}
5110
}
5111
5112
static void _action_wl_5g(struct rtw89_dev *rtwdev)
5113
{
5114
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W5G);
5115
_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_5G);
5116
}
5117
5118
static void _action_wl_other(struct rtw89_dev *rtwdev)
5119
{
5120
struct rtw89_btc *btc = &rtwdev->btc;
5121
5122
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5123
5124
if (btc->ant_type == BTC_ANT_SHARED)
5125
_set_policy(rtwdev, BTC_CXP_OFFB_BWB0, BTC_ACT_WL_OTHER);
5126
else
5127
_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_OTHER);
5128
}
5129
5130
static void _action_wl_nc(struct rtw89_dev *rtwdev)
5131
{
5132
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5133
_set_policy(rtwdev, BTC_CXP_OFF_BT, BTC_ACT_WL_NC);
5134
}
5135
5136
static void _action_wl_rfk(struct rtw89_dev *rtwdev)
5137
{
5138
struct rtw89_btc *btc = &rtwdev->btc;
5139
struct rtw89_btc_wl_rfk_info rfk = btc->cx.wl.rfk_info;
5140
5141
if (rfk.state != BTC_WRFK_START)
5142
return;
5143
5144
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): band = %d\n",
5145
__func__, rfk.band);
5146
5147
btc->dm.tdma_instant_excute = 1;
5148
5149
if (rfk.state == BTC_WRFK_ONESHOT_START ||
5150
btc->ant_type == BTC_ANT_SHARED) {
5151
_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK2);
5152
_set_policy(rtwdev, BTC_CXP_OFF_WL2, BTC_ACT_WL_RFK);
5153
} else {
5154
_set_ant(rtwdev, FC_EXEC, BTC_PHY_ALL, BTC_ANT_WRFK);
5155
_set_policy(rtwdev, BTC_CXP_OFF_WL, BTC_ACT_WL_RFK);
5156
}
5157
}
5158
5159
static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
5160
{
5161
struct rtw89_btc *btc = &rtwdev->btc;
5162
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5163
struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5164
struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5165
struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
5166
struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5167
struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info;
5168
struct rtw89_btc_wl_role_info *wl_rinfo_v0 = &wl->role_info;
5169
const struct rtw89_chip_info *chip = rtwdev->chip;
5170
const struct rtw89_btc_ver *ver = btc->ver;
5171
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5172
struct rtw89_btc_dm *dm = &btc->dm;
5173
struct _wl_rinfo_now wl_rinfo;
5174
u32 is_btg = BTC_BTGCTRL_DISABLE;
5175
5176
if (btc->manual_ctrl)
5177
return;
5178
5179
if (ver->fwlrole == 0)
5180
wl_rinfo.link_mode = wl_rinfo_v0->link_mode;
5181
else if (ver->fwlrole == 1)
5182
wl_rinfo.link_mode = wl_rinfo_v1->link_mode;
5183
else if (ver->fwlrole == 2)
5184
wl_rinfo.link_mode = wl_rinfo_v2->link_mode;
5185
else if (ver->fwlrole == 7)
5186
wl_rinfo.link_mode = wl_rinfo_v7->link_mode;
5187
else if (ver->fwlrole == 8)
5188
wl_rinfo.link_mode = wl_rinfo_v8->link_mode;
5189
else
5190
return;
5191
5192
/* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */
5193
if (btc->ant_type == BTC_ANT_SHARED) {
5194
if (!(bt->run_patch_code && bt->enable.now))
5195
is_btg = BTC_BTGCTRL_DISABLE;
5196
else if (wl_rinfo.link_mode != BTC_WLINK_5G)
5197
is_btg = BTC_BTGCTRL_ENABLE;
5198
else
5199
is_btg = BTC_BTGCTRL_DISABLE;
5200
5201
/* bb call ctrl_btg() in WL FW by slot */
5202
if (!ver->fcxosi &&
5203
wl_rinfo.link_mode == BTC_WLINK_25G_MCC)
5204
is_btg = BTC_BTGCTRL_BB_GNT_FWCTRL;
5205
}
5206
5207
if (is_btg == dm->wl_btg_rx)
5208
return;
5209
else
5210
dm->wl_btg_rx = is_btg;
5211
5212
/* skip setup if btg_ctrl set by wl fw */
5213
if (!ver->fcxosi && is_btg > BTC_BTGCTRL_ENABLE)
5214
return;
5215
5216
/* Below flow is for BTC_FEAT_NEW_BBAPI_FLOW = 1 */
5217
if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */
5218
if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */
5219
o_info->btg_rx[BTC_RF_S0] = BTC_BTGCTRL_DISABLE;
5220
else
5221
o_info->btg_rx[BTC_RF_S0] = is_btg;
5222
5223
if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */
5224
o_info->btg_rx[BTC_RF_S1] = BTC_BTGCTRL_DISABLE;
5225
else
5226
o_info->btg_rx[BTC_RF_S1] = is_btg;
5227
} else { /* 2+0 or 0+2 */
5228
o_info->btg_rx[BTC_RF_S0] = is_btg;
5229
o_info->btg_rx[BTC_RF_S1] = is_btg;
5230
}
5231
5232
if (ver->fcxosi)
5233
return;
5234
5235
chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S0],
5236
RTW89_PHY_0);
5237
if (chip->chip_id != RTL8922A)
5238
return;
5239
5240
chip->ops->ctrl_btg_bt_rx(rtwdev, o_info->btg_rx[BTC_RF_S1],
5241
RTW89_PHY_1);
5242
}
5243
5244
static void _set_wl_preagc_ctrl(struct rtw89_dev *rtwdev)
5245
{
5246
struct rtw89_btc *btc = &rtwdev->btc;
5247
struct rtw89_btc_fbtc_outsrc_set_info *o_info = &btc->dm.ost_info;
5248
struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
5249
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5250
struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2;
5251
struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
5252
struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8;
5253
const struct rtw89_chip_info *chip = rtwdev->chip;
5254
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5255
struct rtw89_btc_dm *dm = &btc->dm;
5256
u8 is_preagc, val, link_mode, dbcc_2g_phy;
5257
u8 role_ver = rtwdev->btc.ver->fwlrole;
5258
bool dbcc_en;
5259
5260
if (btc->manual_ctrl)
5261
return;
5262
5263
if (role_ver == 2) {
5264
dbcc_en = rinfo_v2->dbcc_en;
5265
link_mode = rinfo_v2->link_mode;
5266
dbcc_2g_phy = rinfo_v2->dbcc_2g_phy;
5267
} else if (role_ver == 7) {
5268
dbcc_en = rinfo_v7->dbcc_en;
5269
link_mode = rinfo_v7->link_mode;
5270
dbcc_2g_phy = rinfo_v7->dbcc_2g_phy;
5271
} else if (role_ver == 8) {
5272
dbcc_en = rinfo_v8->dbcc_en;
5273
link_mode = rinfo_v8->link_mode;
5274
dbcc_2g_phy = rinfo_v7->dbcc_2g_phy;
5275
} else {
5276
return;
5277
}
5278
5279
if (!(bt->run_patch_code && bt->enable.now)) {
5280
is_preagc = BTC_PREAGC_DISABLE;
5281
} else if (link_mode == BTC_WLINK_5G) {
5282
is_preagc = BTC_PREAGC_DISABLE;
5283
} else if (link_mode == BTC_WLINK_NOLINK ||
5284
btc->cx.bt.link_info.profile_cnt.now == 0) {
5285
is_preagc = BTC_PREAGC_DISABLE;
5286
} else if (dm->tdma_now.type != CXTDMA_OFF &&
5287
!bt_linfo->hfp_desc.exist &&
5288
!bt_linfo->hid_desc.exist &&
5289
dm->fddt_train == BTC_FDDT_DISABLE) {
5290
is_preagc = BTC_PREAGC_DISABLE;
5291
} else if (dbcc_en && (dbcc_2g_phy != RTW89_PHY_1)) {
5292
is_preagc = BTC_PREAGC_DISABLE;
5293
} else if (btc->ant_type == BTC_ANT_SHARED) {
5294
is_preagc = BTC_PREAGC_DISABLE;
5295
} else {
5296
is_preagc = BTC_PREAGC_ENABLE;
5297
}
5298
5299
if (!btc->ver->fcxosi && link_mode == BTC_WLINK_25G_MCC)
5300
is_preagc = BTC_PREAGC_BB_FWCTRL;
5301
5302
if (dm->wl_pre_agc_rb != dm->wl_pre_agc &&
5303
dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND) {
5304
_get_reg_status(rtwdev, BTC_CSTATUS_BB_PRE_AGC, &val);
5305
dm->wl_pre_agc_rb = val;
5306
}
5307
5308
if ((wl->coex_mode == BTC_MODE_NORMAL &&
5309
(dm->run_reason == BTC_RSN_NTFY_INIT ||
5310
dm->run_reason == BTC_RSN_NTFY_SWBAND ||
5311
dm->wl_pre_agc_rb != dm->wl_pre_agc)) ||
5312
is_preagc != dm->wl_pre_agc) {
5313
dm->wl_pre_agc = is_preagc;
5314
5315
if (!btc->ver->fcxosi && is_preagc > BTC_PREAGC_ENABLE)
5316
return;
5317
5318
if (o_info->rf_band[BTC_RF_S0] != o_info->rf_band[BTC_RF_S1]) {/* 1+1 */
5319
if (o_info->rf_band[BTC_RF_S0]) /* Non-2G */
5320
o_info->nbtg_tx[BTC_RF_S0] = BTC_PREAGC_DISABLE;
5321
else
5322
o_info->nbtg_tx[BTC_RF_S0] = is_preagc;
5323
5324
if (o_info->rf_band[BTC_RF_S1]) /* Non-2G */
5325
o_info->nbtg_tx[BTC_RF_S1] = BTC_PREAGC_DISABLE;
5326
else
5327
o_info->nbtg_tx[BTC_RF_S1] = is_preagc;
5328
5329
} else { /* 2+0 or 0+2 */
5330
o_info->nbtg_tx[BTC_RF_S0] = is_preagc;
5331
o_info->nbtg_tx[BTC_RF_S1] = is_preagc;
5332
}
5333
5334
if (btc->ver->fcxosi)
5335
return;
5336
5337
chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S0],
5338
RTW89_PHY_0);
5339
if (chip->chip_id != RTL8922A)
5340
return;
5341
chip->ops->ctrl_nbtg_bt_tx(rtwdev, o_info->nbtg_tx[BTC_RF_S1],
5342
RTW89_PHY_1);
5343
}
5344
}
5345
5346
struct rtw89_txtime_data {
5347
struct rtw89_dev *rtwdev;
5348
int type;
5349
u32 tx_time;
5350
u8 tx_retry;
5351
u16 enable;
5352
bool reenable;
5353
};
5354
5355
static void __rtw89_tx_time_iter(struct rtw89_vif_link *rtwvif_link,
5356
struct rtw89_sta_link *rtwsta_link,
5357
struct rtw89_txtime_data *iter_data)
5358
{
5359
struct rtw89_dev *rtwdev = iter_data->rtwdev;
5360
struct rtw89_btc *btc = &rtwdev->btc;
5361
struct rtw89_btc_cx *cx = &btc->cx;
5362
struct rtw89_btc_wl_info *wl = &cx->wl;
5363
struct rtw89_btc_wl_link_info *plink = NULL;
5364
u8 port = rtwvif_link->port;
5365
u32 tx_time = iter_data->tx_time;
5366
u8 tx_retry = iter_data->tx_retry;
5367
u16 enable = iter_data->enable;
5368
bool reenable = iter_data->reenable;
5369
5370
if (btc->ver->fwlrole == 8)
5371
plink = &wl->rlink_info[port][0];
5372
else
5373
plink = &wl->link_info[port];
5374
5375
rtw89_debug(rtwdev, RTW89_DBG_BTC,
5376
"[BTC], %s(): port = %d\n", __func__, port);
5377
5378
if (!plink->connected) {
5379
rtw89_debug(rtwdev, RTW89_DBG_BTC,
5380
"[BTC], %s(): connected = %d\n",
5381
__func__, plink->connected);
5382
return;
5383
}
5384
5385
/* backup the original tx time before tx-limit on */
5386
if (reenable) {
5387
rtw89_mac_get_tx_time(rtwdev, rtwsta_link, &plink->tx_time);
5388
rtw89_mac_get_tx_retry_limit(rtwdev, rtwsta_link, &plink->tx_retry);
5389
rtw89_debug(rtwdev, RTW89_DBG_BTC,
5390
"[BTC], %s(): reenable, tx_time=%d tx_retry= %d\n",
5391
__func__, plink->tx_time, plink->tx_retry);
5392
}
5393
5394
/* restore the original tx time if no tx-limit */
5395
if (!enable) {
5396
rtw89_mac_set_tx_time(rtwdev, rtwsta_link, true, plink->tx_time);
5397
rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, true,
5398
plink->tx_retry);
5399
rtw89_debug(rtwdev, RTW89_DBG_BTC,
5400
"[BTC], %s(): restore, tx_time=%d tx_retry= %d\n",
5401
__func__, plink->tx_time, plink->tx_retry);
5402
5403
} else {
5404
rtw89_mac_set_tx_time(rtwdev, rtwsta_link, false, tx_time);
5405
rtw89_mac_set_tx_retry_limit(rtwdev, rtwsta_link, false, tx_retry);
5406
rtw89_debug(rtwdev, RTW89_DBG_BTC,
5407
"[BTC], %s(): set, tx_time=%d tx_retry= %d\n",
5408
__func__, tx_time, tx_retry);
5409
}
5410
}
5411
5412
static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
5413
{
5414
struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
5415
struct rtw89_txtime_data *iter_data =
5416
(struct rtw89_txtime_data *)data;
5417
struct rtw89_vif_link *rtwvif_link;
5418
struct rtw89_sta_link *rtwsta_link;
5419
unsigned int link_id;
5420
5421
rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
5422
rtwvif_link = rtwsta_link->rtwvif_link;
5423
__rtw89_tx_time_iter(rtwvif_link, rtwsta_link, iter_data);
5424
}
5425
}
5426
5427
static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
5428
{
5429
struct rtw89_btc *btc = &rtwdev->btc;
5430
const struct rtw89_btc_ver *ver = btc->ver;
5431
struct rtw89_btc_cx *cx = &btc->cx;
5432
struct rtw89_btc_dm *dm = &btc->dm;
5433
struct rtw89_btc_wl_info *wl = &cx->wl;
5434
struct rtw89_btc_bt_info *bt = &cx->bt;
5435
struct rtw89_btc_bt_link_info *b = &bt->link_info;
5436
struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
5437
struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
5438
struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5439
struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5440
struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5441
struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
5442
struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5443
struct rtw89_txtime_data data = {.rtwdev = rtwdev};
5444
u8 mode, igno_bt, tx_retry;
5445
u32 tx_time;
5446
u16 enable;
5447
bool reenable = false;
5448
5449
if (btc->manual_ctrl)
5450
return;
5451
5452
if (ver->fwlrole == 0)
5453
mode = wl_rinfo->link_mode;
5454
else if (ver->fwlrole == 1)
5455
mode = wl_rinfo_v1->link_mode;
5456
else if (ver->fwlrole == 2)
5457
mode = wl_rinfo_v2->link_mode;
5458
else if (ver->fwlrole == 7)
5459
mode = wl_rinfo_v7->link_mode;
5460
else if (ver->fwlrole == 8)
5461
mode = wl_rinfo_v8->link_mode;
5462
else
5463
return;
5464
5465
if (ver->fcxctrl == 7)
5466
igno_bt = btc->ctrl.ctrl_v7.igno_bt;
5467
else
5468
igno_bt = btc->ctrl.ctrl.igno_bt;
5469
5470
if (btc->dm.freerun || igno_bt || b->profile_cnt.now == 0 ||
5471
mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) {
5472
enable = 0;
5473
tx_time = BTC_MAX_TX_TIME_DEF;
5474
tx_retry = BTC_MAX_TX_RETRY_DEF;
5475
} else if ((hfp->exist && hid->exist) || hid->pair_cnt > 1) {
5476
enable = 1;
5477
tx_time = BTC_MAX_TX_TIME_L2;
5478
tx_retry = BTC_MAX_TX_RETRY_L1;
5479
} else if (hfp->exist || hid->exist) {
5480
enable = 1;
5481
tx_time = BTC_MAX_TX_TIME_L3;
5482
tx_retry = BTC_MAX_TX_RETRY_L1;
5483
} else {
5484
enable = 0;
5485
tx_time = BTC_MAX_TX_TIME_DEF;
5486
tx_retry = BTC_MAX_TX_RETRY_DEF;
5487
}
5488
5489
if (dm->wl_tx_limit.enable == enable &&
5490
dm->wl_tx_limit.tx_time == tx_time &&
5491
dm->wl_tx_limit.tx_retry == tx_retry)
5492
return;
5493
5494
if (!dm->wl_tx_limit.enable && enable)
5495
reenable = true;
5496
5497
dm->wl_tx_limit.enable = enable;
5498
dm->wl_tx_limit.tx_time = tx_time;
5499
dm->wl_tx_limit.tx_retry = tx_retry;
5500
5501
data.enable = enable;
5502
data.tx_time = tx_time;
5503
data.tx_retry = tx_retry;
5504
data.reenable = reenable;
5505
5506
ieee80211_iterate_stations_atomic(rtwdev->hw,
5507
rtw89_tx_time_iter,
5508
&data);
5509
}
5510
5511
static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
5512
{
5513
struct rtw89_btc *btc = &rtwdev->btc;
5514
const struct rtw89_btc_ver *ver = btc->ver;
5515
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5516
struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
5517
struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
5518
struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
5519
struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
5520
struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
5521
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5522
bool bt_hi_lna_rx = false;
5523
u8 mode;
5524
5525
if (ver->fwlrole == 0)
5526
mode = wl_rinfo->link_mode;
5527
else if (ver->fwlrole == 1)
5528
mode = wl_rinfo_v1->link_mode;
5529
else if (ver->fwlrole == 2)
5530
mode = wl_rinfo_v2->link_mode;
5531
else if (ver->fwlrole == 7)
5532
mode = wl_rinfo_v7->link_mode;
5533
else if (ver->fwlrole == 8)
5534
mode = wl_rinfo_v8->link_mode;
5535
else
5536
return;
5537
5538
if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
5539
bt_hi_lna_rx = true;
5540
5541
if (bt_hi_lna_rx == bt->hi_lna_rx)
5542
return;
5543
5544
_write_scbd(rtwdev, BTC_WSCB_BT_HILNA, bt_hi_lna_rx);
5545
}
5546
5547
static void _set_bt_rx_scan_pri(struct rtw89_dev *rtwdev)
5548
{
5549
struct rtw89_btc *btc = &rtwdev->btc;
5550
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5551
5552
_write_scbd(rtwdev, BTC_WSCB_RXSCAN_PRI, (bool)(!!bt->scan_rx_low_pri));
5553
}
5554
5555
static void _wl_req_mac(struct rtw89_dev *rtwdev, u8 mac)
5556
{
5557
struct rtw89_btc *btc = &rtwdev->btc;
5558
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5559
struct rtw89_btc_dm *dm = &btc->dm;
5560
u32 add;
5561
5562
if (mac == wl->pta_req_mac)
5563
return;
5564
5565
dm->ost_info.pta_req_hw_band = mac;
5566
wl->pta_req_mac = mac;
5567
wl->pta_reg_mac_chg = true;
5568
5569
if (btc->ver->fcxosi)
5570
return;
5571
5572
if (rtwdev->chip->chip_gen == RTW89_CHIP_BE)
5573
add = R_BE_BTC_CFG;
5574
else
5575
add = R_AX_BTC_CFG;
5576
5577
if (mac == RTW89_MAC_0)
5578
rtw89_write32_clr(rtwdev, add, B_AX_WL_SRC);
5579
else
5580
rtw89_write32_set(rtwdev, add, B_AX_WL_SRC);
5581
}
5582
5583
static void _action_common(struct rtw89_dev *rtwdev)
5584
{
5585
struct rtw89_btc *btc = &rtwdev->btc;
5586
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5587
struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8;
5588
struct rtw89_btc_wl_smap *wl_smap = &wl->status.map;
5589
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5590
struct rtw89_btc_dm *dm = &btc->dm;
5591
u32 bt_rom_code_id, bt_fw_ver;
5592
5593
if (btc->ver->fwlrole == 8)
5594
_wl_req_mac(rtwdev, rinfo_v8->pta_req_band);
5595
5596
_set_btg_ctrl(rtwdev);
5597
_set_wl_preagc_ctrl(rtwdev);
5598
_set_wl_tx_limit(rtwdev);
5599
_set_bt_afh_info(rtwdev);
5600
_set_bt_rx_agc(rtwdev);
5601
_set_rf_trx_para(rtwdev);
5602
_set_bt_rx_scan_pri(rtwdev);
5603
5604
bt_rom_code_id = chip_id_to_bt_rom_code_id(rtwdev->btc.ver->chip_id);
5605
bt_fw_ver = bt->ver_info.fw & 0xffff;
5606
if (bt->enable.now &&
5607
(bt_fw_ver == 0 ||
5608
(bt_fw_ver == bt_rom_code_id && bt->run_patch_code && rtwdev->chip->scbd)))
5609
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 1);
5610
else
5611
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, 0);
5612
5613
if (dm->run_reason == BTC_RSN_NTFY_INIT ||
5614
dm->run_reason == BTC_RSN_NTFY_RADIO_STATE ||
5615
dm->run_reason == BTC_RSN_NTFY_POWEROFF) {
5616
_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
5617
5618
if (wl_smap->rf_off == 1 || wl_smap->lps != BTC_LPS_OFF)
5619
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
5620
else
5621
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, 1);
5622
}
5623
5624
if (wl->scbd_change) {
5625
rtw89_mac_cfg_sb(rtwdev, wl->scbd);
5626
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], write scbd: 0x%08x\n",
5627
wl->scbd);
5628
wl->scbd_change = false;
5629
btc->cx.cnt_wl[BTC_WCNT_SCBDUPDATE]++;
5630
}
5631
5632
if (btc->ver->fcxosi) {
5633
if (memcmp(&dm->ost_info_last, &dm->ost_info,
5634
sizeof(dm->ost_info_last)) ||
5635
dm->run_reason == BTC_RSN_NTFY_INIT ||
5636
dm->run_reason == BTC_RSN_NTFY_RADIO_STATE) {
5637
dm->ost_info_last = dm->ost_info;
5638
_fw_set_drv_info(rtwdev, CXDRVINFO_OSI);
5639
}
5640
}
5641
btc->dm.tdma_instant_excute = 0;
5642
wl->pta_reg_mac_chg = false;
5643
}
5644
5645
static void _action_by_bt(struct rtw89_dev *rtwdev)
5646
{
5647
struct rtw89_btc *btc = &rtwdev->btc;
5648
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5649
struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
5650
struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
5651
struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
5652
struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
5653
struct rtw89_btc_dm *dm = &btc->dm;
5654
u8 profile_map = 0;
5655
5656
if (dm->freerun_chk) {
5657
_action_freerun(rtwdev);
5658
return;
5659
}
5660
5661
if (bt_linfo->hfp_desc.exist)
5662
profile_map |= BTC_BT_HFP;
5663
5664
if (bt_linfo->hid_desc.exist)
5665
profile_map |= BTC_BT_HID;
5666
5667
if (bt_linfo->a2dp_desc.exist)
5668
profile_map |= BTC_BT_A2DP;
5669
5670
if (bt_linfo->pan_desc.exist)
5671
profile_map |= BTC_BT_PAN;
5672
5673
switch (profile_map) {
5674
case BTC_BT_NOPROFILE:
5675
if (pan.active)
5676
_action_bt_pan(rtwdev);
5677
else
5678
_action_bt_idle(rtwdev);
5679
break;
5680
case BTC_BT_HFP:
5681
_action_bt_hfp(rtwdev);
5682
break;
5683
case BTC_BT_HFP | BTC_BT_HID:
5684
case BTC_BT_HID:
5685
_action_bt_hid(rtwdev);
5686
break;
5687
case BTC_BT_A2DP:
5688
if (a2dp.sink)
5689
_action_bt_a2dpsink(rtwdev);
5690
else if (bt_linfo->multi_link.now && !hid.pair_cnt)
5691
_action_bt_a2dp_pan(rtwdev);
5692
else
5693
_action_bt_a2dp(rtwdev);
5694
break;
5695
case BTC_BT_PAN:
5696
_action_bt_pan(rtwdev);
5697
break;
5698
case BTC_BT_A2DP | BTC_BT_HFP:
5699
case BTC_BT_A2DP | BTC_BT_HID:
5700
case BTC_BT_A2DP | BTC_BT_HFP | BTC_BT_HID:
5701
if (a2dp.sink)
5702
_action_bt_a2dpsink(rtwdev);
5703
else if (pan.active)
5704
_action_bt_a2dp_pan_hid(rtwdev);
5705
else
5706
_action_bt_a2dp_hid(rtwdev);
5707
break;
5708
case BTC_BT_A2DP | BTC_BT_PAN:
5709
if (a2dp.sink)
5710
_action_bt_a2dpsink(rtwdev);
5711
else
5712
_action_bt_a2dp_pan(rtwdev);
5713
break;
5714
case BTC_BT_PAN | BTC_BT_HFP:
5715
case BTC_BT_PAN | BTC_BT_HID:
5716
case BTC_BT_PAN | BTC_BT_HFP | BTC_BT_HID:
5717
_action_bt_pan_hid(rtwdev);
5718
break;
5719
case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HID:
5720
case BTC_BT_A2DP | BTC_BT_PAN | BTC_BT_HFP:
5721
default:
5722
if (a2dp.sink)
5723
_action_bt_a2dpsink(rtwdev);
5724
else
5725
_action_bt_a2dp_pan_hid(rtwdev);
5726
break;
5727
}
5728
}
5729
5730
static void _action_wl_2g_sta(struct rtw89_dev *rtwdev)
5731
{
5732
_action_by_bt(rtwdev);
5733
}
5734
5735
static void _action_wl_25g_mcc(struct rtw89_dev *rtwdev)
5736
{
5737
struct rtw89_btc *btc = &rtwdev->btc;
5738
u16 policy_type = BTC_CXP_OFF_BT;
5739
5740
if (btc->ant_type == BTC_ANT_SHARED) {
5741
if (btc->cx.wl.status.map._4way)
5742
policy_type = BTC_CXP_OFFE_WL;
5743
else if (btc->cx.wl.status.val & btc_scanning_map.val)
5744
policy_type = BTC_CXP_OFFE_2GBWMIXB;
5745
else if (btc->cx.bt.link_info.status.map.connect == 0)
5746
policy_type = BTC_CXP_OFFE_2GISOB;
5747
else
5748
policy_type = BTC_CXP_OFFE_2GBWISOB;
5749
} else { /* dedicated-antenna */
5750
policy_type = BTC_CXP_OFF_EQ0;
5751
}
5752
5753
btc->dm.e2g_slot_limit = BTC_E2G_LIMIT_DEF;
5754
5755
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W25G);
5756
_set_policy(rtwdev, policy_type, BTC_ACT_WL_25G_MCC);
5757
}
5758
5759
static void _action_wl_scan(struct rtw89_dev *rtwdev)
5760
{
5761
struct rtw89_btc *btc = &rtwdev->btc;
5762
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5763
struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
5764
5765
if (btc->cx.state_map != BTC_WLINKING &&
5766
RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
5767
_action_wl_25g_mcc(rtwdev);
5768
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], Scan offload!\n");
5769
} else if (rtwdev->dbcc_en) {
5770
if (wl_dinfo->real_band[RTW89_PHY_0] != RTW89_BAND_2G &&
5771
wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
5772
_action_wl_5g(rtwdev);
5773
else
5774
_action_by_bt(rtwdev);
5775
} else {
5776
if (wl->scan_info.band[RTW89_PHY_0] != RTW89_BAND_2G)
5777
_action_wl_5g(rtwdev);
5778
else
5779
_action_by_bt(rtwdev);
5780
}
5781
}
5782
5783
static void _action_wl_2g_mcc(struct rtw89_dev *rtwdev)
5784
{ struct rtw89_btc *btc = &rtwdev->btc;
5785
5786
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5787
5788
if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5789
if (btc->cx.bt.link_info.profile_cnt.now == 0)
5790
_set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
5791
BTC_ACT_WL_2G_MCC);
5792
else
5793
_set_policy(rtwdev, BTC_CXP_OFFE_DEF,
5794
BTC_ACT_WL_2G_MCC);
5795
} else { /* dedicated-antenna */
5796
_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_MCC);
5797
}
5798
}
5799
5800
static void _action_wl_2g_scc(struct rtw89_dev *rtwdev)
5801
{
5802
struct rtw89_btc *btc = &rtwdev->btc;
5803
5804
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5805
5806
if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
5807
if (btc->cx.bt.link_info.profile_cnt.now == 0)
5808
_set_policy(rtwdev,
5809
BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_SCC);
5810
else
5811
_set_policy(rtwdev,
5812
BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_SCC);
5813
} else { /* dedicated-antenna */
5814
_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_SCC);
5815
}
5816
}
5817
5818
static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev)
5819
{
5820
struct rtw89_btc *btc = &rtwdev->btc;
5821
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5822
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5823
struct rtw89_btc_dm *dm = &btc->dm;
5824
struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
5825
u16 policy_type = BTC_CXP_OFF_BT;
5826
u32 dur;
5827
5828
if (btc->ant_type == BTC_ANT_DEDICATED) {
5829
policy_type = BTC_CXP_OFF_EQ0;
5830
} else {
5831
/* shared-antenna */
5832
switch (wl_rinfo->mrole_type) {
5833
case BTC_WLMROLE_STA_GC:
5834
dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5835
dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
5836
dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5837
_action_by_bt(rtwdev);
5838
return;
5839
case BTC_WLMROLE_STA_STA:
5840
dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5841
dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
5842
dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5843
_action_by_bt(rtwdev);
5844
return;
5845
case BTC_WLMROLE_STA_GC_NOA:
5846
case BTC_WLMROLE_STA_GO:
5847
case BTC_WLMROLE_STA_GO_NOA:
5848
dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5849
dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
5850
dur = wl_rinfo->mrole_noa_duration;
5851
5852
if (wl->status.map._4way) {
5853
dm->wl_scc.ebt_null = 0;
5854
policy_type = BTC_CXP_OFFE_WL;
5855
} else if (bt->link_info.status.map.connect == 0) {
5856
dm->wl_scc.ebt_null = 0;
5857
policy_type = BTC_CXP_OFFE_2GISOB;
5858
} else if (bt->link_info.a2dp_desc.exist &&
5859
dur < btc->bt_req_len) {
5860
dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5861
policy_type = BTC_CXP_OFFE_2GBWMIXB2;
5862
} else if (bt->link_info.a2dp_desc.exist ||
5863
bt->link_info.pan_desc.exist) {
5864
dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5865
policy_type = BTC_CXP_OFFE_2GBWISOB;
5866
} else {
5867
dm->wl_scc.ebt_null = 0;
5868
policy_type = BTC_CXP_OFFE_2GBWISOB;
5869
}
5870
break;
5871
default:
5872
break;
5873
}
5874
}
5875
5876
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5877
_set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5878
}
5879
5880
static void _action_wl_2g_scc_v2(struct rtw89_dev *rtwdev)
5881
{
5882
struct rtw89_btc *btc = &rtwdev->btc;
5883
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5884
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5885
struct rtw89_btc_dm *dm = &btc->dm;
5886
struct rtw89_btc_wl_role_info_v2 *rinfo_v2 = &wl->role_info_v2;
5887
struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
5888
u32 dur, mrole_type, mrole_noa_duration;
5889
u16 policy_type = BTC_CXP_OFF_BT;
5890
5891
if (btc->ver->fwlrole == 2) {
5892
mrole_type = rinfo_v2->mrole_type;
5893
mrole_noa_duration = rinfo_v2->mrole_noa_duration;
5894
} else if (btc->ver->fwlrole == 7) {
5895
mrole_type = rinfo_v7->mrole_type;
5896
mrole_noa_duration = rinfo_v7->mrole_noa_duration;
5897
} else {
5898
return;
5899
}
5900
5901
if (btc->ant_type == BTC_ANT_DEDICATED) {
5902
policy_type = BTC_CXP_OFF_EQ0;
5903
} else {
5904
/* shared-antenna */
5905
switch (mrole_type) {
5906
case BTC_WLMROLE_STA_GC:
5907
dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5908
dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
5909
dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5910
_action_by_bt(rtwdev);
5911
return;
5912
case BTC_WLMROLE_STA_STA:
5913
dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5914
dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
5915
dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
5916
_action_by_bt(rtwdev);
5917
return;
5918
case BTC_WLMROLE_STA_GC_NOA:
5919
case BTC_WLMROLE_STA_GO:
5920
case BTC_WLMROLE_STA_GO_NOA:
5921
dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
5922
dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
5923
dur = mrole_noa_duration;
5924
5925
if (wl->status.map._4way) {
5926
dm->wl_scc.ebt_null = 0;
5927
policy_type = BTC_CXP_OFFE_WL;
5928
} else if (bt->link_info.status.map.connect == 0) {
5929
dm->wl_scc.ebt_null = 0;
5930
policy_type = BTC_CXP_OFFE_2GISOB;
5931
} else if (bt->link_info.a2dp_desc.exist &&
5932
dur < btc->bt_req_len) {
5933
dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5934
policy_type = BTC_CXP_OFFE_2GBWMIXB2;
5935
} else if (bt->link_info.a2dp_desc.exist ||
5936
bt->link_info.pan_desc.exist) {
5937
dm->wl_scc.ebt_null = 1; /* tx null at EBT */
5938
policy_type = BTC_CXP_OFFE_2GBWISOB;
5939
} else {
5940
dm->wl_scc.ebt_null = 0;
5941
policy_type = BTC_CXP_OFFE_2GBWISOB;
5942
}
5943
break;
5944
default:
5945
break;
5946
}
5947
}
5948
5949
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5950
_set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5951
}
5952
5953
static void _action_wl_2g_scc_v8(struct rtw89_dev *rtwdev)
5954
{
5955
struct rtw89_btc *btc = &rtwdev->btc;
5956
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
5957
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
5958
struct rtw89_btc_dm *dm = &btc->dm;
5959
u16 policy_type = BTC_CXP_OFF_BT;
5960
5961
if (btc->ant_type == BTC_ANT_SHARED) {
5962
if (wl->status.map._4way)
5963
policy_type = BTC_CXP_OFFE_WL;
5964
else if (bt->link_info.status.map.connect == 0)
5965
policy_type = BTC_CXP_OFFE_2GISOB;
5966
else
5967
policy_type = BTC_CXP_OFFE_2GBWISOB;
5968
} else {
5969
policy_type = BTC_CXP_OFF_EQ0;
5970
}
5971
5972
dm->e2g_slot_limit = BTC_E2G_LIMIT_DEF;
5973
5974
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5975
_set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
5976
}
5977
5978
static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
5979
{
5980
struct rtw89_btc *btc = &rtwdev->btc;
5981
5982
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
5983
5984
if (btc->ant_type == BTC_ANT_SHARED) {
5985
if (btc->cx.bt.link_info.profile_cnt.now == 0)
5986
_set_policy(rtwdev, BTC_CXP_OFFE_DEF2,
5987
BTC_ACT_WL_2G_AP);
5988
else
5989
_set_policy(rtwdev, BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_AP);
5990
} else {/* dedicated-antenna */
5991
_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_AP);
5992
}
5993
}
5994
5995
static void _action_wl_2g_go(struct rtw89_dev *rtwdev)
5996
{
5997
struct rtw89_btc *btc = &rtwdev->btc;
5998
5999
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6000
6001
if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6002
if (btc->cx.bt.link_info.profile_cnt.now == 0)
6003
_set_policy(rtwdev,
6004
BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_GO);
6005
else
6006
_set_policy(rtwdev,
6007
BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_GO);
6008
} else { /* dedicated-antenna */
6009
_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GO);
6010
}
6011
}
6012
6013
static void _action_wl_2g_gc(struct rtw89_dev *rtwdev)
6014
{
6015
struct rtw89_btc *btc = &rtwdev->btc;
6016
6017
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6018
6019
if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6020
_action_by_bt(rtwdev);
6021
} else {/* dedicated-antenna */
6022
_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_GC);
6023
}
6024
}
6025
6026
static void _action_wl_2g_nan(struct rtw89_dev *rtwdev)
6027
{
6028
struct rtw89_btc *btc = &rtwdev->btc;
6029
6030
_set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
6031
6032
if (btc->ant_type == BTC_ANT_SHARED) { /* shared-antenna */
6033
if (btc->cx.bt.link_info.profile_cnt.now == 0)
6034
_set_policy(rtwdev,
6035
BTC_CXP_OFFE_DEF2, BTC_ACT_WL_2G_NAN);
6036
else
6037
_set_policy(rtwdev,
6038
BTC_CXP_OFFE_DEF, BTC_ACT_WL_2G_NAN);
6039
} else { /* dedicated-antenna */
6040
_set_policy(rtwdev, BTC_CXP_OFF_EQ0, BTC_ACT_WL_2G_NAN);
6041
}
6042
}
6043
6044
static u32 _read_scbd(struct rtw89_dev *rtwdev)
6045
{
6046
const struct rtw89_chip_info *chip = rtwdev->chip;
6047
struct rtw89_btc *btc = &rtwdev->btc;
6048
u32 scbd_val = 0;
6049
6050
if (!chip->scbd)
6051
return 0;
6052
6053
scbd_val = rtw89_mac_get_sb(rtwdev);
6054
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], read scbd: 0x%08x\n",
6055
scbd_val);
6056
6057
btc->cx.cnt_bt[BTC_BCNT_SCBDREAD]++;
6058
return scbd_val;
6059
}
6060
6061
static void _write_scbd(struct rtw89_dev *rtwdev, u32 val, bool state)
6062
{
6063
const struct rtw89_chip_info *chip = rtwdev->chip;
6064
struct rtw89_btc *btc = &rtwdev->btc;
6065
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6066
u32 scbd_val = 0;
6067
u8 force_exec = false;
6068
6069
if (!chip->scbd)
6070
return;
6071
6072
scbd_val = state ? wl->scbd | val : wl->scbd & ~val;
6073
6074
if (val & BTC_WSCB_ACTIVE || val & BTC_WSCB_ON)
6075
force_exec = true;
6076
6077
if (scbd_val != wl->scbd || force_exec) {
6078
wl->scbd = scbd_val;
6079
wl->scbd_change = true;
6080
}
6081
}
6082
6083
static u8
6084
_update_rssi_state(struct rtw89_dev *rtwdev, u8 pre_state, u8 rssi, u8 thresh)
6085
{
6086
const struct rtw89_chip_info *chip = rtwdev->chip;
6087
u8 next_state, tol = chip->rssi_tol;
6088
6089
if (pre_state == BTC_RSSI_ST_LOW ||
6090
pre_state == BTC_RSSI_ST_STAY_LOW) {
6091
if (rssi >= (thresh + tol))
6092
next_state = BTC_RSSI_ST_HIGH;
6093
else
6094
next_state = BTC_RSSI_ST_STAY_LOW;
6095
} else {
6096
if (rssi < thresh)
6097
next_state = BTC_RSSI_ST_LOW;
6098
else
6099
next_state = BTC_RSSI_ST_STAY_HIGH;
6100
}
6101
6102
return next_state;
6103
}
6104
6105
static
6106
void _update_dbcc_band(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
6107
{
6108
struct rtw89_btc *btc = &rtwdev->btc;
6109
6110
btc->cx.wl.dbcc_info.real_band[phy_idx] =
6111
btc->cx.wl.scan_info.phy_map & BIT(phy_idx) ?
6112
btc->cx.wl.dbcc_info.scan_band[phy_idx] :
6113
btc->cx.wl.dbcc_info.op_band[phy_idx];
6114
}
6115
6116
static void _update_wl_info(struct rtw89_dev *rtwdev)
6117
{
6118
struct rtw89_btc *btc = &rtwdev->btc;
6119
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6120
struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6121
struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
6122
struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6123
u8 i, cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
6124
u8 cnt_2g = 0, cnt_5g = 0, phy;
6125
u32 wl_2g_ch[2] = {0}, wl_5g_ch[2] = {0};
6126
bool b2g = false, b5g = false, client_joined = false;
6127
6128
memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6129
6130
for (i = 0; i < RTW89_PORT_NUM; i++) {
6131
/* check if role active? */
6132
if (!wl_linfo[i].active)
6133
continue;
6134
6135
cnt_active++;
6136
wl_rinfo->active_role[cnt_active - 1].role = wl_linfo[i].role;
6137
wl_rinfo->active_role[cnt_active - 1].pid = wl_linfo[i].pid;
6138
wl_rinfo->active_role[cnt_active - 1].phy = wl_linfo[i].phy;
6139
wl_rinfo->active_role[cnt_active - 1].band = wl_linfo[i].band;
6140
wl_rinfo->active_role[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
6141
wl_rinfo->active_role[cnt_active - 1].connected = 0;
6142
6143
wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
6144
6145
phy = wl_linfo[i].phy;
6146
6147
/* check dbcc role */
6148
if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) {
6149
wl_dinfo->role[phy] = wl_linfo[i].role;
6150
wl_dinfo->op_band[phy] = wl_linfo[i].band;
6151
_update_dbcc_band(rtwdev, phy);
6152
_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6153
}
6154
6155
if (wl_linfo[i].connected == MLME_NO_LINK) {
6156
continue;
6157
} else if (wl_linfo[i].connected == MLME_LINKING) {
6158
cnt_connecting++;
6159
} else {
6160
cnt_connect++;
6161
if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6162
wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6163
wl_linfo[i].client_cnt > 1)
6164
client_joined = true;
6165
}
6166
6167
wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
6168
wl_rinfo->active_role[cnt_active - 1].ch = wl_linfo[i].ch;
6169
wl_rinfo->active_role[cnt_active - 1].bw = wl_linfo[i].bw;
6170
wl_rinfo->active_role[cnt_active - 1].connected = 1;
6171
6172
/* only care 2 roles + BT coex */
6173
if (wl_linfo[i].band != RTW89_BAND_2G) {
6174
if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
6175
wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
6176
cnt_5g++;
6177
b5g = true;
6178
} else {
6179
if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
6180
wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
6181
cnt_2g++;
6182
b2g = true;
6183
}
6184
}
6185
6186
wl_rinfo->connect_cnt = cnt_connect;
6187
6188
/* Be careful to change the following sequence!! */
6189
if (cnt_connect == 0) {
6190
wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6191
wl_rinfo->role_map.role.none = 1;
6192
} else if (!b2g && b5g) {
6193
wl_rinfo->link_mode = BTC_WLINK_5G;
6194
} else if (wl_rinfo->role_map.role.nan) {
6195
wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
6196
} else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
6197
wl_rinfo->link_mode = BTC_WLINK_OTHER;
6198
} else if (b2g && b5g && cnt_connect == 2) {
6199
if (rtwdev->dbcc_en) {
6200
switch (wl_dinfo->role[RTW89_PHY_0]) {
6201
case RTW89_WIFI_ROLE_STATION:
6202
wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6203
break;
6204
case RTW89_WIFI_ROLE_P2P_GO:
6205
wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6206
break;
6207
case RTW89_WIFI_ROLE_P2P_CLIENT:
6208
wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6209
break;
6210
case RTW89_WIFI_ROLE_AP:
6211
wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6212
break;
6213
default:
6214
wl_rinfo->link_mode = BTC_WLINK_OTHER;
6215
break;
6216
}
6217
} else {
6218
wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
6219
}
6220
} else if (!b5g && cnt_connect == 2) {
6221
if (wl_rinfo->role_map.role.station &&
6222
(wl_rinfo->role_map.role.p2p_go ||
6223
wl_rinfo->role_map.role.p2p_gc ||
6224
wl_rinfo->role_map.role.ap)) {
6225
if (wl_2g_ch[0] == wl_2g_ch[1])
6226
wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
6227
else
6228
wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6229
} else {
6230
wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6231
}
6232
} else if (!b5g && cnt_connect == 1) {
6233
if (wl_rinfo->role_map.role.station)
6234
wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6235
else if (wl_rinfo->role_map.role.ap)
6236
wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6237
else if (wl_rinfo->role_map.role.p2p_go)
6238
wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6239
else if (wl_rinfo->role_map.role.p2p_gc)
6240
wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6241
else
6242
wl_rinfo->link_mode = BTC_WLINK_OTHER;
6243
}
6244
6245
/* if no client_joined, don't care P2P-GO/AP role */
6246
if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6247
if (!client_joined) {
6248
if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6249
wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6250
wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6251
wl_rinfo->connect_cnt = 1;
6252
} else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6253
wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6254
wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6255
wl_rinfo->connect_cnt = 0;
6256
}
6257
}
6258
}
6259
6260
rtw89_debug(rtwdev, RTW89_DBG_BTC,
6261
"[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6262
cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6263
6264
_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6265
}
6266
6267
static void _update_wl_info_v1(struct rtw89_dev *rtwdev)
6268
{
6269
struct rtw89_btc *btc = &rtwdev->btc;
6270
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6271
struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6272
struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
6273
struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6274
u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
6275
u8 cnt_2g = 0, cnt_5g = 0, phy;
6276
u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
6277
bool b2g = false, b5g = false, client_joined = false;
6278
u8 i;
6279
6280
memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6281
6282
for (i = 0; i < RTW89_PORT_NUM; i++) {
6283
if (!wl_linfo[i].active)
6284
continue;
6285
6286
cnt_active++;
6287
wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role;
6288
wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid;
6289
wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy;
6290
wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band;
6291
wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
6292
wl_rinfo->active_role_v1[cnt_active - 1].connected = 0;
6293
6294
wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
6295
6296
phy = wl_linfo[i].phy;
6297
6298
if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) {
6299
wl_dinfo->role[phy] = wl_linfo[i].role;
6300
wl_dinfo->op_band[phy] = wl_linfo[i].band;
6301
_update_dbcc_band(rtwdev, phy);
6302
_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6303
}
6304
6305
if (wl_linfo[i].connected == MLME_NO_LINK) {
6306
continue;
6307
} else if (wl_linfo[i].connected == MLME_LINKING) {
6308
cnt_connecting++;
6309
} else {
6310
cnt_connect++;
6311
if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6312
wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6313
wl_linfo[i].client_cnt > 1)
6314
client_joined = true;
6315
}
6316
6317
wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
6318
wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch;
6319
wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw;
6320
wl_rinfo->active_role_v1[cnt_active - 1].connected = 1;
6321
6322
/* only care 2 roles + BT coex */
6323
if (wl_linfo[i].band != RTW89_BAND_2G) {
6324
if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
6325
wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
6326
cnt_5g++;
6327
b5g = true;
6328
} else {
6329
if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
6330
wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
6331
cnt_2g++;
6332
b2g = true;
6333
}
6334
}
6335
6336
wl_rinfo->connect_cnt = cnt_connect;
6337
6338
/* Be careful to change the following sequence!! */
6339
if (cnt_connect == 0) {
6340
wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6341
wl_rinfo->role_map.role.none = 1;
6342
} else if (!b2g && b5g) {
6343
wl_rinfo->link_mode = BTC_WLINK_5G;
6344
} else if (wl_rinfo->role_map.role.nan) {
6345
wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
6346
} else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
6347
wl_rinfo->link_mode = BTC_WLINK_OTHER;
6348
} else if (b2g && b5g && cnt_connect == 2) {
6349
if (rtwdev->dbcc_en) {
6350
switch (wl_dinfo->role[RTW89_PHY_0]) {
6351
case RTW89_WIFI_ROLE_STATION:
6352
wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6353
break;
6354
case RTW89_WIFI_ROLE_P2P_GO:
6355
wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6356
break;
6357
case RTW89_WIFI_ROLE_P2P_CLIENT:
6358
wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6359
break;
6360
case RTW89_WIFI_ROLE_AP:
6361
wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6362
break;
6363
default:
6364
wl_rinfo->link_mode = BTC_WLINK_OTHER;
6365
break;
6366
}
6367
} else {
6368
wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
6369
}
6370
} else if (!b5g && cnt_connect == 2) {
6371
if (wl_rinfo->role_map.role.station &&
6372
(wl_rinfo->role_map.role.p2p_go ||
6373
wl_rinfo->role_map.role.p2p_gc ||
6374
wl_rinfo->role_map.role.ap)) {
6375
if (wl_2g_ch[0] == wl_2g_ch[1])
6376
wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
6377
else
6378
wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6379
} else {
6380
wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6381
}
6382
} else if (!b5g && cnt_connect == 1) {
6383
if (wl_rinfo->role_map.role.station)
6384
wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6385
else if (wl_rinfo->role_map.role.ap)
6386
wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6387
else if (wl_rinfo->role_map.role.p2p_go)
6388
wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6389
else if (wl_rinfo->role_map.role.p2p_gc)
6390
wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6391
else
6392
wl_rinfo->link_mode = BTC_WLINK_OTHER;
6393
}
6394
6395
/* if no client_joined, don't care P2P-GO/AP role */
6396
if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6397
if (!client_joined) {
6398
if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6399
wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6400
wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6401
wl_rinfo->connect_cnt = 1;
6402
} else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6403
wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6404
wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6405
wl_rinfo->connect_cnt = 0;
6406
}
6407
}
6408
}
6409
6410
rtw89_debug(rtwdev, RTW89_DBG_BTC,
6411
"[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6412
cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6413
6414
_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6415
}
6416
6417
static void _update_wl_info_v2(struct rtw89_dev *rtwdev)
6418
{
6419
struct rtw89_btc *btc = &rtwdev->btc;
6420
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6421
struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6422
struct rtw89_btc_wl_role_info_v2 *wl_rinfo = &wl->role_info_v2;
6423
struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6424
u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
6425
u8 cnt_2g = 0, cnt_5g = 0, phy;
6426
u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
6427
bool b2g = false, b5g = false, client_joined = false;
6428
u8 i;
6429
6430
memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6431
6432
for (i = 0; i < RTW89_PORT_NUM; i++) {
6433
if (!wl_linfo[i].active)
6434
continue;
6435
6436
cnt_active++;
6437
wl_rinfo->active_role_v2[cnt_active - 1].role = wl_linfo[i].role;
6438
wl_rinfo->active_role_v2[cnt_active - 1].pid = wl_linfo[i].pid;
6439
wl_rinfo->active_role_v2[cnt_active - 1].phy = wl_linfo[i].phy;
6440
wl_rinfo->active_role_v2[cnt_active - 1].band = wl_linfo[i].band;
6441
wl_rinfo->active_role_v2[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
6442
wl_rinfo->active_role_v2[cnt_active - 1].connected = 0;
6443
6444
wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
6445
6446
phy = wl_linfo[i].phy;
6447
6448
if (rtwdev->dbcc_en && phy < RTW89_PHY_NUM) {
6449
wl_dinfo->role[phy] = wl_linfo[i].role;
6450
wl_dinfo->op_band[phy] = wl_linfo[i].band;
6451
_update_dbcc_band(rtwdev, phy);
6452
_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
6453
}
6454
6455
if (wl_linfo[i].connected == MLME_NO_LINK) {
6456
continue;
6457
} else if (wl_linfo[i].connected == MLME_LINKING) {
6458
cnt_connecting++;
6459
} else {
6460
cnt_connect++;
6461
if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6462
wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6463
wl_linfo[i].client_cnt > 1)
6464
client_joined = true;
6465
}
6466
6467
wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
6468
wl_rinfo->active_role_v2[cnt_active - 1].ch = wl_linfo[i].ch;
6469
wl_rinfo->active_role_v2[cnt_active - 1].bw = wl_linfo[i].bw;
6470
wl_rinfo->active_role_v2[cnt_active - 1].connected = 1;
6471
6472
/* only care 2 roles + BT coex */
6473
if (wl_linfo[i].band != RTW89_BAND_2G) {
6474
if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
6475
wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
6476
cnt_5g++;
6477
b5g = true;
6478
} else {
6479
if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
6480
wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
6481
cnt_2g++;
6482
b2g = true;
6483
}
6484
}
6485
6486
wl_rinfo->connect_cnt = cnt_connect;
6487
6488
/* Be careful to change the following sequence!! */
6489
if (cnt_connect == 0) {
6490
wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6491
wl_rinfo->role_map.role.none = 1;
6492
} else if (!b2g && b5g) {
6493
wl_rinfo->link_mode = BTC_WLINK_5G;
6494
} else if (wl_rinfo->role_map.role.nan) {
6495
wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
6496
} else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
6497
wl_rinfo->link_mode = BTC_WLINK_OTHER;
6498
} else if (b2g && b5g && cnt_connect == 2) {
6499
if (rtwdev->dbcc_en) {
6500
switch (wl_dinfo->role[RTW89_PHY_0]) {
6501
case RTW89_WIFI_ROLE_STATION:
6502
wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6503
break;
6504
case RTW89_WIFI_ROLE_P2P_GO:
6505
wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6506
break;
6507
case RTW89_WIFI_ROLE_P2P_CLIENT:
6508
wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6509
break;
6510
case RTW89_WIFI_ROLE_AP:
6511
wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6512
break;
6513
default:
6514
wl_rinfo->link_mode = BTC_WLINK_OTHER;
6515
break;
6516
}
6517
} else {
6518
wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
6519
}
6520
} else if (!b5g && cnt_connect == 2) {
6521
if (wl_rinfo->role_map.role.station &&
6522
(wl_rinfo->role_map.role.p2p_go ||
6523
wl_rinfo->role_map.role.p2p_gc ||
6524
wl_rinfo->role_map.role.ap)) {
6525
if (wl_2g_ch[0] == wl_2g_ch[1])
6526
wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
6527
else
6528
wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6529
} else {
6530
wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
6531
}
6532
} else if (!b5g && cnt_connect == 1) {
6533
if (wl_rinfo->role_map.role.station)
6534
wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6535
else if (wl_rinfo->role_map.role.ap)
6536
wl_rinfo->link_mode = BTC_WLINK_2G_AP;
6537
else if (wl_rinfo->role_map.role.p2p_go)
6538
wl_rinfo->link_mode = BTC_WLINK_2G_GO;
6539
else if (wl_rinfo->role_map.role.p2p_gc)
6540
wl_rinfo->link_mode = BTC_WLINK_2G_GC;
6541
else
6542
wl_rinfo->link_mode = BTC_WLINK_OTHER;
6543
}
6544
6545
/* if no client_joined, don't care P2P-GO/AP role */
6546
if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
6547
if (!client_joined) {
6548
if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
6549
wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
6550
wl_rinfo->link_mode = BTC_WLINK_2G_STA;
6551
wl_rinfo->connect_cnt = 1;
6552
} else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
6553
wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
6554
wl_rinfo->link_mode = BTC_WLINK_NOLINK;
6555
wl_rinfo->connect_cnt = 0;
6556
}
6557
}
6558
}
6559
6560
rtw89_debug(rtwdev, RTW89_DBG_BTC,
6561
"[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
6562
cnt_connect, cnt_connecting, wl_rinfo->link_mode);
6563
6564
_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6565
}
6566
6567
#define BTC_CHK_HANG_MAX 3
6568
#define BTC_SCB_INV_VALUE GENMASK(31, 0)
6569
6570
static u8 _get_role_link_mode(u8 role)
6571
{
6572
switch (role) {
6573
case RTW89_WIFI_ROLE_STATION:
6574
return BTC_WLINK_2G_STA;
6575
case RTW89_WIFI_ROLE_P2P_GO:
6576
return BTC_WLINK_2G_GO;
6577
case RTW89_WIFI_ROLE_P2P_CLIENT:
6578
return BTC_WLINK_2G_GC;
6579
case RTW89_WIFI_ROLE_AP:
6580
return BTC_WLINK_2G_AP;
6581
default:
6582
return BTC_WLINK_OTHER;
6583
}
6584
}
6585
6586
static bool _chk_role_ch_group(const struct rtw89_btc_chdef *r1,
6587
const struct rtw89_btc_chdef *r2)
6588
{
6589
if (r1->chan != r2->chan) { /* primary ch is different */
6590
return false;
6591
} else if (r1->bw == RTW89_CHANNEL_WIDTH_40 &&
6592
r2->bw == RTW89_CHANNEL_WIDTH_40) {
6593
if (r1->offset != r2->offset)
6594
return false;
6595
}
6596
return true;
6597
}
6598
6599
static u8 _chk_dbcc(struct rtw89_dev *rtwdev, struct rtw89_btc_chdef *ch,
6600
u8 *phy, u8 *role, u8 link_cnt)
6601
{
6602
struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6603
struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &wl->role_info_v7;
6604
struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &wl->role_info_v8;
6605
bool is_2g_ch_exist = false, is_multi_role_in_2g_phy = false;
6606
u8 j, k, dbcc_2g_cid, dbcc_2g_cid2, dbcc_2g_phy, pta_req_band;
6607
6608
/* find out the 2G-PHY by connect-id ->ch */
6609
for (j = 0; j < link_cnt; j++) {
6610
if (ch[j].center_ch <= 14) {
6611
is_2g_ch_exist = true;
6612
break;
6613
}
6614
}
6615
6616
/* If no any 2G-port exist, it's impossible because 5G-exclude */
6617
if (!is_2g_ch_exist)
6618
return BTC_WLINK_5G;
6619
6620
dbcc_2g_cid = j;
6621
dbcc_2g_phy = phy[dbcc_2g_cid];
6622
6623
if (dbcc_2g_phy == RTW89_PHY_1)
6624
pta_req_band = RTW89_PHY_1;
6625
else
6626
pta_req_band = RTW89_PHY_0;
6627
6628
if (rtwdev->btc.ver->fwlrole == 7) {
6629
rinfo_v7->dbcc_2g_phy = dbcc_2g_phy;
6630
} else if (rtwdev->btc.ver->fwlrole == 8) {
6631
rinfo_v8->dbcc_2g_phy = dbcc_2g_phy;
6632
rinfo_v8->pta_req_band = pta_req_band;
6633
}
6634
6635
/* connect_cnt <= 2 */
6636
if (link_cnt < BTC_TDMA_WLROLE_MAX)
6637
return (_get_role_link_mode((role[dbcc_2g_cid])));
6638
6639
/* find the other-port in the 2G-PHY, ex: PHY-0:6G, PHY1: mcc/scc */
6640
for (k = 0; k < link_cnt; k++) {
6641
if (k == dbcc_2g_cid)
6642
continue;
6643
6644
if (phy[k] == dbcc_2g_phy) {
6645
is_multi_role_in_2g_phy = true;
6646
dbcc_2g_cid2 = k;
6647
break;
6648
}
6649
}
6650
6651
/* Single-role in 2G-PHY */
6652
if (!is_multi_role_in_2g_phy)
6653
return (_get_role_link_mode(role[dbcc_2g_cid]));
6654
6655
/* 2-role in 2G-PHY */
6656
if (ch[dbcc_2g_cid2].center_ch > 14)
6657
return BTC_WLINK_25G_MCC;
6658
else if (_chk_role_ch_group(&ch[dbcc_2g_cid], &ch[dbcc_2g_cid2]))
6659
return BTC_WLINK_2G_SCC;
6660
else
6661
return BTC_WLINK_2G_MCC;
6662
}
6663
6664
static void _update_role_link_mode(struct rtw89_dev *rtwdev,
6665
bool client_joined, u32 noa)
6666
{
6667
struct rtw89_btc_wl_role_info_v8 *rinfo_v8 = &rtwdev->btc.cx.wl.role_info_v8;
6668
struct rtw89_btc_wl_role_info_v7 *rinfo_v7 = &rtwdev->btc.cx.wl.role_info_v7;
6669
u8 role_ver = rtwdev->btc.ver->fwlrole;
6670
u32 type = BTC_WLMROLE_NONE, dur = 0;
6671
u8 link_mode, connect_cnt;
6672
u32 wl_role;
6673
6674
if (role_ver == 7) {
6675
wl_role = rinfo_v7->role_map;
6676
link_mode = rinfo_v7->link_mode;
6677
connect_cnt = rinfo_v7->connect_cnt;
6678
} else if (role_ver == 8) {
6679
wl_role = rinfo_v8->role_map;
6680
link_mode = rinfo_v8->link_mode;
6681
connect_cnt = rinfo_v8->connect_cnt;
6682
} else {
6683
return;
6684
}
6685
6686
/* if no client_joined, don't care P2P-GO/AP role */
6687
if (((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
6688
(wl_role & BIT(RTW89_WIFI_ROLE_AP))) && !client_joined) {
6689
if (link_mode == BTC_WLINK_2G_SCC) {
6690
if (role_ver == 7) {
6691
rinfo_v7->link_mode = BTC_WLINK_2G_STA;
6692
rinfo_v7->connect_cnt--;
6693
} else if (role_ver == 8) {
6694
rinfo_v8->link_mode = BTC_WLINK_2G_STA;
6695
rinfo_v8->connect_cnt--;
6696
}
6697
} else if (link_mode == BTC_WLINK_2G_GO ||
6698
link_mode == BTC_WLINK_2G_AP) {
6699
if (role_ver == 7) {
6700
rinfo_v7->link_mode = BTC_WLINK_NOLINK;
6701
rinfo_v7->connect_cnt--;
6702
} else if (role_ver == 8) {
6703
rinfo_v8->link_mode = BTC_WLINK_NOLINK;
6704
rinfo_v8->connect_cnt--;
6705
}
6706
}
6707
}
6708
6709
/* Identify 2-Role type */
6710
if (connect_cnt >= 2 &&
6711
(link_mode == BTC_WLINK_2G_SCC ||
6712
link_mode == BTC_WLINK_2G_MCC ||
6713
link_mode == BTC_WLINK_25G_MCC ||
6714
link_mode == BTC_WLINK_5G)) {
6715
if ((wl_role & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
6716
(wl_role & BIT(RTW89_WIFI_ROLE_AP)))
6717
type = noa ? BTC_WLMROLE_STA_GO_NOA : BTC_WLMROLE_STA_GO;
6718
else if (wl_role & BIT(RTW89_WIFI_ROLE_P2P_CLIENT))
6719
type = noa ? BTC_WLMROLE_STA_GC_NOA : BTC_WLMROLE_STA_GC;
6720
else
6721
type = BTC_WLMROLE_STA_STA;
6722
6723
dur = noa;
6724
}
6725
6726
if (role_ver == 7) {
6727
rinfo_v7->mrole_type = type;
6728
rinfo_v7->mrole_noa_duration = dur;
6729
} else if (role_ver == 8) {
6730
rinfo_v8->mrole_type = type;
6731
rinfo_v8->mrole_noa_duration = dur;
6732
}
6733
}
6734
6735
static void _update_wl_info_v7(struct rtw89_dev *rtwdev, u8 rid)
6736
{
6737
struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER];
6738
struct rtw89_btc *btc = &rtwdev->btc;
6739
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
6740
struct rtw89_btc_wl_role_info_v7 *wl_rinfo = &wl->role_info_v7;
6741
struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
6742
struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
6743
struct rtw89_btc_wl_active_role_v7 *act_role = NULL;
6744
u8 i, mode, cnt = 0, cnt_2g = 0, cnt_5g = 0, phy_now = RTW89_PHY_NUM, phy_dbcc;
6745
bool b2g = false, b5g = false, client_joined = false, client_inc_2g = false;
6746
u8 client_cnt_last[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6747
u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6748
u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
6749
u8 mac = RTW89_MAC_0, dbcc_2g_phy = RTW89_PHY_0;
6750
u32 noa_duration = 0;
6751
6752
memset(wl_rinfo, 0, sizeof(*wl_rinfo));
6753
6754
for (i = 0; i < RTW89_PORT_NUM; i++) {
6755
if (!wl_linfo[i].active || wl_linfo[i].phy >= RTW89_PHY_NUM)
6756
continue;
6757
6758
act_role = &wl_rinfo->active_role[i];
6759
act_role->role = wl_linfo[i].role;
6760
6761
/* check if role connect? */
6762
if (wl_linfo[i].connected == MLME_NO_LINK) {
6763
act_role->connected = 0;
6764
continue;
6765
} else if (wl_linfo[i].connected == MLME_LINKING) {
6766
continue;
6767
}
6768
6769
cnt++;
6770
act_role->connected = 1;
6771
act_role->pid = wl_linfo[i].pid;
6772
act_role->phy = wl_linfo[i].phy;
6773
act_role->band = wl_linfo[i].band;
6774
act_role->ch = wl_linfo[i].ch;
6775
act_role->bw = wl_linfo[i].bw;
6776
act_role->noa = wl_linfo[i].noa;
6777
act_role->noa_dur = wl_linfo[i].noa_duration;
6778
cid_ch[cnt - 1] = wl_linfo[i].chdef;
6779
cid_phy[cnt - 1] = wl_linfo[i].phy;
6780
cid_role[cnt - 1] = wl_linfo[i].role;
6781
wl_rinfo->role_map |= BIT(wl_linfo[i].role);
6782
6783
if (rid == i)
6784
phy_now = act_role->phy;
6785
6786
if (wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6787
wl_linfo[i].role == RTW89_WIFI_ROLE_AP) {
6788
if (wl_linfo[i].client_cnt > 1)
6789
client_joined = true;
6790
if (client_cnt_last[i] < wl_linfo[i].client_cnt &&
6791
wl_linfo[i].chdef.band == RTW89_BAND_2G)
6792
client_inc_2g = true;
6793
act_role->client_cnt = wl_linfo[i].client_cnt;
6794
} else {
6795
act_role->client_cnt = 0;
6796
}
6797
6798
if (act_role->noa && act_role->noa_dur > 0)
6799
noa_duration = act_role->noa_dur;
6800
6801
if (rtwdev->dbcc_en) {
6802
phy_dbcc = wl_linfo[i].phy;
6803
wl_dinfo->role[phy_dbcc] |= BIT(wl_linfo[i].role);
6804
wl_dinfo->op_band[phy_dbcc] = wl_linfo[i].chdef.band;
6805
}
6806
6807
if (wl_linfo[i].chdef.band != RTW89_BAND_2G) {
6808
cnt_5g++;
6809
b5g = true;
6810
} else {
6811
if (((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
6812
wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
6813
client_joined) ||
6814
wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_CLIENT)
6815
wl_rinfo->p2p_2g = 1;
6816
6817
if ((wl_linfo[i].mode & BIT(BTC_WL_MODE_11B)) ||
6818
(wl_linfo[i].mode & BIT(BTC_WL_MODE_11G)))
6819
wl->bg_mode = 1;
6820
else if (wl_linfo[i].mode & BIT(BTC_WL_MODE_HE))
6821
wl->he_mode = true;
6822
6823
cnt_2g++;
6824
b2g = true;
6825
}
6826
6827
if (act_role->band == RTW89_BAND_5G && act_role->ch >= 100)
6828
wl->is_5g_hi_channel = 1;
6829
else
6830
wl->is_5g_hi_channel = 0;
6831
}
6832
6833
wl_rinfo->connect_cnt = cnt;
6834
wl->client_cnt_inc_2g = client_inc_2g;
6835
6836
if (cnt == 0) {
6837
mode = BTC_WLINK_NOLINK;
6838
wl_rinfo->role_map = BIT(RTW89_WIFI_ROLE_NONE);
6839
} else if (!b2g && b5g) {
6840
mode = BTC_WLINK_5G;
6841
} else if (wl_rinfo->role_map & BIT(RTW89_WIFI_ROLE_NAN)) {
6842
mode = BTC_WLINK_2G_NAN;
6843
} else if (cnt > BTC_TDMA_WLROLE_MAX) {
6844
mode = BTC_WLINK_OTHER;
6845
} else if (rtwdev->dbcc_en) {
6846
mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt);
6847
6848
/* correct 2G-located PHY band for gnt ctrl */
6849
if (dbcc_2g_phy < RTW89_PHY_NUM)
6850
wl_dinfo->op_band[dbcc_2g_phy] = RTW89_BAND_2G;
6851
} else if (b2g && b5g && cnt == 2) {
6852
mode = BTC_WLINK_25G_MCC;
6853
} else if (!b5g && cnt == 2) { /* cnt_connect = 2 */
6854
if (_chk_role_ch_group(&cid_ch[0], &cid_ch[cnt - 1]))
6855
mode = BTC_WLINK_2G_SCC;
6856
else
6857
mode = BTC_WLINK_2G_MCC;
6858
} else if (!b5g && cnt == 1) { /* cnt_connect = 1 */
6859
mode = _get_role_link_mode(cid_role[0]);
6860
} else {
6861
mode = BTC_WLINK_NOLINK;
6862
}
6863
6864
wl_rinfo->link_mode = mode;
6865
_update_role_link_mode(rtwdev, client_joined, noa_duration);
6866
6867
/* todo DBCC related event */
6868
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] wl_info phy_now=%d\n", phy_now);
6869
rtw89_debug(rtwdev, RTW89_DBG_BTC,
6870
"[BTC] rlink cnt_2g=%d cnt_5g=%d\n", cnt_2g, cnt_5g);
6871
6872
if (wl_rinfo->dbcc_en != rtwdev->dbcc_en) {
6873
wl_rinfo->dbcc_chg = 1;
6874
wl_rinfo->dbcc_en = rtwdev->dbcc_en;
6875
btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++;
6876
}
6877
6878
if (rtwdev->dbcc_en) {
6879
wl_rinfo->dbcc_2g_phy = dbcc_2g_phy;
6880
6881
if (dbcc_2g_phy == RTW89_PHY_1)
6882
mac = RTW89_MAC_1;
6883
6884
_update_dbcc_band(rtwdev, RTW89_PHY_0);
6885
_update_dbcc_band(rtwdev, RTW89_PHY_1);
6886
}
6887
_wl_req_mac(rtwdev, mac);
6888
_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
6889
}
6890
6891
static u8 _update_wl_link_mode(struct rtw89_dev *rtwdev, u8 hw_band, u8 type)
6892
{
6893
struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6894
struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info;
6895
u8 mode = BTC_WLINK_NOLINK;
6896
6897
switch (type) {
6898
case RTW89_MR_WTYPE_NONE: /* no-link */
6899
mode = BTC_WLINK_NOLINK;
6900
break;
6901
case RTW89_MR_WTYPE_NONMLD: /* Non_MLO 1-role 2+0/0+2 */
6902
case RTW89_MR_WTYPE_MLD1L1R: /* MLO only-1 link 2+0/0+2 */
6903
if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) {
6904
mode = BTC_WLINK_5G;
6905
} else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) {
6906
mode = BTC_WLINK_2G_GO;
6907
} else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT) {
6908
if (wl->role_info_v8.p2p_2g)
6909
mode = BTC_WLINK_2G_GC;
6910
else
6911
mode = BTC_WLINK_2G_STA;
6912
}
6913
break;
6914
case RTW89_MR_WTYPE_NONMLD_NONMLD: /* Non_MLO 2-role 2+0/0+2 */
6915
case RTW89_MR_WTYPE_MLD1L1R_NONMLD: /* MLO only-1 link + P2P 2+0/0+2 */
6916
if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) {
6917
mode = BTC_WLINK_5G;
6918
} else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_5GHZ ||
6919
mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ_6GHZ) {
6920
mode = BTC_WLINK_25G_MCC;
6921
} else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX2_2GHZ) {
6922
mode = BTC_WLINK_2G_MCC;
6923
} else if (mlo_info->ch_type[hw_band] == RTW89_MR_CTX1_2GHZ) {
6924
mode = BTC_WLINK_2G_SCC;
6925
}
6926
break;
6927
case RTW89_MR_WTYPE_MLD2L1R: /* MLO_MLSR 2+0/0+2 */
6928
if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G)
6929
mode = BTC_WLINK_5G;
6930
else if (wl->role_info_v8.p2p_2g)
6931
mode = BTC_WLINK_2G_GC;
6932
else
6933
mode = BTC_WLINK_2G_STA;
6934
break;
6935
case RTW89_MR_WTYPE_MLD2L1R_NONMLD: /* MLO_MLSR + P2P 2+0/0+2 */
6936
case RTW89_MR_WTYPE_MLD2L2R_NONMLD: /* MLO_MLMR + P2P 1+1/2+2 */
6937
/* driver may doze 1-link to
6938
* 2G+5G -> TDMA slot switch by E2G/E5G
6939
* 5G only -> TDMA slot switch by E5G
6940
*/
6941
mode = BTC_WLINK_25G_MCC;
6942
break;
6943
case RTW89_MR_WTYPE_MLD2L2R: /* MLO_MLMR 1+1/2+2 */
6944
if (mlo_info->hwb_rf_band[hw_band] != RTW89_BAND_2G) {
6945
mode = BTC_WLINK_5G;
6946
} else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1AP) {
6947
mode = BTC_WLINK_2G_GO;
6948
} else if (mlo_info->wmode[hw_band] == RTW89_MR_WMODE_1CLIENT) {
6949
if (wl->role_info_v8.p2p_2g)
6950
mode = BTC_WLINK_2G_GC;
6951
else
6952
mode = BTC_WLINK_2G_STA;
6953
}
6954
break;
6955
}
6956
return mode;
6957
}
6958
6959
static void _update_wl_mlo_info(struct rtw89_dev *rtwdev)
6960
{
6961
struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
6962
struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
6963
struct rtw89_btc_wl_mlo_info *mlo_info = &wl->mlo_info;
6964
struct rtw89_mr_chanctx_info qinfo;
6965
u8 track_band = RTW89_PHY_0;
6966
u8 rf_band = RTW89_BAND_2G;
6967
u8 i, type;
6968
6969
/* parse MLO info form PHL API for each HW-band */
6970
for (i = RTW89_MAC_0; i <= RTW89_MAC_1; i++) {
6971
memset(&qinfo, 0, sizeof(qinfo));
6972
6973
rtw89_query_mr_chanctx_info(rtwdev, i, &qinfo);
6974
mlo_info->wmode[i] = qinfo.wmode;
6975
mlo_info->ch_type[i] = qinfo.ctxtype;
6976
mlo_info->wtype = qinfo.wtype;
6977
6978
if (mlo_info->ch_type[i] == RTW89_MR_CTX1_5GHZ ||
6979
mlo_info->ch_type[i] == RTW89_MR_CTX2_5GHZ ||
6980
mlo_info->ch_type[i] == RTW89_MR_CTX2_5GHZ_6GHZ)
6981
mlo_info->hwb_rf_band[i] = RTW89_BAND_5G;
6982
else if (mlo_info->ch_type[i] == RTW89_MR_CTX1_6GHZ ||
6983
mlo_info->ch_type[i] == RTW89_MR_CTX2_6GHZ)
6984
mlo_info->hwb_rf_band[i] = RTW89_BAND_6G;
6985
else /* check if "2G-included" or unknown in each HW-band */
6986
mlo_info->hwb_rf_band[i] = RTW89_BAND_2G;
6987
}
6988
6989
mlo_info->link_status = rtwdev->mlo_dbcc_mode;
6990
type = mlo_info->wtype;
6991
6992
if (mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R ||
6993
mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R ||
6994
mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R ||
6995
mlo_info->wtype == RTW89_MR_WTYPE_MLD1L1R_NONMLD ||
6996
mlo_info->wtype == RTW89_MR_WTYPE_MLD2L1R_NONMLD ||
6997
mlo_info->wtype == RTW89_MR_WTYPE_MLD2L2R_NONMLD)
6998
mlo_info->mlo_en = 1;
6999
else
7000
mlo_info->mlo_en = 0;
7001
7002
if (mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_NONE &&
7003
mlo_info->ch_type[RTW89_MAC_0] != RTW89_MR_CTX_UNKNOWN &&
7004
mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_NONE &&
7005
mlo_info->ch_type[RTW89_MAC_1] != RTW89_MR_CTX_UNKNOWN)
7006
mlo_info->dual_hw_band_en = 1; /* two HW-hand link exist */
7007
else
7008
mlo_info->dual_hw_band_en = 0;
7009
7010
if (mlo_info->link_status == MLO_2_PLUS_0_2RF ||
7011
mlo_info->link_status == MLO_0_PLUS_2_2RF ||
7012
mlo_info->link_status == MLO_2_PLUS_2_2RF)
7013
mlo_info->mlo_adie = 2;
7014
else
7015
mlo_info->mlo_adie = 1;
7016
7017
switch (mlo_info->link_status) {
7018
default:
7019
case MLO_2_PLUS_0_1RF: /* 2+0 */
7020
case MLO_2_PLUS_0_2RF:
7021
mlo_info->rf_combination = BTC_MLO_RF_2_PLUS_0;
7022
track_band = RTW89_MAC_0;
7023
rf_band = mlo_info->hwb_rf_band[RTW89_MAC_0];
7024
mlo_info->path_rf_band[BTC_RF_S0] = rf_band;
7025
mlo_info->path_rf_band[BTC_RF_S1] = rf_band;
7026
7027
wl_rinfo->pta_req_band = RTW89_MAC_0;
7028
wl_rinfo->dbcc_2g_phy = RTW89_PHY_0;
7029
wl_rinfo->dbcc_en = 0;
7030
break;
7031
case MLO_0_PLUS_2_1RF: /* 0+2 */
7032
case MLO_0_PLUS_2_2RF:
7033
mlo_info->rf_combination = BTC_MLO_RF_0_PLUS_2;
7034
track_band = RTW89_MAC_1;
7035
rf_band = mlo_info->hwb_rf_band[RTW89_MAC_1];
7036
mlo_info->path_rf_band[BTC_RF_S0] = rf_band;
7037
mlo_info->path_rf_band[BTC_RF_S1] = rf_band;
7038
7039
wl_rinfo->pta_req_band = RTW89_MAC_1;
7040
wl_rinfo->dbcc_2g_phy = RTW89_PHY_1;
7041
wl_rinfo->dbcc_en = 0;
7042
break;
7043
case MLO_1_PLUS_1_1RF: /* 1+1 */
7044
case MLO_1_PLUS_1_2RF: /* 1+1 */
7045
case MLO_2_PLUS_2_2RF: /* 2+2 */
7046
case DBCC_LEGACY: /* DBCC 1+1 */
7047
if (mlo_info->link_status == MLO_2_PLUS_2_2RF)
7048
mlo_info->rf_combination = BTC_MLO_RF_2_PLUS_2;
7049
else
7050
mlo_info->rf_combination = BTC_MLO_RF_1_PLUS_1;
7051
7052
if (mlo_info->hwb_rf_band[RTW89_MAC_0] == RTW89_BAND_2G)
7053
track_band = RTW89_MAC_0;
7054
else
7055
track_band = RTW89_MAC_1;
7056
7057
mlo_info->path_rf_band[BTC_RF_S0] =
7058
mlo_info->hwb_rf_band[RTW89_MAC_0];
7059
mlo_info->path_rf_band[BTC_RF_S1] =
7060
mlo_info->hwb_rf_band[RTW89_MAC_1];
7061
7062
/* Check ch count from ch_type @ 2.4G HW-band, and modify type */
7063
if (mlo_info->ch_type[track_band] == RTW89_MR_CTX1_2GHZ)
7064
type = RTW89_MR_WTYPE_NONMLD; /* only 1-role at 2G */
7065
else
7066
type = RTW89_MR_WTYPE_NONMLD_NONMLD;
7067
7068
if (mlo_info->hwb_rf_band[RTW89_MAC_0] == RTW89_BAND_2G) {
7069
wl_rinfo->pta_req_band = RTW89_MAC_0;
7070
wl_rinfo->dbcc_2g_phy = RTW89_PHY_0;
7071
} else {
7072
wl_rinfo->pta_req_band = RTW89_MAC_1;
7073
wl_rinfo->dbcc_2g_phy = RTW89_PHY_1;
7074
}
7075
7076
if (mlo_info->wmode[RTW89_MAC_0] == RTW89_MR_WMODE_NONE &&
7077
mlo_info->wmode[RTW89_MAC_1] == RTW89_MR_WMODE_NONE)
7078
wl_rinfo->dbcc_en = 0;
7079
else
7080
wl_rinfo->dbcc_en = 1;
7081
break;
7082
}
7083
7084
wl_rinfo->link_mode = _update_wl_link_mode(rtwdev, track_band, type);
7085
7086
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(), mode=%s, pta_band=%d",
7087
__func__, id_to_linkmode(wl_rinfo->link_mode),
7088
wl_rinfo->pta_req_band);
7089
}
7090
7091
static void _update_wl_non_mlo_info(struct rtw89_dev *rtwdev)
7092
{
7093
struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
7094
struct rtw89_btc_wl_rlink *rlink = NULL;
7095
struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
7096
struct rtw89_btc_chdef cid_ch[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7097
u8 cid_role[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7098
u8 cid_phy[RTW89_BE_BTC_WL_MAX_ROLE_NUMBER] = {};
7099
bool b2g = false, b5g = false, outloop = false;
7100
u8 mode = BTC_WLINK_NOLINK;
7101
u8 cnt_2g = 0, cnt_5g = 0;
7102
u8 i, j, cnt = 0;
7103
7104
for (j = RTW89_PHY_0; j < RTW89_PHY_NUM; j++) {
7105
for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
7106
rlink = &wl_rinfo->rlink[i][j];
7107
7108
if (!rlink->active || !rlink->connected)
7109
continue;
7110
7111
if (cnt >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER) {
7112
outloop = true;
7113
break;
7114
}
7115
7116
cid_ch[cnt] = wl->rlink_info[i][j].chdef;
7117
cid_phy[cnt] = rlink->phy;
7118
cid_role[cnt] = rlink->role;
7119
cnt++;
7120
7121
if (rlink->rf_band != RTW89_BAND_2G) {
7122
cnt_5g++;
7123
b5g = true;
7124
} else {
7125
cnt_2g++;
7126
b2g = true;
7127
}
7128
}
7129
if (outloop)
7130
break;
7131
}
7132
7133
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7134
"[BTC], %s(): cnt_2g=%d, cnt_5g=%d\n", __func__, cnt_2g, cnt_5g);
7135
7136
wl_rinfo->dbcc_en = rtwdev->dbcc_en;
7137
/* Be careful to change the following sequence!! */
7138
if (cnt == 0) {
7139
mode = BTC_WLINK_NOLINK;
7140
} else if (!b2g && b5g) {
7141
mode = BTC_WLINK_5G;
7142
} else if (wl_rinfo->dbcc_en) {
7143
mode = _chk_dbcc(rtwdev, cid_ch, cid_phy, cid_role, cnt);
7144
} else if (b2g && b5g) {
7145
mode = BTC_WLINK_25G_MCC;
7146
} else if (!b5g && cnt >= 2) {
7147
if (_chk_role_ch_group(&cid_ch[0], &cid_ch[1]))
7148
mode = BTC_WLINK_2G_SCC;
7149
else
7150
mode = BTC_WLINK_2G_MCC;
7151
} else if (!b5g) { /* cnt_connect = 1 */
7152
mode = _get_role_link_mode(cid_role[0]);
7153
}
7154
7155
wl_rinfo->link_mode = mode;
7156
}
7157
7158
static void _modify_role_link_mode(struct rtw89_dev *rtwdev)
7159
{
7160
struct rtw89_btc_wl_info *wl = &rtwdev->btc.cx.wl;
7161
struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
7162
u8 go_cleint_exist = wl->go_client_exist;
7163
u8 link_mode = wl_rinfo->link_mode;
7164
u32 role_map = wl_rinfo->role_map;
7165
u8 noa_exist = wl->noa_exist;
7166
u32 mrole = BTC_WLMROLE_NONE;
7167
7168
/* if no client_joined, don't care P2P-GO/AP role */
7169
if (((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
7170
(role_map & BIT(RTW89_WIFI_ROLE_AP))) && !go_cleint_exist) {
7171
if (link_mode == BTC_WLINK_2G_SCC) {
7172
wl_rinfo->link_mode = BTC_WLINK_2G_STA;
7173
} else if (link_mode == BTC_WLINK_2G_GO ||
7174
link_mode == BTC_WLINK_2G_AP) {
7175
wl_rinfo->link_mode = BTC_WLINK_NOLINK;
7176
}
7177
}
7178
7179
/* Identify 2-Role type */
7180
if (link_mode == BTC_WLINK_2G_SCC ||
7181
link_mode == BTC_WLINK_2G_MCC ||
7182
link_mode == BTC_WLINK_25G_MCC ||
7183
link_mode == BTC_WLINK_5G) {
7184
if ((role_map & BIT(RTW89_WIFI_ROLE_P2P_GO)) ||
7185
(role_map & BIT(RTW89_WIFI_ROLE_AP))) {
7186
if (noa_exist)
7187
mrole = BTC_WLMROLE_STA_GO_NOA;
7188
else
7189
mrole = BTC_WLMROLE_STA_GO;
7190
} else if (role_map & BIT(RTW89_WIFI_ROLE_P2P_CLIENT)) {
7191
if (noa_exist)
7192
mrole = BTC_WLMROLE_STA_GC_NOA;
7193
else
7194
mrole = BTC_WLMROLE_STA_GC;
7195
} else {
7196
mrole = BTC_WLMROLE_STA_STA;
7197
}
7198
}
7199
7200
wl_rinfo->mrole_type = mrole;
7201
7202
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7203
"[BTC], %s(): link_mode=%s, mrole_type=%d\n", __func__,
7204
id_to_linkmode(wl_rinfo->link_mode), wl_rinfo->mrole_type);
7205
}
7206
7207
static void _update_wl_info_v8(struct rtw89_dev *rtwdev, u8 role_id, u8 rlink_id,
7208
enum btc_role_state state)
7209
{
7210
struct rtw89_btc_wl_rlink *rlink = NULL;
7211
struct rtw89_btc_wl_link_info *wl_linfo;
7212
struct rtw89_btc *btc = &rtwdev->btc;
7213
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7214
struct rtw89_btc_wl_role_info_v8 *wl_rinfo = &wl->role_info_v8;
7215
bool client_joined = false, noa_exist = false, p2p_exist = false;
7216
bool is_5g_hi_channel = false, bg_mode = false, dbcc_en_ori;
7217
u8 i, j, link_mode_ori;
7218
u32 role_map = 0;
7219
7220
if (role_id >= RTW89_BE_BTC_WL_MAX_ROLE_NUMBER || rlink_id >= RTW89_MAC_NUM)
7221
return;
7222
7223
/* Extract wl->link_info[role_id][rlink_id] to wl->role_info
7224
* role_id: role index
7225
* rlink_id: rlink index (= HW-band index)
7226
* pid: port_index
7227
*/
7228
7229
wl_linfo = &wl->rlink_info[role_id][rlink_id];
7230
rlink = &wl_rinfo->rlink[role_id][rlink_id];
7231
7232
rlink->role = wl_linfo->role;
7233
rlink->active = wl_linfo->active; /* Doze or not */
7234
rlink->pid = wl_linfo->pid;
7235
rlink->phy = wl_linfo->phy;
7236
rlink->rf_band = wl_linfo->band;
7237
rlink->ch = wl_linfo->ch;
7238
rlink->bw = wl_linfo->bw;
7239
rlink->noa = wl_linfo->noa;
7240
rlink->noa_dur = wl_linfo->noa_duration / 1000;
7241
rlink->client_cnt = wl_linfo->client_cnt;
7242
rlink->mode = wl_linfo->mode;
7243
7244
switch (wl_linfo->connected) {
7245
case MLME_NO_LINK:
7246
rlink->connected = 0;
7247
break;
7248
case MLME_LINKED:
7249
rlink->connected = 1;
7250
break;
7251
default:
7252
return;
7253
}
7254
7255
for (j = RTW89_MAC_0; j <= RTW89_MAC_1; j++) {
7256
for (i = 0; i < RTW89_BE_BTC_WL_MAX_ROLE_NUMBER; i++) {
7257
rlink = &wl_rinfo->rlink[i][j];
7258
7259
if (!rlink->active || !rlink->connected)
7260
continue;
7261
7262
role_map |= BIT(rlink->role);
7263
7264
/* only one noa-role exist */
7265
if (rlink->noa && rlink->noa_dur > 0)
7266
noa_exist = true;
7267
7268
/* for WL 5G-Rx interfered with BT issue */
7269
if (rlink->rf_band == RTW89_BAND_5G) {
7270
if (rlink->ch >= 100)
7271
is_5g_hi_channel = true;
7272
7273
continue;
7274
}
7275
7276
/* only if client connect for p2p-Go/AP */
7277
if ((rlink->role == RTW89_WIFI_ROLE_P2P_GO ||
7278
rlink->role == RTW89_WIFI_ROLE_AP) &&
7279
rlink->client_cnt > 1) {
7280
p2p_exist = true;
7281
client_joined = true;
7282
}
7283
7284
/* Identify if P2P-Go (GO/GC/AP) exist at 2G band */
7285
if (rlink->role == RTW89_WIFI_ROLE_P2P_CLIENT)
7286
p2p_exist = true;
7287
7288
if ((rlink->mode & BIT(BTC_WL_MODE_11B)) ||
7289
(rlink->mode & BIT(BTC_WL_MODE_11G)))
7290
bg_mode = true;
7291
}
7292
}
7293
7294
link_mode_ori = wl_rinfo->link_mode;
7295
wl->is_5g_hi_channel = is_5g_hi_channel;
7296
wl->bg_mode = bg_mode;
7297
wl->go_client_exist = client_joined;
7298
wl->noa_exist = noa_exist;
7299
wl_rinfo->p2p_2g = p2p_exist;
7300
wl_rinfo->role_map = role_map;
7301
7302
dbcc_en_ori = wl_rinfo->dbcc_en;
7303
7304
if (rtwdev->chip->para_ver & BTC_FEAT_MLO_SUPPORT) {
7305
/* for MLO-supported, link-mode from driver directly */
7306
_update_wl_mlo_info(rtwdev);
7307
} else {
7308
/* for non-MLO-supported, link-mode by BTC */
7309
_update_wl_non_mlo_info(rtwdev);
7310
}
7311
7312
_modify_role_link_mode(rtwdev);
7313
7314
if (link_mode_ori != wl_rinfo->link_mode)
7315
wl->link_mode_chg = true;
7316
7317
if (wl_rinfo->dbcc_en != dbcc_en_ori) {
7318
wl->dbcc_chg = true;
7319
btc->cx.cnt_wl[BTC_WCNT_DBCC_CHG]++;
7320
}
7321
}
7322
7323
void rtw89_coex_act1_work(struct wiphy *wiphy, struct wiphy_work *work)
7324
{
7325
struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7326
coex_act1_work.work);
7327
struct rtw89_btc *btc = &rtwdev->btc;
7328
struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7329
struct rtw89_btc_cx *cx = &btc->cx;
7330
struct rtw89_btc_wl_info *wl = &cx->wl;
7331
7332
lockdep_assert_wiphy(wiphy);
7333
7334
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7335
dm->cnt_notify[BTC_NCNT_TIMER]++;
7336
if (wl->status.map._4way)
7337
wl->status.map._4way = false;
7338
if (wl->status.map.connecting)
7339
wl->status.map.connecting = false;
7340
7341
_run_coex(rtwdev, BTC_RSN_ACT1_WORK);
7342
}
7343
7344
void rtw89_coex_bt_devinfo_work(struct wiphy *wiphy, struct wiphy_work *work)
7345
{
7346
struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7347
coex_bt_devinfo_work.work);
7348
struct rtw89_btc *btc = &rtwdev->btc;
7349
struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7350
struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
7351
7352
lockdep_assert_wiphy(wiphy);
7353
7354
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7355
dm->cnt_notify[BTC_NCNT_TIMER]++;
7356
a2dp->play_latency = 0;
7357
_run_coex(rtwdev, BTC_RSN_BT_DEVINFO_WORK);
7358
}
7359
7360
void rtw89_coex_rfk_chk_work(struct wiphy *wiphy, struct wiphy_work *work)
7361
{
7362
struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7363
coex_rfk_chk_work.work);
7364
struct rtw89_btc *btc = &rtwdev->btc;
7365
struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7366
struct rtw89_btc_cx *cx = &btc->cx;
7367
struct rtw89_btc_wl_info *wl = &cx->wl;
7368
7369
lockdep_assert_wiphy(wiphy);
7370
7371
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): enter\n", __func__);
7372
dm->cnt_notify[BTC_NCNT_TIMER]++;
7373
if (wl->rfk_info.state != BTC_WRFK_STOP) {
7374
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7375
"[BTC], %s(): RFK timeout\n", __func__);
7376
cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]++;
7377
dm->error.map.wl_rfk_timeout = true;
7378
wl->rfk_info.state = BTC_WRFK_STOP;
7379
_write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
7380
_run_coex(rtwdev, BTC_RSN_RFK_CHK_WORK);
7381
}
7382
}
7383
7384
static void _update_bt_scbd(struct rtw89_dev *rtwdev, bool only_update)
7385
{
7386
const struct rtw89_chip_info *chip = rtwdev->chip;
7387
struct rtw89_btc *btc = &rtwdev->btc;
7388
struct rtw89_btc_cx *cx = &btc->cx;
7389
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
7390
u32 val;
7391
bool status_change = false;
7392
7393
if (!chip->scbd)
7394
return;
7395
7396
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s\n", __func__);
7397
7398
val = _read_scbd(rtwdev);
7399
if (val == BTC_SCB_INV_VALUE) {
7400
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7401
"[BTC], %s(): return by invalid scbd value\n",
7402
__func__);
7403
return;
7404
}
7405
7406
if (!(val & BTC_BSCB_ON))
7407
bt->enable.now = 0;
7408
else
7409
bt->enable.now = 1;
7410
7411
if (bt->enable.now != bt->enable.last)
7412
status_change = true;
7413
7414
/* reset bt info if bt re-enable */
7415
if (bt->enable.now && !bt->enable.last) {
7416
_reset_btc_var(rtwdev, BTC_RESET_BTINFO);
7417
cx->cnt_bt[BTC_BCNT_REENABLE]++;
7418
bt->enable.now = 1;
7419
}
7420
7421
bt->enable.last = bt->enable.now;
7422
bt->scbd = val;
7423
bt->mbx_avl = !!(val & BTC_BSCB_ACT);
7424
7425
if (bt->whql_test != !!(val & BTC_BSCB_WHQL))
7426
status_change = true;
7427
7428
bt->whql_test = !!(val & BTC_BSCB_WHQL);
7429
bt->btg_type = val & BTC_BSCB_BT_S1 ? BTC_BT_BTG : BTC_BT_ALONE;
7430
bt->link_info.a2dp_desc.exist = !!(val & BTC_BSCB_A2DP_ACT);
7431
7432
bt->lna_constrain = !!(val & BTC_BSCB_BT_LNAB0) +
7433
!!(val & BTC_BSCB_BT_LNAB1) * 2 + 4;
7434
7435
/* if rfk run 1->0 */
7436
if (bt->rfk_info.map.run && !(val & BTC_BSCB_RFK_RUN))
7437
status_change = true;
7438
7439
bt->rfk_info.map.run = !!(val & BTC_BSCB_RFK_RUN);
7440
bt->rfk_info.map.req = !!(val & BTC_BSCB_RFK_REQ);
7441
bt->hi_lna_rx = !!(val & BTC_BSCB_BT_HILNA);
7442
bt->link_info.status.map.connect = !!(val & BTC_BSCB_BT_CONNECT);
7443
if (bt->run_patch_code != !!(val & BTC_BSCB_PATCH_CODE))
7444
status_change = true;
7445
bt->run_patch_code = !!(val & BTC_BSCB_PATCH_CODE);
7446
7447
if (!only_update && status_change)
7448
_run_coex(rtwdev, BTC_RSN_UPDATE_BT_SCBD);
7449
}
7450
7451
#define BTC_BTINFO_PWR_LEN 5
7452
static void _update_bt_txpwr_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
7453
{
7454
struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt;
7455
struct rtw89_btc_bt_link_info *b = &bt->link_info;
7456
7457
if (len != BTC_BTINFO_PWR_LEN)
7458
return;
7459
7460
if (!memcmp(bt->txpwr_info, buf, sizeof(bt->txpwr_info))) {
7461
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7462
"[BTC], %s return by info duplicate!\n", __func__);
7463
return;
7464
}
7465
7466
memcpy(bt->txpwr_info, buf, BTC_BTINFO_MAX);
7467
memcpy(&b->bt_txpwr_desc, &buf[2], sizeof(b->bt_txpwr_desc));
7468
}
7469
7470
static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev)
7471
{
7472
struct rtw89_btc *btc = &rtwdev->btc;
7473
struct rtw89_btc_cx *cx = &btc->cx;
7474
struct rtw89_btc_bt_info *bt = &cx->bt;
7475
7476
_update_bt_scbd(rtwdev, true);
7477
7478
cx->cnt_wl[BTC_WCNT_RFK_REQ]++;
7479
7480
if ((bt->rfk_info.map.run || bt->rfk_info.map.req) &&
7481
!bt->rfk_info.map.timeout) {
7482
cx->cnt_wl[BTC_WCNT_RFK_REJECT]++;
7483
} else {
7484
cx->cnt_wl[BTC_WCNT_RFK_GO]++;
7485
return true;
7486
}
7487
return false;
7488
}
7489
7490
static
7491
void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
7492
{
7493
struct rtw89_btc *btc = &rtwdev->btc;
7494
const struct rtw89_btc_ver *ver = btc->ver;
7495
struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7496
struct rtw89_btc_cx *cx = &btc->cx;
7497
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7498
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
7499
struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
7500
struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
7501
struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
7502
struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
7503
struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
7504
u8 mode, igno_bt, always_freerun;
7505
7506
lockdep_assert_wiphy(rtwdev->hw->wiphy);
7507
7508
dm->run_reason = reason;
7509
_update_dm_step(rtwdev, reason);
7510
_update_btc_state_map(rtwdev);
7511
7512
if (ver->fwlrole == 0)
7513
mode = wl_rinfo->link_mode;
7514
else if (ver->fwlrole == 1)
7515
mode = wl_rinfo_v1->link_mode;
7516
else if (ver->fwlrole == 2)
7517
mode = wl_rinfo_v2->link_mode;
7518
else if (ver->fwlrole == 7)
7519
mode = wl_rinfo_v7->link_mode;
7520
else if (ver->fwlrole == 8)
7521
mode = wl_rinfo_v8->link_mode;
7522
else
7523
return;
7524
7525
if (ver->fcxctrl == 7) {
7526
igno_bt = btc->ctrl.ctrl_v7.igno_bt;
7527
always_freerun = btc->ctrl.ctrl_v7.always_freerun;
7528
} else {
7529
igno_bt = btc->ctrl.ctrl.igno_bt;
7530
always_freerun = btc->ctrl.ctrl.always_freerun;
7531
}
7532
7533
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
7534
__func__, reason, mode);
7535
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
7536
__func__, dm->wl_only, dm->bt_only);
7537
7538
/* Be careful to change the following function sequence!! */
7539
if (btc->manual_ctrl) {
7540
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7541
"[BTC], %s(): return for Manual CTRL!!\n",
7542
__func__);
7543
return;
7544
}
7545
7546
if (igno_bt &&
7547
(reason == BTC_RSN_UPDATE_BT_INFO ||
7548
reason == BTC_RSN_UPDATE_BT_SCBD)) {
7549
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7550
"[BTC], %s(): return for Stop Coex DM!!\n",
7551
__func__);
7552
return;
7553
}
7554
7555
if (!wl->status.map.init_ok) {
7556
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7557
"[BTC], %s(): return for WL init fail!!\n",
7558
__func__);
7559
return;
7560
}
7561
7562
if (wl->status.map.rf_off_pre == wl->status.map.rf_off &&
7563
wl->status.map.lps_pre == wl->status.map.lps) {
7564
if (reason == BTC_RSN_NTFY_POWEROFF ||
7565
reason == BTC_RSN_NTFY_RADIO_STATE) {
7566
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7567
"[BTC], %s(): return for WL rf off state no change!!\n",
7568
__func__);
7569
return;
7570
}
7571
if (wl->status.map.rf_off == 1 ||
7572
wl->status.map.lps == BTC_LPS_RF_OFF) {
7573
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7574
"[BTC], %s(): return for WL rf off state!!\n",
7575
__func__);
7576
return;
7577
}
7578
}
7579
7580
dm->freerun = false;
7581
dm->cnt_dm[BTC_DCNT_RUN]++;
7582
dm->fddt_train = BTC_FDDT_DISABLE;
7583
bt->scan_rx_low_pri = false;
7584
igno_bt = false;
7585
7586
dm->freerun_chk = _check_freerun(rtwdev); /* check if meet freerun */
7587
7588
if (always_freerun) {
7589
_action_freerun(rtwdev);
7590
igno_bt = true;
7591
goto exit;
7592
}
7593
7594
if (dm->wl_only) {
7595
_action_wl_only(rtwdev);
7596
igno_bt = true;
7597
goto exit;
7598
}
7599
7600
if (wl->status.map.rf_off || wl->status.map.lps || dm->bt_only) {
7601
_action_wl_off(rtwdev, mode);
7602
igno_bt = true;
7603
goto exit;
7604
}
7605
7606
if (reason == BTC_RSN_NTFY_INIT) {
7607
_action_wl_init(rtwdev);
7608
goto exit;
7609
}
7610
7611
if (!cx->bt.enable.now && !cx->other.type) {
7612
_action_bt_off(rtwdev);
7613
goto exit;
7614
}
7615
7616
if (cx->bt.whql_test) {
7617
_action_bt_whql(rtwdev);
7618
goto exit;
7619
}
7620
7621
if (wl->rfk_info.state != BTC_WRFK_STOP) {
7622
_action_wl_rfk(rtwdev);
7623
goto exit;
7624
}
7625
7626
if (wl->status.val & btc_scanning_map.val && !wl->rfk_info.con_rfk) {
7627
_action_wl_scan(rtwdev);
7628
bt->scan_rx_low_pri = true;
7629
goto exit;
7630
}
7631
7632
switch (mode) {
7633
case BTC_WLINK_NOLINK:
7634
_action_wl_nc(rtwdev);
7635
break;
7636
case BTC_WLINK_2G_STA:
7637
if (wl->status.map.traffic_dir & BIT(RTW89_TFC_DL))
7638
bt->scan_rx_low_pri = true;
7639
_action_wl_2g_sta(rtwdev);
7640
break;
7641
case BTC_WLINK_2G_AP:
7642
bt->scan_rx_low_pri = true;
7643
_action_wl_2g_ap(rtwdev);
7644
break;
7645
case BTC_WLINK_2G_GO:
7646
bt->scan_rx_low_pri = true;
7647
_action_wl_2g_go(rtwdev);
7648
break;
7649
case BTC_WLINK_2G_GC:
7650
bt->scan_rx_low_pri = true;
7651
_action_wl_2g_gc(rtwdev);
7652
break;
7653
case BTC_WLINK_2G_SCC:
7654
bt->scan_rx_low_pri = true;
7655
if (ver->fwlrole == 0)
7656
_action_wl_2g_scc(rtwdev);
7657
else if (ver->fwlrole == 1)
7658
_action_wl_2g_scc_v1(rtwdev);
7659
else if (ver->fwlrole == 2 || ver->fwlrole == 7)
7660
_action_wl_2g_scc_v2(rtwdev);
7661
else if (ver->fwlrole == 8)
7662
_action_wl_2g_scc_v8(rtwdev);
7663
break;
7664
case BTC_WLINK_2G_MCC:
7665
bt->scan_rx_low_pri = true;
7666
_action_wl_2g_mcc(rtwdev);
7667
break;
7668
case BTC_WLINK_25G_MCC:
7669
bt->scan_rx_low_pri = true;
7670
_action_wl_25g_mcc(rtwdev);
7671
break;
7672
case BTC_WLINK_5G:
7673
_action_wl_5g(rtwdev);
7674
break;
7675
case BTC_WLINK_2G_NAN:
7676
_action_wl_2g_nan(rtwdev);
7677
break;
7678
default:
7679
_action_wl_other(rtwdev);
7680
break;
7681
}
7682
7683
exit:
7684
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): exit\n", __func__);
7685
if (ver->fcxctrl == 7)
7686
btc->ctrl.ctrl_v7.igno_bt = igno_bt;
7687
else
7688
btc->ctrl.ctrl.igno_bt = igno_bt;
7689
_action_common(rtwdev);
7690
}
7691
7692
void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
7693
{
7694
struct rtw89_btc *btc = &rtwdev->btc;
7695
7696
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
7697
btc->dm.cnt_notify[BTC_NCNT_POWER_ON]++;
7698
}
7699
7700
void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
7701
{
7702
struct rtw89_btc *btc = &rtwdev->btc;
7703
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7704
7705
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
7706
btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
7707
7708
btc->cx.wl.status.map.rf_off = 1;
7709
btc->cx.wl.status.map.busy = 0;
7710
wl->status.map.lps = BTC_LPS_OFF;
7711
7712
_write_scbd(rtwdev, BTC_WSCB_ALL, false);
7713
_run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
7714
7715
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, 0);
7716
7717
btc->cx.wl.status.map.rf_off_pre = btc->cx.wl.status.map.rf_off;
7718
}
7719
7720
static void _set_init_info(struct rtw89_dev *rtwdev)
7721
{
7722
const struct rtw89_chip_info *chip = rtwdev->chip;
7723
struct rtw89_btc *btc = &rtwdev->btc;
7724
const struct rtw89_btc_ver *ver = btc->ver;
7725
struct rtw89_btc_dm *dm = &btc->dm;
7726
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7727
7728
if (ver->fcxinit == 7) {
7729
dm->init_info.init_v7.wl_only = (u8)dm->wl_only;
7730
dm->init_info.init_v7.bt_only = (u8)dm->bt_only;
7731
dm->init_info.init_v7.wl_init_ok = (u8)wl->status.map.init_ok;
7732
dm->init_info.init_v7.cx_other = btc->cx.other.type;
7733
dm->init_info.init_v7.wl_guard_ch = chip->afh_guard_ch;
7734
dm->init_info.init_v7.module = btc->mdinfo.md_v7;
7735
} else {
7736
dm->init_info.init.wl_only = (u8)dm->wl_only;
7737
dm->init_info.init.bt_only = (u8)dm->bt_only;
7738
dm->init_info.init.wl_init_ok = (u8)wl->status.map.init_ok;
7739
dm->init_info.init.dbcc_en = rtwdev->dbcc_en;
7740
dm->init_info.init.cx_other = btc->cx.other.type;
7741
dm->init_info.init.wl_guard_ch = chip->afh_guard_ch;
7742
dm->init_info.init.module = btc->mdinfo.md;
7743
}
7744
}
7745
7746
void rtw89_btc_ntfy_init(struct rtw89_dev *rtwdev, u8 mode)
7747
{
7748
struct rtw89_btc *btc = &rtwdev->btc;
7749
struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
7750
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7751
const struct rtw89_chip_info *chip = rtwdev->chip;
7752
const struct rtw89_btc_ver *ver = btc->ver;
7753
7754
_reset_btc_var(rtwdev, BTC_RESET_ALL);
7755
btc->dm.run_reason = BTC_RSN_NONE;
7756
btc->dm.run_action = BTC_ACT_NONE;
7757
if (ver->fcxctrl == 7)
7758
btc->ctrl.ctrl_v7.igno_bt = true;
7759
else
7760
btc->ctrl.ctrl.igno_bt = true;
7761
7762
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7763
"[BTC], %s(): mode=%d\n", __func__, mode);
7764
7765
wl->coex_mode = mode;
7766
dm->cnt_notify[BTC_NCNT_INIT_COEX]++;
7767
dm->wl_only = mode == BTC_MODE_WL ? 1 : 0;
7768
dm->bt_only = mode == BTC_MODE_BT ? 1 : 0;
7769
wl->status.map.rf_off = mode == BTC_MODE_WLOFF ? 1 : 0;
7770
7771
chip->ops->btc_set_rfe(rtwdev);
7772
chip->ops->btc_init_cfg(rtwdev);
7773
7774
if (!wl->status.map.init_ok) {
7775
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7776
"[BTC], %s(): return for WL init fail!!\n",
7777
__func__);
7778
dm->error.map.init = true;
7779
return;
7780
}
7781
7782
_write_scbd(rtwdev,
7783
BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG, true);
7784
_update_bt_scbd(rtwdev, true);
7785
if (rtw89_mac_get_ctrl_path(rtwdev)) {
7786
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7787
"[BTC], %s(): PTA owner warning!!\n",
7788
__func__);
7789
dm->error.map.pta_owner = true;
7790
}
7791
7792
_set_init_info(rtwdev);
7793
_set_wl_tx_power(rtwdev, RTW89_BTC_WL_DEF_TX_PWR);
7794
btc_fw_set_monreg(rtwdev);
7795
rtw89_btc_fw_set_slots(rtwdev);
7796
_fw_set_drv_info(rtwdev, CXDRVINFO_INIT);
7797
_fw_set_drv_info(rtwdev, CXDRVINFO_CTRL);
7798
7799
_run_coex(rtwdev, BTC_RSN_NTFY_INIT);
7800
}
7801
7802
void rtw89_btc_ntfy_scan_start(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
7803
{
7804
struct rtw89_btc *btc = &rtwdev->btc;
7805
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7806
7807
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7808
"[BTC], %s(): phy_idx=%d, band=%d\n",
7809
__func__, phy_idx, band);
7810
7811
if (phy_idx >= RTW89_PHY_NUM)
7812
return;
7813
7814
btc->dm.cnt_notify[BTC_NCNT_SCAN_START]++;
7815
wl->status.map.scan = true;
7816
wl->scan_info.band[phy_idx] = band;
7817
wl->scan_info.phy_map |= BIT(phy_idx);
7818
_fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
7819
7820
if (rtwdev->dbcc_en) {
7821
wl->dbcc_info.scan_band[phy_idx] = band;
7822
_update_dbcc_band(rtwdev, phy_idx);
7823
_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7824
}
7825
7826
_run_coex(rtwdev, BTC_RSN_NTFY_SCAN_START);
7827
}
7828
7829
void rtw89_btc_ntfy_scan_finish(struct rtw89_dev *rtwdev, u8 phy_idx)
7830
{
7831
struct rtw89_btc *btc = &rtwdev->btc;
7832
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7833
7834
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7835
"[BTC], %s(): phy_idx=%d\n", __func__, phy_idx);
7836
btc->dm.cnt_notify[BTC_NCNT_SCAN_FINISH]++;
7837
7838
wl->status.map.scan = false;
7839
wl->scan_info.phy_map &= ~BIT(phy_idx);
7840
_fw_set_drv_info(rtwdev, CXDRVINFO_SCAN);
7841
7842
if (rtwdev->dbcc_en) {
7843
_update_dbcc_band(rtwdev, phy_idx);
7844
_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7845
}
7846
7847
btc->dm.tdma_instant_excute = 1;
7848
7849
_run_coex(rtwdev, BTC_RSN_NTFY_SCAN_FINISH);
7850
}
7851
7852
void rtw89_btc_ntfy_switch_band(struct rtw89_dev *rtwdev, u8 phy_idx, u8 band)
7853
{
7854
struct rtw89_btc *btc = &rtwdev->btc;
7855
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
7856
7857
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7858
"[BTC], %s(): phy_idx=%d, band=%d\n",
7859
__func__, phy_idx, band);
7860
7861
if (phy_idx >= RTW89_PHY_NUM)
7862
return;
7863
7864
btc->dm.cnt_notify[BTC_NCNT_SWITCH_BAND]++;
7865
7866
if (rtwdev->dbcc_en) {
7867
wl->dbcc_info.scan_band[phy_idx] = band;
7868
_update_dbcc_band(rtwdev, phy_idx);
7869
_fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
7870
}
7871
_run_coex(rtwdev, BTC_RSN_NTFY_SWBAND);
7872
}
7873
7874
void rtw89_btc_ntfy_specific_packet(struct rtw89_dev *rtwdev,
7875
enum btc_pkt_type pkt_type)
7876
{
7877
struct rtw89_btc *btc = &rtwdev->btc;
7878
struct rtw89_btc_cx *cx = &btc->cx;
7879
struct rtw89_btc_wl_info *wl = &cx->wl;
7880
struct rtw89_btc_bt_link_info *b = &cx->bt.link_info;
7881
struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
7882
struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
7883
u32 cnt;
7884
u32 delay = RTW89_COEX_ACT1_WORK_PERIOD;
7885
bool delay_work = false;
7886
7887
switch (pkt_type) {
7888
case PACKET_DHCP:
7889
cnt = ++cx->cnt_wl[BTC_WCNT_DHCP];
7890
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7891
"[BTC], %s(): DHCP cnt=%d\n", __func__, cnt);
7892
wl->status.map.connecting = true;
7893
delay_work = true;
7894
break;
7895
case PACKET_EAPOL:
7896
cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
7897
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7898
"[BTC], %s(): EAPOL cnt=%d\n", __func__, cnt);
7899
wl->status.map._4way = true;
7900
delay_work = true;
7901
if (hfp->exist || hid->exist)
7902
delay /= 2;
7903
break;
7904
case PACKET_EAPOL_END:
7905
cnt = ++cx->cnt_wl[BTC_WCNT_EAPOL];
7906
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7907
"[BTC], %s(): EAPOL_End cnt=%d\n",
7908
__func__, cnt);
7909
wl->status.map._4way = false;
7910
wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work);
7911
break;
7912
case PACKET_ARP:
7913
cnt = ++cx->cnt_wl[BTC_WCNT_ARP];
7914
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7915
"[BTC], %s(): ARP cnt=%d\n", __func__, cnt);
7916
return;
7917
case PACKET_ICMP:
7918
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7919
"[BTC], %s(): ICMP pkt\n", __func__);
7920
return;
7921
default:
7922
rtw89_debug(rtwdev, RTW89_DBG_BTC,
7923
"[BTC], %s(): unknown packet type %d\n",
7924
__func__, pkt_type);
7925
return;
7926
}
7927
7928
if (delay_work) {
7929
wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_act1_work);
7930
wiphy_delayed_work_queue(rtwdev->hw->wiphy,
7931
&rtwdev->coex_act1_work, delay);
7932
}
7933
7934
btc->dm.cnt_notify[BTC_NCNT_SPECIAL_PACKET]++;
7935
_run_coex(rtwdev, BTC_RSN_NTFY_SPECIFIC_PACKET);
7936
}
7937
7938
void rtw89_btc_ntfy_eapol_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7939
{
7940
struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7941
btc.eapol_notify_work);
7942
7943
lockdep_assert_wiphy(wiphy);
7944
7945
rtw89_leave_ps_mode(rtwdev);
7946
rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_EAPOL);
7947
}
7948
7949
void rtw89_btc_ntfy_arp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7950
{
7951
struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7952
btc.arp_notify_work);
7953
7954
lockdep_assert_wiphy(wiphy);
7955
7956
rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ARP);
7957
}
7958
7959
void rtw89_btc_ntfy_dhcp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7960
{
7961
struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7962
btc.dhcp_notify_work);
7963
7964
lockdep_assert_wiphy(wiphy);
7965
7966
rtw89_leave_ps_mode(rtwdev);
7967
rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_DHCP);
7968
}
7969
7970
void rtw89_btc_ntfy_icmp_packet_work(struct wiphy *wiphy, struct wiphy_work *work)
7971
{
7972
struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
7973
btc.icmp_notify_work);
7974
7975
lockdep_assert_wiphy(wiphy);
7976
7977
rtw89_leave_ps_mode(rtwdev);
7978
rtw89_btc_ntfy_specific_packet(rtwdev, PACKET_ICMP);
7979
}
7980
7981
static u8 _update_bt_rssi_level(struct rtw89_dev *rtwdev, u8 rssi)
7982
{
7983
const struct rtw89_chip_info *chip = rtwdev->chip;
7984
struct rtw89_btc *btc = &rtwdev->btc;
7985
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
7986
u8 *rssi_st, rssi_th, rssi_level = 0;
7987
u8 i;
7988
7989
/* for rssi locate in which {40, 36, 31, 28}
7990
* if rssi >= 40% (-60dBm) --> rssi_level = 4
7991
* if 36% <= rssi < 40% --> rssi_level = 3
7992
* if 31% <= rssi < 36% --> rssi_level = 2
7993
* if 28% <= rssi < 31% --> rssi_level = 1
7994
* if rssi < 28% --> rssi_level = 0
7995
*/
7996
7997
/* check if rssi across bt_rssi_thres boundary */
7998
for (i = 0; i < BTC_BT_RSSI_THMAX; i++) {
7999
rssi_th = chip->bt_rssi_thres[i];
8000
rssi_st = &bt->link_info.rssi_state[i];
8001
8002
*rssi_st = _update_rssi_state(rtwdev, *rssi_st, rssi, rssi_th);
8003
8004
if (BTC_RSSI_HIGH(*rssi_st)) {
8005
rssi_level = BTC_BT_RSSI_THMAX - i;
8006
break;
8007
}
8008
}
8009
return rssi_level;
8010
}
8011
8012
static void _update_zb_coex_tbl(struct rtw89_dev *rtwdev)
8013
{
8014
u8 mode = rtwdev->btc.cx.wl.role_info.link_mode;
8015
u32 zb_tbl0 = 0xda5a5a5a, zb_tbl1 = 0xda5a5a5a;
8016
8017
if (mode == BTC_WLINK_5G || rtwdev->btc.dm.freerun) {
8018
zb_tbl0 = 0xffffffff;
8019
zb_tbl1 = 0xffffffff;
8020
} else if (mode == BTC_WLINK_25G_MCC) {
8021
zb_tbl0 = 0xffffffff; /* for E5G slot */
8022
zb_tbl1 = 0xda5a5a5a; /* for E2G slot */
8023
}
8024
rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_0, zb_tbl0);
8025
rtw89_write32(rtwdev, R_BTC_ZB_COEX_TBL_1, zb_tbl1);
8026
}
8027
8028
#define BT_PROFILE_PROTOCOL_MASK GENMASK(7, 4)
8029
8030
static void _update_bt_info(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
8031
{
8032
const struct rtw89_chip_info *chip = rtwdev->chip;
8033
struct rtw89_btc *btc = &rtwdev->btc;
8034
struct rtw89_btc_cx *cx = &btc->cx;
8035
struct rtw89_btc_bt_info *bt = &cx->bt;
8036
struct rtw89_btc_bt_link_info *b = &bt->link_info;
8037
struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
8038
struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
8039
struct rtw89_btc_bt_a2dp_desc *a2dp = &b->a2dp_desc;
8040
struct rtw89_btc_bt_pan_desc *pan = &b->pan_desc;
8041
union btc_btinfo btinfo;
8042
8043
if (buf[BTC_BTINFO_L1] != 6)
8044
return;
8045
8046
if (!memcmp(bt->raw_info, buf, BTC_BTINFO_MAX)) {
8047
rtw89_debug(rtwdev, RTW89_DBG_BTC,
8048
"[BTC], %s(): return by bt-info duplicate!!\n",
8049
__func__);
8050
cx->cnt_bt[BTC_BCNT_INFOSAME]++;
8051
return;
8052
}
8053
8054
memcpy(bt->raw_info, buf, BTC_BTINFO_MAX);
8055
8056
rtw89_debug(rtwdev, RTW89_DBG_BTC,
8057
"[BTC], %s(): bt_info[2]=0x%02x\n",
8058
__func__, bt->raw_info[2]);
8059
8060
b->profile_cnt.last = b->profile_cnt.now;
8061
b->profile_cnt.now = 0;
8062
hid->type = 0;
8063
8064
/* parse raw info low-Byte2 */
8065
btinfo.val = bt->raw_info[BTC_BTINFO_L2];
8066
b->status.map.connect = btinfo.lb2.connect;
8067
b->status.map.sco_busy = btinfo.lb2.sco_busy;
8068
b->status.map.acl_busy = btinfo.lb2.acl_busy;
8069
b->status.map.inq_pag = btinfo.lb2.inq_pag;
8070
bt->inq_pag.now = btinfo.lb2.inq_pag;
8071
cx->cnt_bt[BTC_BCNT_INQPAG] += !!(bt->inq_pag.now && !bt->inq_pag.last);
8072
8073
hfp->exist = btinfo.lb2.hfp;
8074
b->profile_cnt.now += (u8)hfp->exist;
8075
hid->exist = btinfo.lb2.hid;
8076
b->profile_cnt.now += (u8)hid->exist;
8077
a2dp->exist = btinfo.lb2.a2dp;
8078
b->profile_cnt.now += (u8)a2dp->exist;
8079
pan->exist = btinfo.lb2.pan;
8080
b->profile_cnt.now += (u8)pan->exist;
8081
btc->dm.trx_info.bt_profile = u32_get_bits(btinfo.val, BT_PROFILE_PROTOCOL_MASK);
8082
8083
/* parse raw info low-Byte3 */
8084
btinfo.val = bt->raw_info[BTC_BTINFO_L3];
8085
if (btinfo.lb3.retry != 0)
8086
cx->cnt_bt[BTC_BCNT_RETRY]++;
8087
b->cqddr = btinfo.lb3.cqddr;
8088
cx->cnt_bt[BTC_BCNT_INQ] += !!(btinfo.lb3.inq && !bt->inq);
8089
bt->inq = btinfo.lb3.inq;
8090
cx->cnt_bt[BTC_BCNT_PAGE] += !!(btinfo.lb3.pag && !bt->pag);
8091
bt->pag = btinfo.lb3.pag;
8092
8093
b->status.map.mesh_busy = btinfo.lb3.mesh_busy;
8094
/* parse raw info high-Byte0 */
8095
btinfo.val = bt->raw_info[BTC_BTINFO_H0];
8096
/* raw val is dBm unit, translate from -100~ 0dBm to 0~100%*/
8097
b->rssi = chip->ops->btc_get_bt_rssi(rtwdev, btinfo.hb0.rssi);
8098
bt->rssi_level = _update_bt_rssi_level(rtwdev, b->rssi);
8099
btc->dm.trx_info.bt_rssi = bt->rssi_level;
8100
8101
/* parse raw info high-Byte1 */
8102
btinfo.val = bt->raw_info[BTC_BTINFO_H1];
8103
b->status.map.ble_connect = btinfo.hb1.ble_connect;
8104
if (btinfo.hb1.ble_connect) {
8105
if (hid->exist)
8106
hid->type |= BTC_HID_BLE;
8107
else if (btinfo.hb1.voice)
8108
hid->type |= BTC_HID_RCU_VOICE;
8109
else
8110
hid->type |= BTC_HID_RCU;
8111
}
8112
8113
cx->cnt_bt[BTC_BCNT_REINIT] += !!(btinfo.hb1.reinit && !bt->reinit);
8114
bt->reinit = btinfo.hb1.reinit;
8115
cx->cnt_bt[BTC_BCNT_RELINK] += !!(btinfo.hb1.relink && !b->relink.now);
8116
b->relink.now = btinfo.hb1.relink;
8117
cx->cnt_bt[BTC_BCNT_IGNOWL] += !!(btinfo.hb1.igno_wl && !bt->igno_wl);
8118
bt->igno_wl = btinfo.hb1.igno_wl;
8119
8120
if (bt->igno_wl && !cx->wl.status.map.rf_off)
8121
_set_bt_ignore_wlan_act(rtwdev, false);
8122
8123
bt->ble_scan_en = btinfo.hb1.ble_scan;
8124
8125
cx->cnt_bt[BTC_BCNT_ROLESW] += !!(btinfo.hb1.role_sw && !b->role_sw);
8126
b->role_sw = btinfo.hb1.role_sw;
8127
8128
b->multi_link.now = btinfo.hb1.multi_link;
8129
8130
/* parse raw info high-Byte2 */
8131
btinfo.val = bt->raw_info[BTC_BTINFO_H2];
8132
pan->active = !!btinfo.hb2.pan_active;
8133
8134
cx->cnt_bt[BTC_BCNT_AFH] += !!(btinfo.hb2.afh_update && !b->afh_update);
8135
b->afh_update = btinfo.hb2.afh_update;
8136
a2dp->active = btinfo.hb2.a2dp_active;
8137
b->slave_role = btinfo.hb2.slave;
8138
hid->slot_info = btinfo.hb2.hid_slot;
8139
hid->pair_cnt = btinfo.hb2.hid_cnt;
8140
if (!b->status.map.ble_connect || hid->pair_cnt > 1)
8141
hid->type |= (hid->slot_info == BTC_HID_218 ?
8142
BTC_HID_218 : BTC_HID_418);
8143
/* parse raw info high-Byte3 */
8144
btinfo.val = bt->raw_info[BTC_BTINFO_H3];
8145
a2dp->bitpool = btinfo.hb3.a2dp_bitpool;
8146
8147
if (b->tx_3m != (u32)btinfo.hb3.tx_3m)
8148
cx->cnt_bt[BTC_BCNT_RATECHG]++;
8149
b->tx_3m = (u32)btinfo.hb3.tx_3m;
8150
8151
a2dp->sink = btinfo.hb3.a2dp_sink;
8152
8153
if (!a2dp->exist_last && a2dp->exist) {
8154
a2dp->vendor_id = 0;
8155
a2dp->flush_time = 0;
8156
a2dp->play_latency = 1;
8157
wiphy_delayed_work_queue(rtwdev->hw->wiphy,
8158
&rtwdev->coex_bt_devinfo_work,
8159
RTW89_COEX_BT_DEVINFO_WORK_PERIOD);
8160
}
8161
8162
_run_coex(rtwdev, BTC_RSN_UPDATE_BT_INFO);
8163
}
8164
8165
void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev,
8166
struct rtw89_vif_link *rtwvif_link,
8167
struct rtw89_sta_link *rtwsta_link,
8168
enum btc_role_state state)
8169
{
8170
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
8171
rtwvif_link->chanctx_idx);
8172
struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
8173
struct ieee80211_bss_conf *bss_conf;
8174
struct ieee80211_link_sta *link_sta;
8175
struct rtw89_btc *btc = &rtwdev->btc;
8176
const struct rtw89_btc_ver *ver = btc->ver;
8177
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8178
struct rtw89_btc_wl_link_info r = {0};
8179
struct rtw89_btc_wl_link_info *wlinfo = NULL;
8180
u8 mode = 0, rlink_id, link_mode_ori, pta_req_mac_ori, wa_type;
8181
8182
rcu_read_lock();
8183
8184
bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, false);
8185
8186
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], state=%d\n", state);
8187
rtw89_debug(rtwdev, RTW89_DBG_BTC,
8188
"[BTC], role is STA=%d\n",
8189
vif->type == NL80211_IFTYPE_STATION);
8190
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif_link->port);
8191
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
8192
chan->band_type, chan->channel, chan->band_width);
8193
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
8194
state == BTC_ROLE_MSTS_STA_CONN_END);
8195
rtw89_debug(rtwdev, RTW89_DBG_BTC,
8196
"[BTC], bcn_period=%d dtim_period=%d\n",
8197
bss_conf->beacon_int, bss_conf->dtim_period);
8198
8199
if (rtwsta_link) {
8200
link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, false);
8201
8202
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], STA mac_id=%d\n",
8203
rtwsta_link->mac_id);
8204
8205
rtw89_debug(rtwdev, RTW89_DBG_BTC,
8206
"[BTC], STA support HE=%d VHT=%d HT=%d\n",
8207
link_sta->he_cap.has_he,
8208
link_sta->vht_cap.vht_supported,
8209
link_sta->ht_cap.ht_supported);
8210
if (link_sta->he_cap.has_he)
8211
mode |= BIT(BTC_WL_MODE_HE);
8212
if (link_sta->vht_cap.vht_supported)
8213
mode |= BIT(BTC_WL_MODE_VHT);
8214
if (link_sta->ht_cap.ht_supported)
8215
mode |= BIT(BTC_WL_MODE_HT);
8216
8217
r.mode = mode;
8218
}
8219
8220
if (rtwvif_link->wifi_role >= RTW89_WIFI_ROLE_MLME_MAX) {
8221
rcu_read_unlock();
8222
return;
8223
}
8224
8225
rtw89_debug(rtwdev, RTW89_DBG_BTC,
8226
"[BTC], wifi_role=%d\n", rtwvif_link->wifi_role);
8227
8228
r.role = rtwvif_link->wifi_role;
8229
r.phy = rtwvif_link->phy_idx;
8230
r.pid = rtwvif_link->port;
8231
r.active = true;
8232
r.connected = MLME_LINKED;
8233
r.bcn_period = bss_conf->beacon_int;
8234
r.dtim_period = bss_conf->dtim_period;
8235
r.band = chan->band_type;
8236
r.ch = chan->channel;
8237
r.bw = chan->band_width;
8238
r.chdef.band = chan->band_type;
8239
r.chdef.center_ch = chan->channel;
8240
r.chdef.bw = chan->band_width;
8241
r.chdef.chan = chan->primary_channel;
8242
ether_addr_copy(r.mac_addr, rtwvif_link->mac_addr);
8243
8244
rcu_read_unlock();
8245
8246
if (rtwsta_link && vif->type == NL80211_IFTYPE_STATION)
8247
r.mac_id = rtwsta_link->mac_id;
8248
8249
btc->dm.cnt_notify[BTC_NCNT_ROLE_INFO]++;
8250
8251
wlinfo = &wl->link_info[r.pid];
8252
8253
if (ver->fwlrole == 0) {
8254
*wlinfo = r;
8255
_update_wl_info(rtwdev);
8256
} else if (ver->fwlrole == 1) {
8257
*wlinfo = r;
8258
_update_wl_info_v1(rtwdev);
8259
} else if (ver->fwlrole == 2) {
8260
*wlinfo = r;
8261
_update_wl_info_v2(rtwdev);
8262
} else if (ver->fwlrole == 7) {
8263
*wlinfo = r;
8264
_update_wl_info_v7(rtwdev, r.pid);
8265
} else if (ver->fwlrole == 8) {
8266
rlink_id = rtwvif_link->mac_idx;
8267
wlinfo = &wl->rlink_info[r.pid][rlink_id];
8268
*wlinfo = r;
8269
link_mode_ori = wl->role_info_v8.link_mode;
8270
pta_req_mac_ori = wl->pta_req_mac;
8271
_update_wl_info_v8(rtwdev, r.pid, rlink_id, state);
8272
8273
if (wl->role_info_v8.link_mode != link_mode_ori) {
8274
wl->role_info_v8.link_mode_chg = 1;
8275
if (ver->fcxinit == 7)
8276
wa_type = btc->mdinfo.md_v7.wa_type;
8277
else
8278
wa_type = btc->mdinfo.md.wa_type;
8279
8280
if (wa_type & BTC_WA_HFP_ZB)
8281
_update_zb_coex_tbl(rtwdev);
8282
}
8283
8284
if (wl->pta_req_mac != pta_req_mac_ori)
8285
wl->pta_reg_mac_chg = 1;
8286
}
8287
8288
if (wlinfo->role == RTW89_WIFI_ROLE_STATION &&
8289
wlinfo->connected == MLME_NO_LINK)
8290
btc->dm.leak_ap = 0;
8291
8292
if (state == BTC_ROLE_MSTS_STA_CONN_START)
8293
wl->status.map.connecting = 1;
8294
else
8295
wl->status.map.connecting = 0;
8296
8297
if (state == BTC_ROLE_MSTS_STA_DIS_CONN ||
8298
state == BTC_ROLE_MSTS_STA_CONN_END)
8299
wl->status.map._4way = false;
8300
8301
_run_coex(rtwdev, BTC_RSN_NTFY_ROLE_INFO);
8302
}
8303
8304
void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_state)
8305
{
8306
const struct rtw89_chip_info *chip = rtwdev->chip;
8307
struct rtw89_btc *btc = &rtwdev->btc;
8308
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8309
u32 val;
8310
8311
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
8312
__func__, rf_state);
8313
btc->dm.cnt_notify[BTC_NCNT_RADIO_STATE]++;
8314
8315
switch (rf_state) {
8316
case BTC_RFCTRL_WL_OFF:
8317
wl->status.map.rf_off = 1;
8318
wl->status.map.lps = BTC_LPS_OFF;
8319
wl->status.map.busy = 0;
8320
break;
8321
case BTC_RFCTRL_FW_CTRL:
8322
wl->status.map.rf_off = 0;
8323
wl->status.map.lps = BTC_LPS_RF_OFF;
8324
wl->status.map.busy = 0;
8325
break;
8326
case BTC_RFCTRL_LPS_WL_ON: /* LPS-Protocol (RFon) */
8327
wl->status.map.rf_off = 0;
8328
wl->status.map.lps = BTC_LPS_RF_ON;
8329
wl->status.map.busy = 0;
8330
break;
8331
case BTC_RFCTRL_WL_ON:
8332
default:
8333
wl->status.map.rf_off = 0;
8334
wl->status.map.lps = BTC_LPS_OFF;
8335
break;
8336
}
8337
8338
if (rf_state == BTC_RFCTRL_WL_ON) {
8339
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_MREG, true);
8340
val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG;
8341
_write_scbd(rtwdev, val, true);
8342
_update_bt_scbd(rtwdev, true);
8343
chip->ops->btc_init_cfg(rtwdev);
8344
} else {
8345
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false);
8346
if (rf_state == BTC_RFCTRL_FW_CTRL)
8347
_write_scbd(rtwdev, BTC_WSCB_ACTIVE, false);
8348
else if (rf_state == BTC_RFCTRL_WL_OFF)
8349
_write_scbd(rtwdev, BTC_WSCB_ALL, false);
8350
else
8351
_write_scbd(rtwdev, BTC_WSCB_ACTIVE, false);
8352
8353
if (rf_state == BTC_RFCTRL_LPS_WL_ON &&
8354
wl->status.map.lps_pre != BTC_LPS_OFF)
8355
_update_bt_scbd(rtwdev, true);
8356
}
8357
8358
btc->dm.cnt_dm[BTC_DCNT_BTCNT_HANG] = 0;
8359
btc->dm.tdma_instant_excute = 1;
8360
8361
_run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
8362
wl->status.map.rf_off_pre = wl->status.map.rf_off;
8363
wl->status.map.lps_pre = wl->status.map.lps;
8364
}
8365
8366
static bool _ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_path,
8367
enum btc_wl_rfk_type type,
8368
enum btc_wl_rfk_state state)
8369
{
8370
struct rtw89_btc *btc = &rtwdev->btc;
8371
struct rtw89_btc_cx *cx = &btc->cx;
8372
struct rtw89_btc_wl_info *wl = &cx->wl;
8373
bool result = BTC_WRFK_REJECT;
8374
8375
wl->rfk_info.type = type;
8376
wl->rfk_info.path_map = FIELD_GET(BTC_RFK_PATH_MAP, phy_path);
8377
wl->rfk_info.phy_map = FIELD_GET(BTC_RFK_PHY_MAP, phy_path);
8378
wl->rfk_info.band = FIELD_GET(BTC_RFK_BAND_MAP, phy_path);
8379
8380
rtw89_debug(rtwdev, RTW89_DBG_BTC,
8381
"[BTC], %s()_start: phy=0x%x, path=0x%x, type=%d, state=%d\n",
8382
__func__, wl->rfk_info.phy_map, wl->rfk_info.path_map,
8383
type, state);
8384
8385
switch (state) {
8386
case BTC_WRFK_START:
8387
result = _chk_wl_rfk_request(rtwdev);
8388
wl->rfk_info.state = result ? BTC_WRFK_START : BTC_WRFK_STOP;
8389
8390
_write_scbd(rtwdev, BTC_WSCB_WLRFK, result);
8391
8392
btc->dm.cnt_notify[BTC_NCNT_WL_RFK]++;
8393
break;
8394
case BTC_WRFK_ONESHOT_START:
8395
case BTC_WRFK_ONESHOT_STOP:
8396
if (wl->rfk_info.state == BTC_WRFK_STOP) {
8397
result = BTC_WRFK_REJECT;
8398
} else {
8399
result = BTC_WRFK_ALLOW;
8400
wl->rfk_info.state = state;
8401
}
8402
break;
8403
case BTC_WRFK_STOP:
8404
result = BTC_WRFK_ALLOW;
8405
wl->rfk_info.state = BTC_WRFK_STOP;
8406
8407
_write_scbd(rtwdev, BTC_WSCB_WLRFK, false);
8408
wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->coex_rfk_chk_work);
8409
break;
8410
default:
8411
rtw89_debug(rtwdev, RTW89_DBG_BTC,
8412
"[BTC], %s() warning state=%d\n", __func__, state);
8413
break;
8414
}
8415
8416
if (result == BTC_WRFK_ALLOW) {
8417
if (wl->rfk_info.state == BTC_WRFK_START ||
8418
wl->rfk_info.state == BTC_WRFK_STOP)
8419
_run_coex(rtwdev, BTC_RSN_NTFY_WL_RFK);
8420
8421
if (wl->rfk_info.state == BTC_WRFK_START)
8422
wiphy_delayed_work_queue(rtwdev->hw->wiphy,
8423
&rtwdev->coex_rfk_chk_work,
8424
RTW89_COEX_RFK_CHK_WORK_PERIOD);
8425
}
8426
8427
rtw89_debug(rtwdev, RTW89_DBG_BTC,
8428
"[BTC], %s()_finish: rfk_cnt=%d, result=%d\n",
8429
__func__, btc->dm.cnt_notify[BTC_NCNT_WL_RFK], result);
8430
8431
return result == BTC_WRFK_ALLOW;
8432
}
8433
8434
void rtw89_btc_ntfy_wl_rfk(struct rtw89_dev *rtwdev, u8 phy_map,
8435
enum btc_wl_rfk_type type,
8436
enum btc_wl_rfk_state state)
8437
{
8438
u8 band;
8439
bool allow;
8440
int ret;
8441
8442
lockdep_assert_wiphy(rtwdev->hw->wiphy);
8443
8444
band = FIELD_GET(BTC_RFK_BAND_MAP, phy_map);
8445
8446
rtw89_debug(rtwdev, RTW89_DBG_RFK,
8447
"[RFK] RFK notify (%s / PHY%u / K_type = %u / path_idx = %lu / process = %s)\n",
8448
band == RTW89_BAND_2G ? "2G" :
8449
band == RTW89_BAND_5G ? "5G" : "6G",
8450
!!(FIELD_GET(BTC_RFK_PHY_MAP, phy_map) & BIT(RTW89_PHY_1)),
8451
type,
8452
FIELD_GET(BTC_RFK_PATH_MAP, phy_map),
8453
state == BTC_WRFK_STOP ? "RFK_STOP" :
8454
state == BTC_WRFK_START ? "RFK_START" :
8455
state == BTC_WRFK_ONESHOT_START ? "ONE-SHOT_START" :
8456
"ONE-SHOT_STOP");
8457
8458
if (state != BTC_WRFK_START || rtwdev->is_bt_iqk_timeout) {
8459
_ntfy_wl_rfk(rtwdev, phy_map, type, state);
8460
return;
8461
}
8462
8463
ret = read_poll_timeout(_ntfy_wl_rfk, allow, allow, 40, 100000, false,
8464
rtwdev, phy_map, type, state);
8465
if (ret) {
8466
rtw89_warn(rtwdev, "RFK notify timeout\n");
8467
rtwdev->is_bt_iqk_timeout = true;
8468
}
8469
}
8470
EXPORT_SYMBOL(rtw89_btc_ntfy_wl_rfk);
8471
8472
struct rtw89_btc_wl_sta_iter_data {
8473
struct rtw89_dev *rtwdev;
8474
u8 busy_all;
8475
u8 dir_all;
8476
u8 rssi_map_all;
8477
bool is_sta_change;
8478
bool is_traffic_change;
8479
};
8480
8481
static
8482
void __rtw89_btc_ntfy_wl_sta_iter(struct rtw89_vif_link *rtwvif_link,
8483
struct rtw89_sta_link *rtwsta_link,
8484
struct rtw89_btc_wl_sta_iter_data *iter_data)
8485
{
8486
struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
8487
struct rtw89_dev *rtwdev = iter_data->rtwdev;
8488
struct rtw89_btc *btc = &rtwdev->btc;
8489
struct rtw89_btc_dm *dm = &btc->dm;
8490
const struct rtw89_btc_ver *ver = btc->ver;
8491
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8492
struct rtw89_btc_wl_link_info *link_info = NULL;
8493
struct rtw89_traffic_stats *link_info_t = NULL;
8494
struct rtw89_traffic_stats *stats = &rtwvif->stats;
8495
const struct rtw89_chip_info *chip = rtwdev->chip;
8496
struct rtw89_btc_wl_role_info *r;
8497
struct rtw89_btc_wl_role_info_v1 *r1;
8498
u32 last_tx_rate, last_rx_rate;
8499
u16 last_tx_lvl, last_rx_lvl;
8500
u8 port = rtwvif_link->port;
8501
u8 rssi;
8502
u8 busy = 0;
8503
u8 dir = 0;
8504
u8 rssi_map = 0;
8505
u8 i = 0;
8506
bool is_sta_change = false, is_traffic_change = false;
8507
8508
rssi = ewma_rssi_read(&rtwsta_link->avg_rssi) >> RSSI_FACTOR;
8509
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], rssi=%d\n", rssi);
8510
8511
if (btc->ver->fwlrole != 8)
8512
link_info = &wl->link_info[port];
8513
else
8514
link_info = &wl->rlink_info[port][rtwvif_link->mac_idx];
8515
8516
link_info->stat.traffic = *stats;
8517
link_info_t = &link_info->stat.traffic;
8518
8519
if (link_info->connected == MLME_NO_LINK) {
8520
link_info->rx_rate_drop_cnt = 0;
8521
return;
8522
}
8523
8524
link_info->stat.rssi = rssi;
8525
for (i = 0; i < BTC_WL_RSSI_THMAX; i++) {
8526
link_info->rssi_state[i] =
8527
_update_rssi_state(rtwdev,
8528
link_info->rssi_state[i],
8529
link_info->stat.rssi,
8530
chip->wl_rssi_thres[i]);
8531
if (BTC_RSSI_LOW(link_info->rssi_state[i]))
8532
rssi_map |= BIT(i);
8533
8534
if (btc->ant_type == BTC_ANT_DEDICATED &&
8535
BTC_RSSI_CHANGE(link_info->rssi_state[i]))
8536
is_sta_change = true;
8537
}
8538
iter_data->rssi_map_all |= rssi_map;
8539
8540
last_tx_rate = link_info_t->tx_rate;
8541
last_rx_rate = link_info_t->rx_rate;
8542
last_tx_lvl = (u16)link_info_t->tx_tfc_lv;
8543
last_rx_lvl = (u16)link_info_t->rx_tfc_lv;
8544
8545
if (stats->tx_tfc_lv != RTW89_TFC_IDLE ||
8546
stats->rx_tfc_lv != RTW89_TFC_IDLE)
8547
busy = 1;
8548
8549
if (stats->tx_tfc_lv > stats->rx_tfc_lv)
8550
dir = RTW89_TFC_UL;
8551
else
8552
dir = RTW89_TFC_DL;
8553
8554
link_info = &wl->link_info[port];
8555
if (link_info->busy != busy || link_info->dir != dir) {
8556
is_sta_change = true;
8557
link_info->busy = busy;
8558
link_info->dir = dir;
8559
}
8560
8561
iter_data->busy_all |= busy;
8562
iter_data->dir_all |= BIT(dir);
8563
8564
if (rtwsta_link->rx_hw_rate <= RTW89_HW_RATE_CCK2 &&
8565
last_rx_rate > RTW89_HW_RATE_CCK2 &&
8566
link_info_t->rx_tfc_lv > RTW89_TFC_IDLE)
8567
link_info->rx_rate_drop_cnt++;
8568
8569
if (last_tx_rate != rtwsta_link->ra_report.hw_rate ||
8570
last_rx_rate != rtwsta_link->rx_hw_rate ||
8571
last_tx_lvl != link_info_t->tx_tfc_lv ||
8572
last_rx_lvl != link_info_t->rx_tfc_lv)
8573
is_traffic_change = true;
8574
8575
link_info_t->tx_rate = rtwsta_link->ra_report.hw_rate;
8576
link_info_t->rx_rate = rtwsta_link->rx_hw_rate;
8577
8578
if (link_info->role == RTW89_WIFI_ROLE_STATION ||
8579
link_info->role == RTW89_WIFI_ROLE_P2P_CLIENT) {
8580
dm->trx_info.tx_rate = link_info_t->tx_rate;
8581
dm->trx_info.rx_rate = link_info_t->rx_rate;
8582
}
8583
8584
if (ver->fwlrole == 0) {
8585
r = &wl->role_info;
8586
r->active_role[port].tx_lvl = stats->tx_tfc_lv;
8587
r->active_role[port].rx_lvl = stats->rx_tfc_lv;
8588
r->active_role[port].tx_rate = rtwsta_link->ra_report.hw_rate;
8589
r->active_role[port].rx_rate = rtwsta_link->rx_hw_rate;
8590
} else if (ver->fwlrole == 1) {
8591
r1 = &wl->role_info_v1;
8592
r1->active_role_v1[port].tx_lvl = stats->tx_tfc_lv;
8593
r1->active_role_v1[port].rx_lvl = stats->rx_tfc_lv;
8594
r1->active_role_v1[port].tx_rate = rtwsta_link->ra_report.hw_rate;
8595
r1->active_role_v1[port].rx_rate = rtwsta_link->rx_hw_rate;
8596
}
8597
8598
dm->trx_info.tx_lvl = stats->tx_tfc_lv;
8599
dm->trx_info.rx_lvl = stats->rx_tfc_lv;
8600
dm->trx_info.tx_rate = rtwsta_link->ra_report.hw_rate;
8601
dm->trx_info.rx_rate = rtwsta_link->rx_hw_rate;
8602
dm->trx_info.tx_tp = link_info_t->tx_throughput;
8603
dm->trx_info.rx_tp = link_info_t->rx_throughput;
8604
8605
/* Trigger coex-run if 0x10980 reg-value is diff with coex setup */
8606
if ((dm->wl_btg_rx_rb != dm->wl_btg_rx &&
8607
dm->wl_btg_rx_rb != BTC_BTGCTRL_BB_GNT_NOTFOUND) ||
8608
(dm->wl_pre_agc_rb != dm->wl_pre_agc &&
8609
dm->wl_pre_agc_rb != BTC_PREAGC_NOTFOUND))
8610
iter_data->is_sta_change = true;
8611
8612
if (is_sta_change)
8613
iter_data->is_sta_change = true;
8614
8615
if (is_traffic_change)
8616
iter_data->is_traffic_change = true;
8617
}
8618
8619
static void rtw89_btc_ntfy_wl_sta_iter(void *data, struct ieee80211_sta *sta)
8620
{
8621
struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
8622
struct rtw89_btc_wl_sta_iter_data *iter_data =
8623
(struct rtw89_btc_wl_sta_iter_data *)data;
8624
struct rtw89_vif_link *rtwvif_link;
8625
struct rtw89_sta_link *rtwsta_link;
8626
unsigned int link_id;
8627
8628
rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
8629
rtwvif_link = rtwsta_link->rtwvif_link;
8630
__rtw89_btc_ntfy_wl_sta_iter(rtwvif_link, rtwsta_link, iter_data);
8631
}
8632
}
8633
8634
#define BTC_NHM_CHK_INTVL 20
8635
8636
void rtw89_btc_ntfy_wl_sta(struct rtw89_dev *rtwdev)
8637
{
8638
struct rtw89_btc *btc = &rtwdev->btc;
8639
struct rtw89_btc_dm *dm = &btc->dm;
8640
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8641
struct rtw89_btc_wl_sta_iter_data data = {.rtwdev = rtwdev};
8642
u8 i;
8643
8644
ieee80211_iterate_stations_atomic(rtwdev->hw,
8645
rtw89_btc_ntfy_wl_sta_iter,
8646
&data);
8647
8648
wl->rssi_level = 0;
8649
btc->dm.cnt_notify[BTC_NCNT_WL_STA]++;
8650
for (i = BTC_WL_RSSI_THMAX; i > 0; i--) {
8651
/* set RSSI level 4 ~ 0 if rssi bit map match */
8652
if (data.rssi_map_all & BIT(i - 1)) {
8653
wl->rssi_level = i;
8654
break;
8655
}
8656
}
8657
8658
if (dm->trx_info.wl_rssi != wl->rssi_level)
8659
dm->trx_info.wl_rssi = wl->rssi_level;
8660
8661
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): busy=%d\n",
8662
__func__, !!wl->status.map.busy);
8663
8664
_write_scbd(rtwdev, BTC_WSCB_WLBUSY, (!!wl->status.map.busy));
8665
8666
if (data.is_traffic_change)
8667
_fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
8668
if (data.is_sta_change) {
8669
wl->status.map.busy = data.busy_all;
8670
wl->status.map.traffic_dir = data.dir_all;
8671
_run_coex(rtwdev, BTC_RSN_NTFY_WL_STA);
8672
} else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] >=
8673
btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] + BTC_NHM_CHK_INTVL) {
8674
btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
8675
btc->dm.cnt_notify[BTC_NCNT_WL_STA];
8676
} else if (btc->dm.cnt_notify[BTC_NCNT_WL_STA] <
8677
btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST]) {
8678
btc->dm.cnt_dm[BTC_DCNT_WL_STA_LAST] =
8679
btc->dm.cnt_notify[BTC_NCNT_WL_STA];
8680
}
8681
}
8682
8683
static u8 rtw89_btc_c2h_get_index_by_ver(struct rtw89_dev *rtwdev, u8 func)
8684
{
8685
struct rtw89_btc *btc = &rtwdev->btc;
8686
const struct rtw89_btc_ver *ver = btc->ver;
8687
8688
switch (func) {
8689
case BTF_EVNT_RPT:
8690
case BTF_EVNT_BT_INFO:
8691
case BTF_EVNT_BT_SCBD:
8692
case BTF_EVNT_BT_REG:
8693
case BTF_EVNT_CX_RUNINFO:
8694
case BTF_EVNT_BT_PSD:
8695
return func;
8696
case BTF_EVNT_BT_DEV_INFO:
8697
if (ver->fwc2hfunc == 0)
8698
return BTF_EVNT_BUF_OVERFLOW;
8699
else
8700
return BTF_EVNT_BT_DEV_INFO;
8701
case BTF_EVNT_BT_LEAUDIO_INFO:
8702
if (ver->fwc2hfunc == 0)
8703
return BTF_EVNT_C2H_LOOPBACK;
8704
else if (ver->fwc2hfunc == 1)
8705
return BTF_EVNT_BUF_OVERFLOW;
8706
else if (ver->fwc2hfunc == 2)
8707
return func;
8708
else if (ver->fwc2hfunc == 3)
8709
return BTF_EVNT_BUF_OVERFLOW;
8710
else
8711
return BTF_EVNT_MAX;
8712
case BTF_EVNT_BUF_OVERFLOW:
8713
if (ver->fwc2hfunc == 0)
8714
return BTF_EVNT_MAX;
8715
else if (ver->fwc2hfunc == 1)
8716
return BTF_EVNT_C2H_LOOPBACK;
8717
else if (ver->fwc2hfunc == 2)
8718
return func;
8719
else if (ver->fwc2hfunc == 3)
8720
return BTF_EVNT_C2H_LOOPBACK;
8721
else
8722
return BTF_EVNT_MAX;
8723
case BTF_EVNT_C2H_LOOPBACK:
8724
if (ver->fwc2hfunc == 2)
8725
return func;
8726
else if (ver->fwc2hfunc == 3)
8727
return BTF_EVNT_BT_LEAUDIO_INFO;
8728
else
8729
return BTF_EVNT_MAX;
8730
case BTF_EVNT_BT_QUERY_TXPWR:
8731
if (ver->fwc2hfunc == 3)
8732
return func;
8733
else
8734
return BTF_EVNT_MAX;
8735
case BTF_EVNT_MAX:
8736
default:
8737
return BTF_EVNT_MAX;
8738
}
8739
}
8740
8741
void rtw89_btc_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
8742
u32 len, u8 class, u8 func)
8743
{
8744
struct rtw89_btc *btc = &rtwdev->btc;
8745
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
8746
u8 *buf = &skb->data[RTW89_C2H_HEADER_LEN];
8747
8748
len -= RTW89_C2H_HEADER_LEN;
8749
8750
rtw89_debug(rtwdev, RTW89_DBG_BTC,
8751
"[BTC], %s(): C2H BT len:%d class:%d fun:%d\n",
8752
__func__, len, class, func);
8753
8754
if (class != BTFC_FW_EVENT)
8755
return;
8756
8757
func = rtw89_btc_c2h_get_index_by_ver(rtwdev, func);
8758
pfwinfo->cnt_c2h++;
8759
8760
switch (func) {
8761
case BTF_EVNT_BUF_OVERFLOW:
8762
pfwinfo->event[func]++;
8763
break;
8764
case BTF_EVNT_RPT:
8765
pfwinfo->event[func]++;
8766
/* Don't need rtw89_leave_ps_mode() */
8767
btc_fw_event(rtwdev, func, buf, len);
8768
break;
8769
case BTF_EVNT_BT_INFO:
8770
rtw89_debug(rtwdev, RTW89_DBG_BTC,
8771
"[BTC], handle C2H BT INFO with data %8ph\n", buf);
8772
btc->cx.cnt_bt[BTC_BCNT_INFOUPDATE]++;
8773
_update_bt_info(rtwdev, buf, len);
8774
break;
8775
case BTF_EVNT_BT_SCBD:
8776
rtw89_debug(rtwdev, RTW89_DBG_BTC,
8777
"[BTC], handle C2H BT SCBD with data %8ph\n", buf);
8778
btc->cx.cnt_bt[BTC_BCNT_SCBDUPDATE]++;
8779
_update_bt_scbd(rtwdev, false);
8780
break;
8781
case BTF_EVNT_BT_PSD:
8782
break;
8783
case BTF_EVNT_BT_REG:
8784
btc->dbg.rb_done = true;
8785
btc->dbg.rb_val = le32_to_cpu(*((__le32 *)buf));
8786
8787
break;
8788
case BTF_EVNT_C2H_LOOPBACK:
8789
btc->dbg.rb_done = true;
8790
btc->dbg.rb_val = buf[0];
8791
break;
8792
case BTF_EVNT_CX_RUNINFO:
8793
btc->dm.cnt_dm[BTC_DCNT_CX_RUNINFO]++;
8794
break;
8795
case BTF_EVNT_BT_QUERY_TXPWR:
8796
btc->cx.cnt_bt[BTC_BCNT_BTTXPWR_UPDATE]++;
8797
_update_bt_txpwr_info(rtwdev, buf, len);
8798
}
8799
}
8800
8801
#define BTC_CX_FW_OFFLOAD 0
8802
8803
static int _show_cx_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
8804
{
8805
union rtw89_btc_module_info *md = &rtwdev->btc.mdinfo;
8806
const struct rtw89_chip_info *chip = rtwdev->chip;
8807
const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
8808
struct rtw89_hal *hal = &rtwdev->hal;
8809
struct rtw89_btc *btc = &rtwdev->btc;
8810
struct rtw89_btc_dm *dm = &btc->dm;
8811
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
8812
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
8813
u32 ver_main = 0, ver_sub = 0, ver_hotfix = 0, id_branch = 0;
8814
u8 cv, rfe, iso, ant_num, ant_single_pos;
8815
char *p = buf, *end = buf + bufsz;
8816
8817
if (!(dm->coex_info_map & BTC_COEX_INFO_CX))
8818
return 0;
8819
8820
p += scnprintf(p, end - p,
8821
"\n========== [BTC COEX INFO (%s)] ==========\n",
8822
chip_id_str(chip->chip_id));
8823
8824
ver_main = FIELD_GET(GENMASK(31, 24), RTW89_COEX_VERSION);
8825
ver_sub = FIELD_GET(GENMASK(23, 16), RTW89_COEX_VERSION);
8826
ver_hotfix = FIELD_GET(GENMASK(15, 8), RTW89_COEX_VERSION);
8827
id_branch = FIELD_GET(GENMASK(7, 0), RTW89_COEX_VERSION);
8828
p += scnprintf(p, end - p, " %-15s : Coex:%d.%d.%d(branch:%d), ",
8829
"[coex_version]", ver_main, ver_sub, ver_hotfix,
8830
id_branch);
8831
8832
ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
8833
ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw_coex);
8834
ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw_coex);
8835
id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw_coex);
8836
p += scnprintf(p, end - p, "WL_FW_coex:%d.%d.%d(branch:%d)",
8837
ver_main, ver_sub, ver_hotfix, id_branch);
8838
8839
ver_main = FIELD_GET(GENMASK(31, 24), chip->wlcx_desired);
8840
ver_sub = FIELD_GET(GENMASK(23, 16), chip->wlcx_desired);
8841
ver_hotfix = FIELD_GET(GENMASK(15, 8), chip->wlcx_desired);
8842
p += scnprintf(p, end - p, "(%s, desired:%d.%d.%d), ",
8843
(wl->ver_info.fw_coex >= chip->wlcx_desired ?
8844
"Match" : "Mismatch"), ver_main, ver_sub, ver_hotfix);
8845
8846
p += scnprintf(p, end - p, "BT_FW_coex:%d(%s, desired:%d)\n",
8847
bt->ver_info.fw_coex,
8848
(bt->ver_info.fw_coex >= ver->bt_desired ?
8849
"Match" : "Mismatch"), ver->bt_desired);
8850
8851
if (bt->enable.now && bt->ver_info.fw == 0)
8852
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, true);
8853
else
8854
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_VER_INFO, false);
8855
8856
ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw);
8857
ver_sub = FIELD_GET(GENMASK(23, 16), wl->ver_info.fw);
8858
ver_hotfix = FIELD_GET(GENMASK(15, 8), wl->ver_info.fw);
8859
id_branch = FIELD_GET(GENMASK(7, 0), wl->ver_info.fw);
8860
p += scnprintf(p, end - p,
8861
" %-15s : WL_FW:%d.%d.%d.%d, BT_FW:0x%x(%s)\n",
8862
"[sub_module]",
8863
ver_main, ver_sub, ver_hotfix, id_branch,
8864
bt->ver_info.fw, bt->run_patch_code ? "patch" : "ROM");
8865
8866
if (ver->fcxinit == 7) {
8867
cv = md->md_v7.kt_ver;
8868
rfe = md->md_v7.rfe_type;
8869
iso = md->md_v7.ant.isolation;
8870
ant_num = md->md_v7.ant.num;
8871
ant_single_pos = md->md_v7.ant.single_pos;
8872
} else {
8873
cv = md->md.cv;
8874
rfe = md->md.rfe_type;
8875
iso = md->md.ant.isolation;
8876
ant_num = md->md.ant.num;
8877
ant_single_pos = md->md.ant.single_pos;
8878
}
8879
8880
p += scnprintf(p, end - p,
8881
" %-15s : cv:%x, rfe_type:0x%x, ant_iso:%d, ant_pg:%d, %s",
8882
"[hw_info]", cv, rfe, iso, ant_num,
8883
ant_num > 1 ? "" :
8884
ant_single_pos ? "1Ant_Pos:S1, " : "1Ant_Pos:S0, ");
8885
8886
p += scnprintf(p, end - p,
8887
"3rd_coex:%d, dbcc:%d, tx_num:%d, rx_num:%d\n",
8888
btc->cx.other.type, rtwdev->dbcc_en, hal->tx_nss,
8889
hal->rx_nss);
8890
8891
return p - buf;
8892
}
8893
8894
static int _show_wl_role_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
8895
{
8896
struct rtw89_btc *btc = &rtwdev->btc;
8897
struct rtw89_btc_wl_link_info *plink = NULL;
8898
struct rtw89_traffic_stats *t;
8899
char *p = buf, *end = buf + bufsz;
8900
u8 i, j;
8901
8902
for (i = 0; i < btc->ver->max_role_num; i++) {
8903
for (j = 0; j < RTW89_MAC_NUM; j++) {
8904
if (btc->ver->fwlrole == 8)
8905
plink = &btc->cx.wl.rlink_info[i][j];
8906
else
8907
plink = &btc->cx.wl.link_info[i];
8908
8909
if (!plink->active)
8910
continue;
8911
8912
p += scnprintf(p, end - p,
8913
" [port_%d] : role=%d(phy-%d), connect=%s(client_cnt=%d), mode=%d, center_ch=%d, bw=%d",
8914
plink->pid, plink->role, plink->phy,
8915
id_to_mlme_state(plink->connected),
8916
plink->client_cnt - 1, plink->mode,
8917
plink->ch, plink->bw);
8918
8919
if (plink->connected == MLME_NO_LINK)
8920
continue;
8921
8922
p += scnprintf(p, end - p,
8923
", mac_id=%d, max_tx_time=%dus, max_tx_retry=%d\n",
8924
plink->mac_id, plink->tx_time, plink->tx_retry);
8925
8926
p += scnprintf(p, end - p,
8927
" [port_%d] : rssi=-%ddBm(%d), busy=%d, dir=%s, ",
8928
plink->pid, 110 - plink->stat.rssi,
8929
plink->stat.rssi, plink->busy,
8930
plink->dir == RTW89_TFC_UL ? "UL" : "DL");
8931
8932
t = &plink->stat.traffic;
8933
8934
p += scnprintf(p, end - p,
8935
"tx[rate:%d/busy_level:%d], ",
8936
t->tx_rate, t->tx_tfc_lv);
8937
8938
p += scnprintf(p, end - p,
8939
"rx[rate:%d/busy_level:%d/drop:%d]\n",
8940
t->rx_rate,
8941
t->rx_tfc_lv, plink->rx_rate_drop_cnt);
8942
}
8943
}
8944
return p - buf;
8945
}
8946
8947
static int _show_wl_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
8948
{
8949
struct rtw89_btc *btc = &rtwdev->btc;
8950
const struct rtw89_btc_ver *ver = btc->ver;
8951
struct rtw89_btc_cx *cx = &btc->cx;
8952
struct rtw89_btc_wl_info *wl = &cx->wl;
8953
struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
8954
struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
8955
struct rtw89_btc_wl_role_info_v2 *wl_rinfo_v2 = &wl->role_info_v2;
8956
struct rtw89_btc_wl_role_info_v7 *wl_rinfo_v7 = &wl->role_info_v7;
8957
struct rtw89_btc_wl_role_info_v8 *wl_rinfo_v8 = &wl->role_info_v8;
8958
char *p = buf, *end = buf + bufsz;
8959
u8 mode;
8960
8961
if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
8962
return 0;
8963
8964
p += scnprintf(p, end - p, "========== [WL Status] ==========\n");
8965
8966
if (ver->fwlrole == 0)
8967
mode = wl_rinfo->link_mode;
8968
else if (ver->fwlrole == 1)
8969
mode = wl_rinfo_v1->link_mode;
8970
else if (ver->fwlrole == 2)
8971
mode = wl_rinfo_v2->link_mode;
8972
else if (ver->fwlrole == 7)
8973
mode = wl_rinfo_v7->link_mode;
8974
else if (ver->fwlrole == 8)
8975
mode = wl_rinfo_v8->link_mode;
8976
else
8977
goto out;
8978
8979
p += scnprintf(p, end - p, " %-15s : link_mode:%s, ", "[status]",
8980
id_to_linkmode(mode));
8981
8982
p += scnprintf(p, end - p,
8983
"rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ",
8984
wl->status.map.rf_off, wl->status.map.lps,
8985
wl->status.map.scan ? "Y" : "N",
8986
wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
8987
8988
p += scnprintf(p, end - p,
8989
"connecting:%s, roam:%s, 4way:%s, init_ok:%s\n",
8990
wl->status.map.connecting ? "Y" : "N",
8991
wl->status.map.roaming ? "Y" : "N",
8992
wl->status.map._4way ? "Y" : "N",
8993
wl->status.map.init_ok ? "Y" : "N");
8994
8995
p += _show_wl_role_info(rtwdev, p, end - p);
8996
8997
out:
8998
return p - buf;
8999
}
9000
9001
enum btc_bt_a2dp_type {
9002
BTC_A2DP_LEGACY = 0,
9003
BTC_A2DP_TWS_SNIFF = 1,
9004
BTC_A2DP_TWS_RELAY = 2,
9005
};
9006
9007
static int _show_bt_profile_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9008
{
9009
struct rtw89_btc *btc = &rtwdev->btc;
9010
struct rtw89_btc_bt_link_info *bt_linfo = &btc->cx.bt.link_info;
9011
struct rtw89_btc_bt_hfp_desc hfp = bt_linfo->hfp_desc;
9012
struct rtw89_btc_bt_hid_desc hid = bt_linfo->hid_desc;
9013
struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
9014
struct rtw89_btc_bt_pan_desc pan = bt_linfo->pan_desc;
9015
char *p = buf, *end = buf + bufsz;
9016
9017
if (hfp.exist) {
9018
p += scnprintf(p, end - p,
9019
" %-15s : type:%s, sut_pwr:%d, golden-rx:%d",
9020
"[HFP]", (hfp.type == 0 ? "SCO" : "eSCO"),
9021
bt_linfo->sut_pwr_level[0],
9022
bt_linfo->golden_rx_shift[0]);
9023
}
9024
9025
if (hid.exist) {
9026
p += scnprintf(p, end - p,
9027
"\n\r %-15s : type:%s%s%s%s%s pair-cnt:%d, sut_pwr:%d, golden-rx:%d\n",
9028
"[HID]",
9029
hid.type & BTC_HID_218 ? "2/18," : "",
9030
hid.type & BTC_HID_418 ? "4/18," : "",
9031
hid.type & BTC_HID_BLE ? "BLE," : "",
9032
hid.type & BTC_HID_RCU ? "RCU," : "",
9033
hid.type & BTC_HID_RCU_VOICE ? "RCU-Voice," : "",
9034
hid.pair_cnt, bt_linfo->sut_pwr_level[1],
9035
bt_linfo->golden_rx_shift[1]);
9036
}
9037
9038
if (a2dp.exist) {
9039
p += scnprintf(p, end - p,
9040
" %-15s : type:%s, bit-pool:%d, flush-time:%d, ",
9041
"[A2DP]",
9042
a2dp.type == BTC_A2DP_LEGACY ? "Legacy" : "TWS",
9043
a2dp.bitpool, a2dp.flush_time);
9044
9045
p += scnprintf(p, end - p,
9046
"vid:0x%x, Dev-name:0x%x, sut_pwr:%d, golden-rx:%d\n",
9047
a2dp.vendor_id, a2dp.device_name,
9048
bt_linfo->sut_pwr_level[2],
9049
bt_linfo->golden_rx_shift[2]);
9050
}
9051
9052
if (pan.exist) {
9053
p += scnprintf(p, end - p,
9054
" %-15s : sut_pwr:%d, golden-rx:%d\n",
9055
"[PAN]",
9056
bt_linfo->sut_pwr_level[3],
9057
bt_linfo->golden_rx_shift[3]);
9058
}
9059
9060
return p - buf;
9061
}
9062
9063
static int _show_bt_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9064
{
9065
struct rtw89_btc *btc = &rtwdev->btc;
9066
const struct rtw89_btc_ver *ver = btc->ver;
9067
struct rtw89_btc_cx *cx = &btc->cx;
9068
struct rtw89_btc_bt_info *bt = &cx->bt;
9069
struct rtw89_btc_wl_info *wl = &cx->wl;
9070
u32 ver_main = FIELD_GET(GENMASK(31, 24), wl->ver_info.fw_coex);
9071
struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
9072
union rtw89_btc_module_info *md = &btc->mdinfo;
9073
s8 br_dbm = bt->link_info.bt_txpwr_desc.br_dbm;
9074
s8 le_dbm = bt->link_info.bt_txpwr_desc.le_dbm;
9075
char *p = buf, *end = buf + bufsz;
9076
u8 *afh = bt_linfo->afh_map;
9077
u8 *afh_le = bt_linfo->afh_map_le;
9078
u8 bt_pos;
9079
9080
if (!(btc->dm.coex_info_map & BTC_COEX_INFO_BT))
9081
return 0;
9082
9083
if (ver->fcxinit == 7)
9084
bt_pos = md->md_v7.bt_pos;
9085
else
9086
bt_pos = md->md.bt_pos;
9087
9088
p += scnprintf(p, end - p, "========== [BT Status] ==========\n");
9089
9090
p += scnprintf(p, end - p,
9091
" %-15s : enable:%s, btg:%s%s, connect:%s, ",
9092
"[status]", bt->enable.now ? "Y" : "N",
9093
bt->btg_type ? "Y" : "N",
9094
(bt->enable.now && (bt->btg_type != bt_pos) ?
9095
"(efuse-mismatch!!)" : ""),
9096
(bt_linfo->status.map.connect ? "Y" : "N"));
9097
9098
p += scnprintf(p, end - p,
9099
"igno_wl:%s, mailbox_avl:%s, rfk_state:0x%x\n",
9100
bt->igno_wl ? "Y" : "N",
9101
bt->mbx_avl ? "Y" : "N", bt->rfk_info.val);
9102
9103
p += scnprintf(p, end - p, " %-15s : profile:%s%s%s%s%s ",
9104
"[profile]",
9105
(bt_linfo->profile_cnt.now == 0) ? "None," : "",
9106
bt_linfo->hfp_desc.exist ? "HFP," : "",
9107
bt_linfo->hid_desc.exist ? "HID," : "",
9108
bt_linfo->a2dp_desc.exist ?
9109
(bt_linfo->a2dp_desc.sink ? "A2DP_sink," : "A2DP,") : "",
9110
bt_linfo->pan_desc.exist ? "PAN," : "");
9111
9112
p += scnprintf(p, end - p,
9113
"multi-link:%s, role:%s, ble-connect:%s, CQDDR:%s, A2DP_active:%s, PAN_active:%s\n",
9114
bt_linfo->multi_link.now ? "Y" : "N",
9115
bt_linfo->slave_role ? "Slave" : "Master",
9116
bt_linfo->status.map.ble_connect ? "Y" : "N",
9117
bt_linfo->cqddr ? "Y" : "N",
9118
bt_linfo->a2dp_desc.active ? "Y" : "N",
9119
bt_linfo->pan_desc.active ? "Y" : "N");
9120
9121
p += scnprintf(p, end - p,
9122
" %-15s : rssi:%ddBm(lvl:%d), tx_rate:%dM, %s%s%s",
9123
"[link]", bt_linfo->rssi - 100,
9124
bt->rssi_level,
9125
bt_linfo->tx_3m ? 3 : 2,
9126
bt_linfo->status.map.inq_pag ? " inq-page!!" : "",
9127
bt_linfo->status.map.acl_busy ? " acl_busy!!" : "",
9128
bt_linfo->status.map.mesh_busy ? " mesh_busy!!" : "");
9129
9130
p += scnprintf(p, end - p,
9131
"%s afh_map[%02x%02x_%02x%02x_%02x%02x_%02x%02x_%02x%02x], ",
9132
bt_linfo->relink.now ? " ReLink!!" : "",
9133
afh[0], afh[1], afh[2], afh[3], afh[4],
9134
afh[5], afh[6], afh[7], afh[8], afh[9]);
9135
9136
if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
9137
p += scnprintf(p, end - p,
9138
"LE[%02x%02x_%02x_%02x%02x]",
9139
afh_le[0], afh_le[1], afh_le[2],
9140
afh_le[3], afh_le[4]);
9141
9142
p += scnprintf(p, end - p, "wl_ch_map[en:%d/ch:%d/bw:%d]\n",
9143
wl->afh_info.en, wl->afh_info.ch, wl->afh_info.bw);
9144
9145
p += scnprintf(p, end - p,
9146
" %-15s : retry:%d, relink:%d, rate_chg:%d, reinit:%d, reenable:%d, ",
9147
"[stat_cnt]", cx->cnt_bt[BTC_BCNT_RETRY],
9148
cx->cnt_bt[BTC_BCNT_RELINK],
9149
cx->cnt_bt[BTC_BCNT_RATECHG],
9150
cx->cnt_bt[BTC_BCNT_REINIT],
9151
cx->cnt_bt[BTC_BCNT_REENABLE]);
9152
9153
p += scnprintf(p, end - p,
9154
"role-switch:%d, afh:%d, inq_page:%d(inq:%d/page:%d), igno_wl:%d\n",
9155
cx->cnt_bt[BTC_BCNT_ROLESW], cx->cnt_bt[BTC_BCNT_AFH],
9156
cx->cnt_bt[BTC_BCNT_INQPAG], cx->cnt_bt[BTC_BCNT_INQ],
9157
cx->cnt_bt[BTC_BCNT_PAGE], cx->cnt_bt[BTC_BCNT_IGNOWL]);
9158
9159
p += _show_bt_profile_info(rtwdev, p, end - p);
9160
9161
p += scnprintf(p, end - p,
9162
" %-15s : raw_data[%02x %02x %02x %02x %02x %02x] (type:%s/cnt:%d/same:%d)\n",
9163
"[bt_info]", bt->raw_info[2], bt->raw_info[3],
9164
bt->raw_info[4], bt->raw_info[5], bt->raw_info[6],
9165
bt->raw_info[7],
9166
bt->raw_info[0] == BTC_BTINFO_AUTO ? "auto" : "reply",
9167
cx->cnt_bt[BTC_BCNT_INFOUPDATE],
9168
cx->cnt_bt[BTC_BCNT_INFOSAME]);
9169
9170
p += scnprintf(p, end - p,
9171
" %-15s : Hi-rx = %d, Hi-tx = %d, Lo-rx = %d, Lo-tx = %d (bt_polut_wl_tx = %d)",
9172
"[trx_req_cnt]", cx->cnt_bt[BTC_BCNT_HIPRI_RX],
9173
cx->cnt_bt[BTC_BCNT_HIPRI_TX],
9174
cx->cnt_bt[BTC_BCNT_LOPRI_RX],
9175
cx->cnt_bt[BTC_BCNT_LOPRI_TX],
9176
cx->cnt_bt[BTC_BCNT_POLUT]);
9177
9178
if (!bt->scan_info_update) {
9179
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, true);
9180
p += scnprintf(p, end - p, "\n");
9181
} else {
9182
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_SCAN_INFO, false);
9183
if (ver->fcxbtscan == 1) {
9184
p += scnprintf(p, end - p,
9185
"(INQ:%d-%d/PAGE:%d-%d/LE:%d-%d/INIT:%d-%d)",
9186
le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].win),
9187
le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INQ].intvl),
9188
le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].win),
9189
le16_to_cpu(bt->scan_info_v1[BTC_SCAN_PAGE].intvl),
9190
le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].win),
9191
le16_to_cpu(bt->scan_info_v1[BTC_SCAN_BLE].intvl),
9192
le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].win),
9193
le16_to_cpu(bt->scan_info_v1[BTC_SCAN_INIT].intvl));
9194
} else if (ver->fcxbtscan == 2) {
9195
p += scnprintf(p, end - p,
9196
"(BG:%d-%d/INIT:%d-%d/LE:%d-%d)",
9197
le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].win),
9198
le16_to_cpu(bt->scan_info_v2[CXSCAN_BG].intvl),
9199
le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].win),
9200
le16_to_cpu(bt->scan_info_v2[CXSCAN_INIT].intvl),
9201
le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].win),
9202
le16_to_cpu(bt->scan_info_v2[CXSCAN_LE].intvl));
9203
}
9204
p += scnprintf(p, end - p, "\n");
9205
}
9206
9207
if (ver_main >= 9 && bt_linfo->profile_cnt.now)
9208
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_TX_PWR_LVL, true);
9209
else
9210
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_TX_PWR_LVL, false);
9211
9212
if (cx->cnt_bt[BTC_BCNT_BTTXPWR_UPDATE]) {
9213
p += scnprintf(p, end - p,
9214
" %-15s : br_index:0x%x, le_index:0x%x",
9215
"[bt_txpwr_lvl]",
9216
bt->link_info.bt_txpwr_desc.br_gain_index,
9217
bt->link_info.bt_txpwr_desc.le_gain_index);
9218
p += scnprintf(p, end - p, ", br_dbm:%d dBm", br_dbm);
9219
p += scnprintf(p, end - p, ", le_dbm:%d dBm", le_dbm);
9220
} else {
9221
p += scnprintf(p, end - p,
9222
" %-15s : br_index:NA, le_index:NA, br_dbm:%d dBm[def], le_dbm:%d dBm[def]",
9223
"[bt_txpwr_lvl]",
9224
bt->link_info.bt_txpwr_desc.br_dbm,
9225
bt->link_info.bt_txpwr_desc.le_dbm);
9226
}
9227
p += scnprintf(p, end - p, "\n");
9228
9229
if (bt_linfo->profile_cnt.now || bt_linfo->status.map.ble_connect)
9230
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, true);
9231
else
9232
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP, false);
9233
9234
if (ver->fcxbtafh == 2 && bt_linfo->status.map.ble_connect)
9235
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, true);
9236
else
9237
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_AFH_MAP_LE, false);
9238
9239
if (bt_linfo->a2dp_desc.exist &&
9240
(bt_linfo->a2dp_desc.flush_time == 0 ||
9241
bt_linfo->a2dp_desc.vendor_id == 0 ||
9242
bt_linfo->a2dp_desc.play_latency == 1))
9243
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, true);
9244
else
9245
rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_BT_DEVICE_INFO, false);
9246
9247
return p - buf;
9248
}
9249
9250
#define CASE_BTC_RSN_STR(e) case BTC_RSN_ ## e: return #e
9251
#define CASE_BTC_ACT_STR(e) case BTC_ACT_ ## e | BTC_ACT_EXT_BIT: return #e
9252
#define CASE_BTC_POLICY_STR(e) \
9253
case BTC_CXP_ ## e | BTC_POLICY_EXT_BIT: return #e
9254
#define CASE_BTC_SLOT_STR(e) case CXST_ ## e: return #e
9255
#define CASE_BTC_EVT_STR(e) case CXEVNT_## e: return #e
9256
#define CASE_BTC_INIT(e) case BTC_MODE_## e: return #e
9257
#define CASE_BTC_ANTPATH_STR(e) case BTC_ANT_##e: return #e
9258
#define CASE_BTC_POLUT_STR(e) case BTC_PLT_## e: return #e
9259
#define CASE_BTC_REGTYPE_STR(e) case REG_## e: return #e
9260
#define CASE_BTC_GDBG_STR(e) case BTC_DBG_## e: return #e
9261
9262
static const char *id_to_polut(u32 id)
9263
{
9264
switch (id) {
9265
CASE_BTC_POLUT_STR(NONE);
9266
CASE_BTC_POLUT_STR(GNT_BT_TX);
9267
CASE_BTC_POLUT_STR(GNT_BT_RX);
9268
CASE_BTC_POLUT_STR(GNT_WL);
9269
CASE_BTC_POLUT_STR(BT);
9270
CASE_BTC_POLUT_STR(ALL);
9271
default:
9272
return "unknown";
9273
}
9274
}
9275
9276
static const char *id_to_regtype(u32 id)
9277
{
9278
switch (id) {
9279
CASE_BTC_REGTYPE_STR(MAC);
9280
CASE_BTC_REGTYPE_STR(BB);
9281
CASE_BTC_REGTYPE_STR(RF);
9282
CASE_BTC_REGTYPE_STR(BT_RF);
9283
CASE_BTC_REGTYPE_STR(BT_MODEM);
9284
CASE_BTC_REGTYPE_STR(BT_BLUEWIZE);
9285
CASE_BTC_REGTYPE_STR(BT_VENDOR);
9286
CASE_BTC_REGTYPE_STR(BT_LE);
9287
default:
9288
return "unknown";
9289
}
9290
}
9291
9292
static const char *id_to_gdbg(u32 id)
9293
{
9294
switch (id) {
9295
CASE_BTC_GDBG_STR(GNT_BT);
9296
CASE_BTC_GDBG_STR(GNT_WL);
9297
CASE_BTC_GDBG_STR(BCN_EARLY);
9298
CASE_BTC_GDBG_STR(WL_NULL0);
9299
CASE_BTC_GDBG_STR(WL_NULL1);
9300
CASE_BTC_GDBG_STR(WL_RXISR);
9301
CASE_BTC_GDBG_STR(TDMA_ENTRY);
9302
CASE_BTC_GDBG_STR(A2DP_EMPTY);
9303
CASE_BTC_GDBG_STR(BT_RETRY);
9304
CASE_BTC_GDBG_STR(BT_RELINK);
9305
CASE_BTC_GDBG_STR(SLOT_WL);
9306
CASE_BTC_GDBG_STR(SLOT_BT);
9307
CASE_BTC_GDBG_STR(WL_ERR);
9308
CASE_BTC_GDBG_STR(WL_OK);
9309
CASE_BTC_GDBG_STR(SLOT_B2W);
9310
CASE_BTC_GDBG_STR(SLOT_W1);
9311
CASE_BTC_GDBG_STR(SLOT_W2);
9312
CASE_BTC_GDBG_STR(SLOT_W2B);
9313
CASE_BTC_GDBG_STR(SLOT_B1);
9314
CASE_BTC_GDBG_STR(SLOT_B2);
9315
CASE_BTC_GDBG_STR(SLOT_B3);
9316
CASE_BTC_GDBG_STR(SLOT_B4);
9317
CASE_BTC_GDBG_STR(SLOT_LK);
9318
CASE_BTC_GDBG_STR(SLOT_E2G);
9319
CASE_BTC_GDBG_STR(SLOT_E5G);
9320
CASE_BTC_GDBG_STR(SLOT_EBT);
9321
CASE_BTC_GDBG_STR(SLOT_WLK);
9322
CASE_BTC_GDBG_STR(SLOT_B1FDD);
9323
CASE_BTC_GDBG_STR(BT_CHANGE);
9324
CASE_BTC_GDBG_STR(WL_CCA);
9325
CASE_BTC_GDBG_STR(BT_LEAUDIO);
9326
CASE_BTC_GDBG_STR(USER_DEF);
9327
default:
9328
return "unknown";
9329
}
9330
}
9331
9332
static const char *steps_to_str(u16 step)
9333
{
9334
switch (step) {
9335
CASE_BTC_RSN_STR(NONE);
9336
CASE_BTC_RSN_STR(NTFY_INIT);
9337
CASE_BTC_RSN_STR(NTFY_SWBAND);
9338
CASE_BTC_RSN_STR(NTFY_WL_STA);
9339
CASE_BTC_RSN_STR(NTFY_RADIO_STATE);
9340
CASE_BTC_RSN_STR(UPDATE_BT_SCBD);
9341
CASE_BTC_RSN_STR(NTFY_WL_RFK);
9342
CASE_BTC_RSN_STR(UPDATE_BT_INFO);
9343
CASE_BTC_RSN_STR(NTFY_SCAN_START);
9344
CASE_BTC_RSN_STR(NTFY_SCAN_FINISH);
9345
CASE_BTC_RSN_STR(NTFY_SPECIFIC_PACKET);
9346
CASE_BTC_RSN_STR(NTFY_POWEROFF);
9347
CASE_BTC_RSN_STR(NTFY_ROLE_INFO);
9348
CASE_BTC_RSN_STR(CMD_SET_COEX);
9349
CASE_BTC_RSN_STR(ACT1_WORK);
9350
CASE_BTC_RSN_STR(BT_DEVINFO_WORK);
9351
CASE_BTC_RSN_STR(RFK_CHK_WORK);
9352
9353
CASE_BTC_ACT_STR(NONE);
9354
CASE_BTC_ACT_STR(WL_ONLY);
9355
CASE_BTC_ACT_STR(WL_5G);
9356
CASE_BTC_ACT_STR(WL_OTHER);
9357
CASE_BTC_ACT_STR(WL_IDLE);
9358
CASE_BTC_ACT_STR(WL_NC);
9359
CASE_BTC_ACT_STR(WL_RFK);
9360
CASE_BTC_ACT_STR(WL_INIT);
9361
CASE_BTC_ACT_STR(WL_OFF);
9362
CASE_BTC_ACT_STR(FREERUN);
9363
CASE_BTC_ACT_STR(BT_WHQL);
9364
CASE_BTC_ACT_STR(BT_RFK);
9365
CASE_BTC_ACT_STR(BT_OFF);
9366
CASE_BTC_ACT_STR(BT_IDLE);
9367
CASE_BTC_ACT_STR(BT_HFP);
9368
CASE_BTC_ACT_STR(BT_HID);
9369
CASE_BTC_ACT_STR(BT_A2DP);
9370
CASE_BTC_ACT_STR(BT_A2DPSINK);
9371
CASE_BTC_ACT_STR(BT_PAN);
9372
CASE_BTC_ACT_STR(BT_A2DP_HID);
9373
CASE_BTC_ACT_STR(BT_A2DP_PAN);
9374
CASE_BTC_ACT_STR(BT_PAN_HID);
9375
CASE_BTC_ACT_STR(BT_A2DP_PAN_HID);
9376
CASE_BTC_ACT_STR(WL_25G_MCC);
9377
CASE_BTC_ACT_STR(WL_2G_MCC);
9378
CASE_BTC_ACT_STR(WL_2G_SCC);
9379
CASE_BTC_ACT_STR(WL_2G_AP);
9380
CASE_BTC_ACT_STR(WL_2G_GO);
9381
CASE_BTC_ACT_STR(WL_2G_GC);
9382
CASE_BTC_ACT_STR(WL_2G_NAN);
9383
9384
CASE_BTC_POLICY_STR(OFF_BT);
9385
CASE_BTC_POLICY_STR(OFF_WL);
9386
CASE_BTC_POLICY_STR(OFF_EQ0);
9387
CASE_BTC_POLICY_STR(OFF_EQ1);
9388
CASE_BTC_POLICY_STR(OFF_EQ2);
9389
CASE_BTC_POLICY_STR(OFF_EQ3);
9390
CASE_BTC_POLICY_STR(OFF_EQ4);
9391
CASE_BTC_POLICY_STR(OFF_EQ5);
9392
CASE_BTC_POLICY_STR(OFF_BWB0);
9393
CASE_BTC_POLICY_STR(OFF_BWB1);
9394
CASE_BTC_POLICY_STR(OFF_BWB2);
9395
CASE_BTC_POLICY_STR(OFF_BWB3);
9396
CASE_BTC_POLICY_STR(OFF_WL2);
9397
CASE_BTC_POLICY_STR(OFFB_BWB0);
9398
CASE_BTC_POLICY_STR(OFFE_DEF);
9399
CASE_BTC_POLICY_STR(OFFE_DEF2);
9400
CASE_BTC_POLICY_STR(OFFE_2GBWISOB);
9401
CASE_BTC_POLICY_STR(OFFE_2GISOB);
9402
CASE_BTC_POLICY_STR(OFFE_2GBWMIXB);
9403
CASE_BTC_POLICY_STR(OFFE_WL);
9404
CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2);
9405
CASE_BTC_POLICY_STR(FIX_TD3030);
9406
CASE_BTC_POLICY_STR(FIX_TD5050);
9407
CASE_BTC_POLICY_STR(FIX_TD2030);
9408
CASE_BTC_POLICY_STR(FIX_TD4010);
9409
CASE_BTC_POLICY_STR(FIX_TD7010);
9410
CASE_BTC_POLICY_STR(FIX_TD2060);
9411
CASE_BTC_POLICY_STR(FIX_TD3060);
9412
CASE_BTC_POLICY_STR(FIX_TD2080);
9413
CASE_BTC_POLICY_STR(FIX_TDW1B1);
9414
CASE_BTC_POLICY_STR(FIX_TD4010ISO);
9415
CASE_BTC_POLICY_STR(FIX_TD4010ISO_DL);
9416
CASE_BTC_POLICY_STR(FIX_TD4010ISO_UL);
9417
CASE_BTC_POLICY_STR(PFIX_TD3030);
9418
CASE_BTC_POLICY_STR(PFIX_TD5050);
9419
CASE_BTC_POLICY_STR(PFIX_TD2030);
9420
CASE_BTC_POLICY_STR(PFIX_TD2060);
9421
CASE_BTC_POLICY_STR(PFIX_TD3070);
9422
CASE_BTC_POLICY_STR(PFIX_TD2080);
9423
CASE_BTC_POLICY_STR(PFIX_TDW1B1);
9424
CASE_BTC_POLICY_STR(AUTO_TD50B1);
9425
CASE_BTC_POLICY_STR(AUTO_TD60B1);
9426
CASE_BTC_POLICY_STR(AUTO_TD20B1);
9427
CASE_BTC_POLICY_STR(AUTO_TDW1B1);
9428
CASE_BTC_POLICY_STR(PAUTO_TD50B1);
9429
CASE_BTC_POLICY_STR(PAUTO_TD60B1);
9430
CASE_BTC_POLICY_STR(PAUTO_TD20B1);
9431
CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
9432
CASE_BTC_POLICY_STR(AUTO2_TD3050);
9433
CASE_BTC_POLICY_STR(AUTO2_TD3070);
9434
CASE_BTC_POLICY_STR(AUTO2_TD5050);
9435
CASE_BTC_POLICY_STR(AUTO2_TD6060);
9436
CASE_BTC_POLICY_STR(AUTO2_TD2080);
9437
CASE_BTC_POLICY_STR(AUTO2_TDW1B4);
9438
CASE_BTC_POLICY_STR(PAUTO2_TD3050);
9439
CASE_BTC_POLICY_STR(PAUTO2_TD3070);
9440
CASE_BTC_POLICY_STR(PAUTO2_TD5050);
9441
CASE_BTC_POLICY_STR(PAUTO2_TD6060);
9442
CASE_BTC_POLICY_STR(PAUTO2_TD2080);
9443
CASE_BTC_POLICY_STR(PAUTO2_TDW1B4);
9444
default:
9445
return "unknown step";
9446
}
9447
}
9448
9449
static const char *id_to_slot(u32 id)
9450
{
9451
switch (id) {
9452
CASE_BTC_SLOT_STR(OFF);
9453
CASE_BTC_SLOT_STR(B2W);
9454
CASE_BTC_SLOT_STR(W1);
9455
CASE_BTC_SLOT_STR(W2);
9456
CASE_BTC_SLOT_STR(W2B);
9457
CASE_BTC_SLOT_STR(B1);
9458
CASE_BTC_SLOT_STR(B2);
9459
CASE_BTC_SLOT_STR(B3);
9460
CASE_BTC_SLOT_STR(B4);
9461
CASE_BTC_SLOT_STR(LK);
9462
CASE_BTC_SLOT_STR(BLK);
9463
CASE_BTC_SLOT_STR(E2G);
9464
CASE_BTC_SLOT_STR(E5G);
9465
CASE_BTC_SLOT_STR(EBT);
9466
CASE_BTC_SLOT_STR(ENULL);
9467
CASE_BTC_SLOT_STR(WLK);
9468
CASE_BTC_SLOT_STR(W1FDD);
9469
CASE_BTC_SLOT_STR(B1FDD);
9470
default:
9471
return "unknown";
9472
}
9473
}
9474
9475
static const char *id_to_evt(u32 id)
9476
{
9477
switch (id) {
9478
CASE_BTC_EVT_STR(TDMA_ENTRY);
9479
CASE_BTC_EVT_STR(WL_TMR);
9480
CASE_BTC_EVT_STR(B1_TMR);
9481
CASE_BTC_EVT_STR(B2_TMR);
9482
CASE_BTC_EVT_STR(B3_TMR);
9483
CASE_BTC_EVT_STR(B4_TMR);
9484
CASE_BTC_EVT_STR(W2B_TMR);
9485
CASE_BTC_EVT_STR(B2W_TMR);
9486
CASE_BTC_EVT_STR(BCN_EARLY);
9487
CASE_BTC_EVT_STR(A2DP_EMPTY);
9488
CASE_BTC_EVT_STR(LK_END);
9489
CASE_BTC_EVT_STR(RX_ISR);
9490
CASE_BTC_EVT_STR(RX_FC0);
9491
CASE_BTC_EVT_STR(RX_FC1);
9492
CASE_BTC_EVT_STR(BT_RELINK);
9493
CASE_BTC_EVT_STR(BT_RETRY);
9494
CASE_BTC_EVT_STR(E2G);
9495
CASE_BTC_EVT_STR(E5G);
9496
CASE_BTC_EVT_STR(EBT);
9497
CASE_BTC_EVT_STR(ENULL);
9498
CASE_BTC_EVT_STR(DRV_WLK);
9499
CASE_BTC_EVT_STR(BCN_OK);
9500
CASE_BTC_EVT_STR(BT_CHANGE);
9501
CASE_BTC_EVT_STR(EBT_EXTEND);
9502
CASE_BTC_EVT_STR(E2G_NULL1);
9503
CASE_BTC_EVT_STR(B1FDD_TMR);
9504
default:
9505
return "unknown";
9506
}
9507
}
9508
9509
static const char *id_to_mode(u8 id)
9510
{
9511
switch (id) {
9512
CASE_BTC_INIT(NORMAL);
9513
CASE_BTC_INIT(WL);
9514
CASE_BTC_INIT(BT);
9515
CASE_BTC_INIT(WLOFF);
9516
default:
9517
return "unknown";
9518
}
9519
}
9520
9521
static const char *id_to_ant(u32 id)
9522
{
9523
switch (id) {
9524
CASE_BTC_ANTPATH_STR(WPOWERON);
9525
CASE_BTC_ANTPATH_STR(WINIT);
9526
CASE_BTC_ANTPATH_STR(WONLY);
9527
CASE_BTC_ANTPATH_STR(WOFF);
9528
CASE_BTC_ANTPATH_STR(W2G);
9529
CASE_BTC_ANTPATH_STR(W5G);
9530
CASE_BTC_ANTPATH_STR(W25G);
9531
CASE_BTC_ANTPATH_STR(FREERUN);
9532
CASE_BTC_ANTPATH_STR(WRFK);
9533
CASE_BTC_ANTPATH_STR(BRFK);
9534
CASE_BTC_ANTPATH_STR(MAX);
9535
default:
9536
return "unknown";
9537
}
9538
}
9539
9540
static
9541
int scnprintf_segment(char *buf, size_t bufsz, const char *prefix, const u16 *data,
9542
u8 len, u8 seg_len, u8 start_idx, u8 ring_len)
9543
{
9544
char *p = buf, *end = buf + bufsz;
9545
u8 cur_index;
9546
u8 i;
9547
9548
for (i = 0; i < len ; i++) {
9549
if ((i % seg_len) == 0)
9550
p += scnprintf(p, end - p, " %-15s : ", prefix);
9551
cur_index = (start_idx + i) % ring_len;
9552
if (i % 3 == 0)
9553
p += scnprintf(p, end - p, "-> %-20s",
9554
steps_to_str(*(data + cur_index)));
9555
else if (i % 3 == 1)
9556
p += scnprintf(p, end - p, "-> %-15s",
9557
steps_to_str(*(data + cur_index)));
9558
else
9559
p += scnprintf(p, end - p, "-> %-13s",
9560
steps_to_str(*(data + cur_index)));
9561
if (i == (len - 1) || (i % seg_len) == (seg_len - 1))
9562
p += scnprintf(p, end - p, "\n");
9563
}
9564
9565
return p - buf;
9566
}
9567
9568
static int _show_dm_step(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9569
{
9570
struct rtw89_btc *btc = &rtwdev->btc;
9571
struct rtw89_btc_dm *dm = &btc->dm;
9572
char *p = buf, *end = buf + bufsz;
9573
u8 start_idx;
9574
u8 len;
9575
9576
len = dm->dm_step.step_ov ? RTW89_BTC_DM_MAXSTEP : dm->dm_step.step_pos;
9577
start_idx = dm->dm_step.step_ov ? dm->dm_step.step_pos : 0;
9578
9579
p += scnprintf_segment(p, end - p, "[dm_steps]", dm->dm_step.step, len,
9580
6, start_idx, ARRAY_SIZE(dm->dm_step.step));
9581
9582
return p - buf;
9583
}
9584
9585
static int _show_dm_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9586
{
9587
struct rtw89_btc *btc = &rtwdev->btc;
9588
const struct rtw89_btc_ver *ver = btc->ver;
9589
struct rtw89_btc_dm *dm = &btc->dm;
9590
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
9591
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
9592
char *p = buf, *end = buf + bufsz;
9593
u8 igno_bt;
9594
9595
if (!(dm->coex_info_map & BTC_COEX_INFO_DM))
9596
return 0;
9597
9598
p += scnprintf(p, end - p,
9599
"========== [Mechanism Status %s] ==========\n",
9600
(btc->manual_ctrl ? "(Manual)" : "(Auto)"));
9601
9602
p += scnprintf(p, end - p,
9603
" %-15s : type:%s, reason:%s(), action:%s(), ant_path:%s, init_mode:%s, run_cnt:%d\n",
9604
"[status]",
9605
btc->ant_type == BTC_ANT_SHARED ? "shared" : "dedicated",
9606
steps_to_str(dm->run_reason),
9607
steps_to_str(dm->run_action | BTC_ACT_EXT_BIT),
9608
id_to_ant(FIELD_GET(GENMASK(7, 0), dm->set_ant_path)),
9609
id_to_mode(wl->coex_mode),
9610
dm->cnt_dm[BTC_DCNT_RUN]);
9611
9612
p += _show_dm_step(rtwdev, p, end - p);
9613
9614
if (ver->fcxctrl == 7)
9615
igno_bt = btc->ctrl.ctrl_v7.igno_bt;
9616
else
9617
igno_bt = btc->ctrl.ctrl.igno_bt;
9618
9619
p += scnprintf(p, end - p,
9620
" %-15s : wl_only:%d, bt_only:%d, igno_bt:%d, free_run:%d, wl_ps_ctrl:%d, wl_mimo_ps:%d, ",
9621
"[dm_flag]", dm->wl_only, dm->bt_only, igno_bt,
9622
dm->freerun, btc->lps, dm->wl_mimo_ps);
9623
9624
p += scnprintf(p, end - p, "leak_ap:%d, fw_offload:%s%s\n",
9625
dm->leak_ap,
9626
(BTC_CX_FW_OFFLOAD ? "Y" : "N"),
9627
(dm->wl_fw_cx_offload == BTC_CX_FW_OFFLOAD ?
9628
"" : "(Mismatch!!)"));
9629
9630
if (dm->rf_trx_para.wl_tx_power == 0xff)
9631
p += scnprintf(p, end - p,
9632
" %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:orig, ",
9633
"[trx_ctrl]", wl->rssi_level,
9634
dm->trx_para_level);
9635
9636
else
9637
p += scnprintf(p, end - p,
9638
" %-15s : wl_rssi_lvl:%d, para_lvl:%d, wl_tx_pwr:%d, ",
9639
"[trx_ctrl]", wl->rssi_level,
9640
dm->trx_para_level,
9641
dm->rf_trx_para.wl_tx_power);
9642
9643
p += scnprintf(p, end - p,
9644
"wl_rx_lvl:%d, bt_tx_pwr_dec:%d, bt_rx_lna:%d(%s-tbl), wl_btg_rx:%d\n",
9645
dm->rf_trx_para.wl_rx_gain,
9646
dm->rf_trx_para.bt_tx_power,
9647
dm->rf_trx_para.bt_rx_gain,
9648
(bt->hi_lna_rx ? "Hi" : "Ori"), dm->wl_btg_rx);
9649
9650
p += scnprintf(p, end - p,
9651
" %-15s : wl_tx_limit[en:%d/max_t:%dus/max_retry:%d], bt_slot_reg:%d-TU, bt_scan_rx_low_pri:%d\n",
9652
"[dm_ctrl]", dm->wl_tx_limit.enable,
9653
dm->wl_tx_limit.tx_time,
9654
dm->wl_tx_limit.tx_retry, btc->bt_req_len,
9655
bt->scan_rx_low_pri);
9656
9657
return p - buf;
9658
}
9659
9660
static int _show_error(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9661
{
9662
struct rtw89_btc *btc = &rtwdev->btc;
9663
const struct rtw89_btc_ver *ver = btc->ver;
9664
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9665
union rtw89_btc_fbtc_cysta_info *pcysta;
9666
char *p = buf, *end = buf + bufsz;
9667
u32 except_cnt, exception_map;
9668
9669
pcysta = &pfwinfo->rpt_fbtc_cysta.finfo;
9670
if (ver->fcxcysta == 2) {
9671
pcysta->v2 = pfwinfo->rpt_fbtc_cysta.finfo.v2;
9672
except_cnt = le32_to_cpu(pcysta->v2.except_cnt);
9673
exception_map = le32_to_cpu(pcysta->v2.exception);
9674
} else if (ver->fcxcysta == 3) {
9675
pcysta->v3 = pfwinfo->rpt_fbtc_cysta.finfo.v3;
9676
except_cnt = le32_to_cpu(pcysta->v3.except_cnt);
9677
exception_map = le32_to_cpu(pcysta->v3.except_map);
9678
} else if (ver->fcxcysta == 4) {
9679
pcysta->v4 = pfwinfo->rpt_fbtc_cysta.finfo.v4;
9680
except_cnt = pcysta->v4.except_cnt;
9681
exception_map = le32_to_cpu(pcysta->v4.except_map);
9682
} else if (ver->fcxcysta == 5) {
9683
pcysta->v5 = pfwinfo->rpt_fbtc_cysta.finfo.v5;
9684
except_cnt = pcysta->v5.except_cnt;
9685
exception_map = le32_to_cpu(pcysta->v5.except_map);
9686
} else if (ver->fcxcysta == 7) {
9687
pcysta->v7 = pfwinfo->rpt_fbtc_cysta.finfo.v7;
9688
except_cnt = pcysta->v7.except_cnt;
9689
exception_map = le32_to_cpu(pcysta->v7.except_map);
9690
} else {
9691
return 0;
9692
}
9693
9694
if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW] == 0 && except_cnt == 0 &&
9695
!pfwinfo->len_mismch && !pfwinfo->fver_mismch)
9696
return 0;
9697
9698
p += scnprintf(p, end - p, " %-15s : ", "[error]");
9699
9700
if (pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]) {
9701
p += scnprintf(p, end - p,
9702
"overflow-cnt: %d, ",
9703
pfwinfo->event[BTF_EVNT_BUF_OVERFLOW]);
9704
}
9705
9706
if (pfwinfo->len_mismch) {
9707
p += scnprintf(p, end - p,
9708
"len-mismatch: 0x%x, ",
9709
pfwinfo->len_mismch);
9710
}
9711
9712
if (pfwinfo->fver_mismch) {
9713
p += scnprintf(p, end - p,
9714
"fver-mismatch: 0x%x, ",
9715
pfwinfo->fver_mismch);
9716
}
9717
9718
/* cycle statistics exceptions */
9719
if (exception_map || except_cnt) {
9720
p += scnprintf(p, end - p,
9721
"exception-type: 0x%x, exception-cnt = %d",
9722
exception_map, except_cnt);
9723
}
9724
p += scnprintf(p, end - p, "\n");
9725
9726
return p - buf;
9727
}
9728
9729
static int _show_fbtc_tdma(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9730
{
9731
struct rtw89_btc *btc = &rtwdev->btc;
9732
const struct rtw89_btc_ver *ver = btc->ver;
9733
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9734
struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9735
struct rtw89_btc_fbtc_tdma *t = NULL;
9736
char *p = buf, *end = buf + bufsz;
9737
9738
pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
9739
if (!pcinfo->valid)
9740
return 0;
9741
9742
if (ver->fcxtdma == 1)
9743
t = &pfwinfo->rpt_fbtc_tdma.finfo.v1;
9744
else
9745
t = &pfwinfo->rpt_fbtc_tdma.finfo.v3.tdma;
9746
9747
p += scnprintf(p, end - p,
9748
" %-15s : ", "[tdma_policy]");
9749
p += scnprintf(p, end - p,
9750
"type:%d, rx_flow_ctrl:%d, tx_pause:%d, ",
9751
(u32)t->type,
9752
t->rxflctrl, t->txpause);
9753
9754
p += scnprintf(p, end - p,
9755
"wl_toggle_n:%d, leak_n:%d, ext_ctrl:%d, ",
9756
t->wtgle_n, t->leak_n, t->ext_ctrl);
9757
9758
p += scnprintf(p, end - p,
9759
"policy_type:%d",
9760
(u32)btc->policy_type);
9761
9762
p += scnprintf(p, end - p, "\n");
9763
9764
return p - buf;
9765
}
9766
9767
static int _show_fbtc_slots(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9768
{
9769
struct rtw89_btc *btc = &rtwdev->btc;
9770
struct rtw89_btc_dm *dm = &btc->dm;
9771
char *p = buf, *end = buf + bufsz;
9772
u16 dur, cxtype;
9773
u32 tbl;
9774
u8 i = 0;
9775
9776
for (i = 0; i < CXST_MAX; i++) {
9777
if (btc->ver->fcxslots == 1) {
9778
dur = le16_to_cpu(dm->slot_now.v1[i].dur);
9779
tbl = le32_to_cpu(dm->slot_now.v1[i].cxtbl);
9780
cxtype = le16_to_cpu(dm->slot_now.v1[i].cxtype);
9781
} else if (btc->ver->fcxslots == 7) {
9782
dur = le16_to_cpu(dm->slot_now.v7[i].dur);
9783
tbl = le32_to_cpu(dm->slot_now.v7[i].cxtbl);
9784
cxtype = le16_to_cpu(dm->slot_now.v7[i].cxtype);
9785
} else {
9786
return 0;
9787
}
9788
9789
if (i % 5 == 0)
9790
p += scnprintf(p, end - p,
9791
" %-15s : %5s[%03d/0x%x/%d]",
9792
"[slot_list]",
9793
id_to_slot((u32)i),
9794
dur, tbl, cxtype);
9795
else
9796
p += scnprintf(p, end - p,
9797
", %5s[%03d/0x%x/%d]",
9798
id_to_slot((u32)i),
9799
dur, tbl, cxtype);
9800
9801
if (i % 5 == 4)
9802
p += scnprintf(p, end - p, "\n");
9803
}
9804
9805
return p - buf;
9806
}
9807
9808
static int _show_fbtc_cysta_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9809
{
9810
struct rtw89_btc *btc = &rtwdev->btc;
9811
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9812
struct rtw89_btc_dm *dm = &btc->dm;
9813
struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
9814
struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
9815
struct rtw89_btc_fbtc_cysta_v2 *pcysta_le32 = NULL;
9816
union rtw89_btc_fbtc_rxflct r;
9817
u16 cycle, c_begin, c_end, store_index;
9818
char *p = buf, *end = buf + bufsz;
9819
u8 i, cnt = 0, slot_pair;
9820
9821
pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9822
if (!pcinfo->valid)
9823
return 0;
9824
9825
pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo.v2;
9826
p += scnprintf(p, end - p,
9827
" %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
9828
"[cycle_cnt]",
9829
le16_to_cpu(pcysta_le32->cycles),
9830
le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL]),
9831
le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_ALL_OK]),
9832
le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_SLOT]),
9833
le32_to_cpu(pcysta_le32->bcn_cnt[CXBCN_BT_OK]));
9834
9835
for (i = 0; i < CXST_MAX; i++) {
9836
if (!le32_to_cpu(pcysta_le32->slot_cnt[i]))
9837
continue;
9838
p += scnprintf(p, end - p, ", %s:%d", id_to_slot((u32)i),
9839
le32_to_cpu(pcysta_le32->slot_cnt[i]));
9840
}
9841
9842
if (dm->tdma_now.rxflctrl) {
9843
p += scnprintf(p, end - p, ", leak_rx:%d",
9844
le32_to_cpu(pcysta_le32->leakrx_cnt));
9845
}
9846
9847
if (le32_to_cpu(pcysta_le32->collision_cnt)) {
9848
p += scnprintf(p, end - p, ", collision:%d",
9849
le32_to_cpu(pcysta_le32->collision_cnt));
9850
}
9851
9852
if (le32_to_cpu(pcysta_le32->skip_cnt)) {
9853
p += scnprintf(p, end - p, ", skip:%d",
9854
le32_to_cpu(pcysta_le32->skip_cnt));
9855
}
9856
p += scnprintf(p, end - p, "\n");
9857
9858
p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9859
"[cycle_time]",
9860
le16_to_cpu(pcysta_le32->tavg_cycle[CXT_WL]),
9861
le16_to_cpu(pcysta_le32->tavg_cycle[CXT_BT]),
9862
le16_to_cpu(pcysta_le32->tavg_lk) / 1000,
9863
le16_to_cpu(pcysta_le32->tavg_lk) % 1000);
9864
p += scnprintf(p, end - p, ", max_t[wl:%d/bt:%d/lk:%d.%03d]",
9865
le16_to_cpu(pcysta_le32->tmax_cycle[CXT_WL]),
9866
le16_to_cpu(pcysta_le32->tmax_cycle[CXT_BT]),
9867
le16_to_cpu(pcysta_le32->tmax_lk) / 1000,
9868
le16_to_cpu(pcysta_le32->tmax_lk) % 1000);
9869
p += scnprintf(p, end - p, ", maxdiff_t[wl:%d/bt:%d]\n",
9870
le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_WL]),
9871
le16_to_cpu(pcysta_le32->tmaxdiff_cycle[CXT_BT]));
9872
9873
if (le16_to_cpu(pcysta_le32->cycles) <= 1)
9874
goto out;
9875
9876
/* 1 cycle record 1 wl-slot and 1 bt-slot */
9877
slot_pair = BTC_CYCLE_SLOT_MAX / 2;
9878
9879
if (le16_to_cpu(pcysta_le32->cycles) <= slot_pair)
9880
c_begin = 1;
9881
else
9882
c_begin = le16_to_cpu(pcysta_le32->cycles) - slot_pair + 1;
9883
9884
c_end = le16_to_cpu(pcysta_le32->cycles);
9885
9886
for (cycle = c_begin; cycle <= c_end; cycle++) {
9887
cnt++;
9888
store_index = ((cycle - 1) % slot_pair) * 2;
9889
9890
if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 1)
9891
p += scnprintf(p, end - p,
9892
" %-15s : ->b%02d->w%02d",
9893
"[cycle_step]",
9894
le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
9895
le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
9896
else
9897
p += scnprintf(p, end - p,
9898
"->b%02d->w%02d",
9899
le16_to_cpu(pcysta_le32->tslot_cycle[store_index]),
9900
le16_to_cpu(pcysta_le32->tslot_cycle[store_index + 1]));
9901
if (cnt % (BTC_CYCLE_SLOT_MAX / 4) == 0 || cnt == c_end)
9902
p += scnprintf(p, end - p, "\n");
9903
}
9904
9905
if (a2dp->exist) {
9906
p += scnprintf(p, end - p,
9907
" %-15s : a2dp_ept:%d, a2dp_late:%d",
9908
"[a2dp_t_sta]",
9909
le16_to_cpu(pcysta_le32->a2dpept),
9910
le16_to_cpu(pcysta_le32->a2dpeptto));
9911
9912
p += scnprintf(p, end - p,
9913
", avg_t:%d, max_t:%d",
9914
le16_to_cpu(pcysta_le32->tavg_a2dpept),
9915
le16_to_cpu(pcysta_le32->tmax_a2dpept));
9916
r.val = dm->tdma_now.rxflctrl;
9917
9918
if (r.type && r.tgln_n) {
9919
p += scnprintf(p, end - p,
9920
", cycle[PSTDMA:%d/TDMA:%d], ",
9921
le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_ON]),
9922
le16_to_cpu(pcysta_le32->cycles_a2dp[CXT_FLCTRL_OFF]));
9923
9924
p += scnprintf(p, end - p,
9925
"avg_t[PSTDMA:%d/TDMA:%d], ",
9926
le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_ON]),
9927
le16_to_cpu(pcysta_le32->tavg_a2dp[CXT_FLCTRL_OFF]));
9928
9929
p += scnprintf(p, end - p,
9930
"max_t[PSTDMA:%d/TDMA:%d]",
9931
le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_ON]),
9932
le16_to_cpu(pcysta_le32->tmax_a2dp[CXT_FLCTRL_OFF]));
9933
}
9934
p += scnprintf(p, end - p, "\n");
9935
}
9936
9937
out:
9938
return p - buf;
9939
}
9940
9941
static int _show_fbtc_cysta_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
9942
{
9943
struct rtw89_btc *btc = &rtwdev->btc;
9944
struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
9945
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
9946
struct rtw89_btc_dm *dm = &btc->dm;
9947
struct rtw89_btc_fbtc_a2dp_trx_stat *a2dp_trx;
9948
struct rtw89_btc_fbtc_cysta_v3 *pcysta;
9949
struct rtw89_btc_rpt_cmn_info *pcinfo;
9950
u8 i, cnt = 0, slot_pair, divide_cnt;
9951
u16 cycle, c_begin, c_end, store_index;
9952
char *p = buf, *end = buf + bufsz;
9953
9954
pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
9955
if (!pcinfo->valid)
9956
return 0;
9957
9958
pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v3;
9959
p += scnprintf(p, end - p,
9960
" %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
9961
"[cycle_cnt]",
9962
le16_to_cpu(pcysta->cycles),
9963
le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
9964
le32_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
9965
le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
9966
le32_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
9967
9968
for (i = 0; i < CXST_MAX; i++) {
9969
if (!le32_to_cpu(pcysta->slot_cnt[i]))
9970
continue;
9971
9972
p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
9973
le32_to_cpu(pcysta->slot_cnt[i]));
9974
}
9975
9976
if (dm->tdma_now.rxflctrl)
9977
p += scnprintf(p, end - p, ", leak_rx:%d",
9978
le32_to_cpu(pcysta->leak_slot.cnt_rximr));
9979
9980
if (le32_to_cpu(pcysta->collision_cnt))
9981
p += scnprintf(p, end - p, ", collision:%d",
9982
le32_to_cpu(pcysta->collision_cnt));
9983
9984
if (le32_to_cpu(pcysta->skip_cnt))
9985
p += scnprintf(p, end - p, ", skip:%d",
9986
le32_to_cpu(pcysta->skip_cnt));
9987
9988
p += scnprintf(p, end - p, "\n");
9989
9990
p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
9991
"[cycle_time]",
9992
le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
9993
le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
9994
le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
9995
le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
9996
p += scnprintf(p, end - p,
9997
", max_t[wl:%d/bt:%d/lk:%d.%03d]",
9998
le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
9999
le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
10000
le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
10001
le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
10002
p += scnprintf(p, end - p,
10003
", maxdiff_t[wl:%d/bt:%d]\n",
10004
le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
10005
le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
10006
10007
cycle = le16_to_cpu(pcysta->cycles);
10008
if (cycle <= 1)
10009
goto out;
10010
10011
/* 1 cycle record 1 wl-slot and 1 bt-slot */
10012
slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10013
10014
if (cycle <= slot_pair)
10015
c_begin = 1;
10016
else
10017
c_begin = cycle - slot_pair + 1;
10018
10019
c_end = cycle;
10020
10021
if (a2dp->exist)
10022
divide_cnt = 3;
10023
else
10024
divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
10025
10026
for (cycle = c_begin; cycle <= c_end; cycle++) {
10027
cnt++;
10028
store_index = ((cycle - 1) % slot_pair) * 2;
10029
10030
if (cnt % divide_cnt == 1)
10031
p += scnprintf(p, end - p, " %-15s : ",
10032
"[cycle_step]");
10033
10034
p += scnprintf(p, end - p, "->b%02d",
10035
le16_to_cpu(pcysta->slot_step_time[store_index]));
10036
if (a2dp->exist) {
10037
a2dp_trx = &pcysta->a2dp_trx[store_index];
10038
p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10039
a2dp_trx->empty_cnt,
10040
a2dp_trx->retry_cnt,
10041
a2dp_trx->tx_rate ? 3 : 2,
10042
a2dp_trx->tx_cnt,
10043
a2dp_trx->ack_cnt,
10044
a2dp_trx->nack_cnt);
10045
}
10046
p += scnprintf(p, end - p, "->w%02d",
10047
le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
10048
if (a2dp->exist) {
10049
a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
10050
p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10051
a2dp_trx->empty_cnt,
10052
a2dp_trx->retry_cnt,
10053
a2dp_trx->tx_rate ? 3 : 2,
10054
a2dp_trx->tx_cnt,
10055
a2dp_trx->ack_cnt,
10056
a2dp_trx->nack_cnt);
10057
}
10058
if (cnt % divide_cnt == 0 || cnt == c_end)
10059
p += scnprintf(p, end - p, "\n");
10060
}
10061
10062
if (a2dp->exist) {
10063
p += scnprintf(p, end - p,
10064
" %-15s : a2dp_ept:%d, a2dp_late:%d",
10065
"[a2dp_t_sta]",
10066
le16_to_cpu(pcysta->a2dp_ept.cnt),
10067
le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
10068
10069
p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10070
le16_to_cpu(pcysta->a2dp_ept.tavg),
10071
le16_to_cpu(pcysta->a2dp_ept.tmax));
10072
10073
p += scnprintf(p, end - p, "\n");
10074
}
10075
10076
out:
10077
return p - buf;
10078
}
10079
10080
static int _show_fbtc_cysta_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10081
{
10082
struct rtw89_btc *btc = &rtwdev->btc;
10083
struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
10084
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10085
struct rtw89_btc_dm *dm = &btc->dm;
10086
struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
10087
struct rtw89_btc_fbtc_cysta_v4 *pcysta;
10088
struct rtw89_btc_rpt_cmn_info *pcinfo;
10089
u8 i, cnt = 0, slot_pair, divide_cnt;
10090
u16 cycle, c_begin, c_end, store_index;
10091
char *p = buf, *end = buf + bufsz;
10092
10093
pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10094
if (!pcinfo->valid)
10095
return 0;
10096
10097
pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v4;
10098
p += scnprintf(p, end - p,
10099
" %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
10100
"[cycle_cnt]",
10101
le16_to_cpu(pcysta->cycles),
10102
le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
10103
le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
10104
le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
10105
le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
10106
10107
for (i = 0; i < CXST_MAX; i++) {
10108
if (!le16_to_cpu(pcysta->slot_cnt[i]))
10109
continue;
10110
10111
p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
10112
le16_to_cpu(pcysta->slot_cnt[i]));
10113
}
10114
10115
if (dm->tdma_now.rxflctrl)
10116
p += scnprintf(p, end - p, ", leak_rx:%d",
10117
le32_to_cpu(pcysta->leak_slot.cnt_rximr));
10118
10119
if (pcysta->collision_cnt)
10120
p += scnprintf(p, end - p, ", collision:%d",
10121
pcysta->collision_cnt);
10122
10123
if (le16_to_cpu(pcysta->skip_cnt))
10124
p += scnprintf(p, end - p, ", skip:%d",
10125
le16_to_cpu(pcysta->skip_cnt));
10126
10127
p += scnprintf(p, end - p, "\n");
10128
10129
p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
10130
"[cycle_time]",
10131
le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
10132
le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
10133
le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
10134
le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
10135
p += scnprintf(p, end - p,
10136
", max_t[wl:%d/bt:%d/lk:%d.%03d]",
10137
le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
10138
le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
10139
le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
10140
le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
10141
p += scnprintf(p, end - p,
10142
", maxdiff_t[wl:%d/bt:%d]\n",
10143
le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_WL]),
10144
le16_to_cpu(pcysta->cycle_time.tmaxdiff[CXT_BT]));
10145
10146
cycle = le16_to_cpu(pcysta->cycles);
10147
if (cycle <= 1)
10148
goto out;
10149
10150
/* 1 cycle record 1 wl-slot and 1 bt-slot */
10151
slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10152
10153
if (cycle <= slot_pair)
10154
c_begin = 1;
10155
else
10156
c_begin = cycle - slot_pair + 1;
10157
10158
c_end = cycle;
10159
10160
if (a2dp->exist)
10161
divide_cnt = 3;
10162
else
10163
divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
10164
10165
for (cycle = c_begin; cycle <= c_end; cycle++) {
10166
cnt++;
10167
store_index = ((cycle - 1) % slot_pair) * 2;
10168
10169
if (cnt % divide_cnt == 1)
10170
p += scnprintf(p, end - p, " %-15s : ",
10171
"[cycle_step]");
10172
10173
p += scnprintf(p, end - p, "->b%02d",
10174
le16_to_cpu(pcysta->slot_step_time[store_index]));
10175
if (a2dp->exist) {
10176
a2dp_trx = &pcysta->a2dp_trx[store_index];
10177
p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10178
a2dp_trx->empty_cnt,
10179
a2dp_trx->retry_cnt,
10180
a2dp_trx->tx_rate ? 3 : 2,
10181
a2dp_trx->tx_cnt,
10182
a2dp_trx->ack_cnt,
10183
a2dp_trx->nack_cnt);
10184
}
10185
p += scnprintf(p, end - p, "->w%02d",
10186
le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
10187
if (a2dp->exist) {
10188
a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
10189
p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10190
a2dp_trx->empty_cnt,
10191
a2dp_trx->retry_cnt,
10192
a2dp_trx->tx_rate ? 3 : 2,
10193
a2dp_trx->tx_cnt,
10194
a2dp_trx->ack_cnt,
10195
a2dp_trx->nack_cnt);
10196
}
10197
if (cnt % divide_cnt == 0 || cnt == c_end)
10198
p += scnprintf(p, end - p, "\n");
10199
}
10200
10201
if (a2dp->exist) {
10202
p += scnprintf(p, end - p,
10203
" %-15s : a2dp_ept:%d, a2dp_late:%d",
10204
"[a2dp_t_sta]",
10205
le16_to_cpu(pcysta->a2dp_ept.cnt),
10206
le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
10207
10208
p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10209
le16_to_cpu(pcysta->a2dp_ept.tavg),
10210
le16_to_cpu(pcysta->a2dp_ept.tmax));
10211
10212
p += scnprintf(p, end - p, "\n");
10213
}
10214
10215
out:
10216
return p - buf;
10217
}
10218
10219
static int _show_fbtc_cysta_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10220
{
10221
struct rtw89_btc *btc = &rtwdev->btc;
10222
struct rtw89_btc_bt_a2dp_desc *a2dp = &btc->cx.bt.link_info.a2dp_desc;
10223
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10224
struct rtw89_btc_dm *dm = &btc->dm;
10225
struct rtw89_btc_fbtc_a2dp_trx_stat_v4 *a2dp_trx;
10226
struct rtw89_btc_fbtc_cysta_v5 *pcysta;
10227
struct rtw89_btc_rpt_cmn_info *pcinfo;
10228
u8 i, cnt = 0, slot_pair, divide_cnt;
10229
u16 cycle, c_begin, c_end, store_index;
10230
char *p = buf, *end = buf + bufsz;
10231
10232
pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10233
if (!pcinfo->valid)
10234
return 0;
10235
10236
pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v5;
10237
p += scnprintf(p, end - p,
10238
" %-15s : cycle:%d, bcn[all:%d/all_ok:%d/bt:%d/bt_ok:%d]",
10239
"[cycle_cnt]",
10240
le16_to_cpu(pcysta->cycles),
10241
le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
10242
le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
10243
le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
10244
le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
10245
10246
for (i = 0; i < CXST_MAX; i++) {
10247
if (!le16_to_cpu(pcysta->slot_cnt[i]))
10248
continue;
10249
10250
p += scnprintf(p, end - p, ", %s:%d", id_to_slot(i),
10251
le16_to_cpu(pcysta->slot_cnt[i]));
10252
}
10253
10254
if (dm->tdma_now.rxflctrl)
10255
p += scnprintf(p, end - p, ", leak_rx:%d",
10256
le32_to_cpu(pcysta->leak_slot.cnt_rximr));
10257
10258
if (pcysta->collision_cnt)
10259
p += scnprintf(p, end - p, ", collision:%d",
10260
pcysta->collision_cnt);
10261
10262
if (le16_to_cpu(pcysta->skip_cnt))
10263
p += scnprintf(p, end - p, ", skip:%d",
10264
le16_to_cpu(pcysta->skip_cnt));
10265
10266
p += scnprintf(p, end - p, "\n");
10267
10268
p += scnprintf(p, end - p, " %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
10269
"[cycle_time]",
10270
le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
10271
le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
10272
le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
10273
le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
10274
p += scnprintf(p, end - p,
10275
", max_t[wl:%d/bt:%d/lk:%d.%03d]\n",
10276
le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
10277
le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
10278
le16_to_cpu(pcysta->leak_slot.tmax) / 1000,
10279
le16_to_cpu(pcysta->leak_slot.tmax) % 1000);
10280
10281
cycle = le16_to_cpu(pcysta->cycles);
10282
if (cycle <= 1)
10283
goto out;
10284
10285
/* 1 cycle record 1 wl-slot and 1 bt-slot */
10286
slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10287
10288
if (cycle <= slot_pair)
10289
c_begin = 1;
10290
else
10291
c_begin = cycle - slot_pair + 1;
10292
10293
c_end = cycle;
10294
10295
if (a2dp->exist)
10296
divide_cnt = 3;
10297
else
10298
divide_cnt = BTC_CYCLE_SLOT_MAX / 4;
10299
10300
if (c_begin > c_end)
10301
goto out;
10302
10303
for (cycle = c_begin; cycle <= c_end; cycle++) {
10304
cnt++;
10305
store_index = ((cycle - 1) % slot_pair) * 2;
10306
10307
if (cnt % divide_cnt == 1)
10308
p += scnprintf(p, end - p, " %-15s : ",
10309
"[cycle_step]");
10310
10311
p += scnprintf(p, end - p, "->b%02d",
10312
le16_to_cpu(pcysta->slot_step_time[store_index]));
10313
if (a2dp->exist) {
10314
a2dp_trx = &pcysta->a2dp_trx[store_index];
10315
p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10316
a2dp_trx->empty_cnt,
10317
a2dp_trx->retry_cnt,
10318
a2dp_trx->tx_rate ? 3 : 2,
10319
a2dp_trx->tx_cnt,
10320
a2dp_trx->ack_cnt,
10321
a2dp_trx->nack_cnt);
10322
}
10323
p += scnprintf(p, end - p, "->w%02d",
10324
le16_to_cpu(pcysta->slot_step_time[store_index + 1]));
10325
if (a2dp->exist) {
10326
a2dp_trx = &pcysta->a2dp_trx[store_index + 1];
10327
p += scnprintf(p, end - p, "(%d/%d/%dM/%d/%d/%d)",
10328
a2dp_trx->empty_cnt,
10329
a2dp_trx->retry_cnt,
10330
a2dp_trx->tx_rate ? 3 : 2,
10331
a2dp_trx->tx_cnt,
10332
a2dp_trx->ack_cnt,
10333
a2dp_trx->nack_cnt);
10334
}
10335
if (cnt % divide_cnt == 0 || cnt == c_end)
10336
p += scnprintf(p, end - p, "\n");
10337
}
10338
10339
if (a2dp->exist) {
10340
p += scnprintf(p, end - p,
10341
" %-15s : a2dp_ept:%d, a2dp_late:%d",
10342
"[a2dp_t_sta]",
10343
le16_to_cpu(pcysta->a2dp_ept.cnt),
10344
le16_to_cpu(pcysta->a2dp_ept.cnt_timeout));
10345
10346
p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10347
le16_to_cpu(pcysta->a2dp_ept.tavg),
10348
le16_to_cpu(pcysta->a2dp_ept.tmax));
10349
10350
p += scnprintf(p, end - p, "\n");
10351
}
10352
10353
out:
10354
return p - buf;
10355
}
10356
10357
static int _show_fbtc_cysta_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10358
{
10359
struct rtw89_btc_bt_info *bt = &rtwdev->btc.cx.bt;
10360
struct rtw89_btc_bt_a2dp_desc *a2dp = &bt->link_info.a2dp_desc;
10361
struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
10362
struct rtw89_btc_fbtc_cysta_v7 *pcysta = NULL;
10363
struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
10364
struct rtw89_btc_rpt_cmn_info *pcinfo;
10365
char *p = buf, *end = buf + bufsz;
10366
u16 cycle, c_begin, c_end, s_id;
10367
u8 i, cnt = 0, divide_cnt;
10368
u8 slot_pair;
10369
10370
pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
10371
if (!pcinfo->valid)
10372
return 0;
10373
10374
pcysta = &pfwinfo->rpt_fbtc_cysta.finfo.v7;
10375
p += scnprintf(p, end - p, "\n %-15s : cycle:%d", "[slot_stat]",
10376
le16_to_cpu(pcysta->cycles));
10377
10378
for (i = 0; i < CXST_MAX; i++) {
10379
if (!le16_to_cpu(pcysta->slot_cnt[i]))
10380
continue;
10381
p += scnprintf(p, end - p, ", %s:%d",
10382
id_to_slot(i),
10383
le16_to_cpu(pcysta->slot_cnt[i]));
10384
}
10385
10386
if (dm->tdma_now.rxflctrl)
10387
p += scnprintf(p, end - p, ", leak_rx:%d",
10388
le32_to_cpu(pcysta->leak_slot.cnt_rximr));
10389
10390
if (pcysta->collision_cnt)
10391
p += scnprintf(p, end - p, ", collision:%d",
10392
pcysta->collision_cnt);
10393
10394
if (pcysta->skip_cnt)
10395
p += scnprintf(p, end - p, ", skip:%d",
10396
le16_to_cpu(pcysta->skip_cnt));
10397
10398
p += scnprintf(p, end - p,
10399
"\n\r %-15s : avg_t[wl:%d/bt:%d/lk:%d.%03d]",
10400
"[cycle_stat]",
10401
le16_to_cpu(pcysta->cycle_time.tavg[CXT_WL]),
10402
le16_to_cpu(pcysta->cycle_time.tavg[CXT_BT]),
10403
le16_to_cpu(pcysta->leak_slot.tavg) / 1000,
10404
le16_to_cpu(pcysta->leak_slot.tavg) % 1000);
10405
p += scnprintf(p, end - p,
10406
", max_t[wl:%d/bt:%d(>%dms:%d)/lk:%d.%03d]",
10407
le16_to_cpu(pcysta->cycle_time.tmax[CXT_WL]),
10408
le16_to_cpu(pcysta->cycle_time.tmax[CXT_BT]),
10409
dm->bt_slot_flood, dm->cnt_dm[BTC_DCNT_BT_SLOT_FLOOD],
10410
le16_to_cpu(pcysta->leak_slot.tamx) / 1000,
10411
le16_to_cpu(pcysta->leak_slot.tamx) % 1000);
10412
p += scnprintf(p, end - p, ", bcn[all:%d/ok:%d/in_bt:%d/in_bt_ok:%d]",
10413
le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL]),
10414
le16_to_cpu(pcysta->bcn_cnt[CXBCN_ALL_OK]),
10415
le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_SLOT]),
10416
le16_to_cpu(pcysta->bcn_cnt[CXBCN_BT_OK]));
10417
10418
if (a2dp->exist) {
10419
p += scnprintf(p, end - p,
10420
"\n\r %-15s : a2dp_ept:%d, a2dp_late:%d(streak 2S:%d/max:%d)",
10421
"[a2dp_stat]",
10422
le16_to_cpu(pcysta->a2dp_ept.cnt),
10423
le16_to_cpu(pcysta->a2dp_ept.cnt_timeout),
10424
a2dp->no_empty_streak_2s,
10425
a2dp->no_empty_streak_max);
10426
10427
p += scnprintf(p, end - p, ", avg_t:%d, max_t:%d",
10428
le16_to_cpu(pcysta->a2dp_ept.tavg),
10429
le16_to_cpu(pcysta->a2dp_ept.tmax));
10430
}
10431
10432
if (le16_to_cpu(pcysta->cycles) <= 1)
10433
goto out;
10434
10435
/* 1 cycle = 1 wl-slot + 1 bt-slot */
10436
slot_pair = BTC_CYCLE_SLOT_MAX / 2;
10437
10438
if (le16_to_cpu(pcysta->cycles) <= slot_pair)
10439
c_begin = 1;
10440
else
10441
c_begin = le16_to_cpu(pcysta->cycles) - slot_pair + 1;
10442
10443
c_end = le16_to_cpu(pcysta->cycles);
10444
10445
if (a2dp->exist)
10446
divide_cnt = 2;
10447
else
10448
divide_cnt = 6;
10449
10450
if (c_begin > c_end)
10451
goto out;
10452
10453
for (cycle = c_begin; cycle <= c_end; cycle++) {
10454
cnt++;
10455
s_id = ((cycle - 1) % slot_pair) * 2;
10456
10457
if (cnt % divide_cnt == 1) {
10458
if (a2dp->exist)
10459
p += scnprintf(p, end - p, "\n\r %-15s : ",
10460
"[slotT_wermtan]");
10461
else
10462
p += scnprintf(p, end - p, "\n\r %-15s : ",
10463
"[slotT_rxerr]");
10464
}
10465
10466
p += scnprintf(p, end - p, "->b%d",
10467
le16_to_cpu(pcysta->slot_step_time[s_id]));
10468
10469
if (a2dp->exist)
10470
p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)",
10471
pcysta->wl_rx_err_ratio[s_id],
10472
pcysta->a2dp_trx[s_id].empty_cnt,
10473
pcysta->a2dp_trx[s_id].retry_cnt,
10474
(pcysta->a2dp_trx[s_id].tx_rate ? 3 : 2),
10475
pcysta->a2dp_trx[s_id].tx_cnt,
10476
pcysta->a2dp_trx[s_id].ack_cnt,
10477
pcysta->a2dp_trx[s_id].nack_cnt);
10478
else
10479
p += scnprintf(p, end - p, "(%d)",
10480
pcysta->wl_rx_err_ratio[s_id]);
10481
10482
p += scnprintf(p, end - p, "->w%d",
10483
le16_to_cpu(pcysta->slot_step_time[s_id + 1]));
10484
10485
if (a2dp->exist)
10486
p += scnprintf(p, end - p, "(%d/%d/%d/%dM/%d/%d/%d)",
10487
pcysta->wl_rx_err_ratio[s_id + 1],
10488
pcysta->a2dp_trx[s_id + 1].empty_cnt,
10489
pcysta->a2dp_trx[s_id + 1].retry_cnt,
10490
(pcysta->a2dp_trx[s_id + 1].tx_rate ? 3 : 2),
10491
pcysta->a2dp_trx[s_id + 1].tx_cnt,
10492
pcysta->a2dp_trx[s_id + 1].ack_cnt,
10493
pcysta->a2dp_trx[s_id + 1].nack_cnt);
10494
else
10495
p += scnprintf(p, end - p, "(%d)",
10496
pcysta->wl_rx_err_ratio[s_id + 1]);
10497
}
10498
10499
out:
10500
return p - buf;
10501
}
10502
10503
static int _show_fbtc_nullsta(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10504
{
10505
struct rtw89_btc *btc = &rtwdev->btc;
10506
const struct rtw89_btc_ver *ver = btc->ver;
10507
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10508
struct rtw89_btc_rpt_cmn_info *pcinfo;
10509
union rtw89_btc_fbtc_cynullsta_info *ns;
10510
char *p = buf, *end = buf + bufsz;
10511
u8 i = 0;
10512
10513
if (!btc->dm.tdma_now.rxflctrl)
10514
return 0;
10515
10516
pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
10517
if (!pcinfo->valid)
10518
return 0;
10519
10520
ns = &pfwinfo->rpt_fbtc_nullsta.finfo;
10521
if (ver->fcxnullsta == 1) {
10522
for (i = 0; i < 2; i++) {
10523
p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]");
10524
p += scnprintf(p, end - p, "null-%d", i);
10525
p += scnprintf(p, end - p, "[ok:%d/",
10526
le32_to_cpu(ns->v1.result[i][1]));
10527
p += scnprintf(p, end - p, "fail:%d/",
10528
le32_to_cpu(ns->v1.result[i][0]));
10529
p += scnprintf(p, end - p, "on_time:%d/",
10530
le32_to_cpu(ns->v1.result[i][2]));
10531
p += scnprintf(p, end - p, "retry:%d/",
10532
le32_to_cpu(ns->v1.result[i][3]));
10533
p += scnprintf(p, end - p, "avg_t:%d.%03d/",
10534
le32_to_cpu(ns->v1.avg_t[i]) / 1000,
10535
le32_to_cpu(ns->v1.avg_t[i]) % 1000);
10536
p += scnprintf(p, end - p, "max_t:%d.%03d]",
10537
le32_to_cpu(ns->v1.max_t[i]) / 1000,
10538
le32_to_cpu(ns->v1.max_t[i]) % 1000);
10539
}
10540
} else if (ver->fcxnullsta == 7) {
10541
for (i = 0; i < 2; i++) {
10542
p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]");
10543
p += scnprintf(p, end - p, "null-%d", i);
10544
p += scnprintf(p, end - p, "[Tx:%d/",
10545
le32_to_cpu(ns->v7.result[i][4]));
10546
p += scnprintf(p, end - p, "[ok:%d/",
10547
le32_to_cpu(ns->v7.result[i][1]));
10548
p += scnprintf(p, end - p, "fail:%d/",
10549
le32_to_cpu(ns->v7.result[i][0]));
10550
p += scnprintf(p, end - p, "on_time:%d/",
10551
le32_to_cpu(ns->v7.result[i][2]));
10552
p += scnprintf(p, end - p, "retry:%d/",
10553
le32_to_cpu(ns->v7.result[i][3]));
10554
p += scnprintf(p, end - p, "avg_t:%d.%03d/",
10555
le32_to_cpu(ns->v7.tavg[i]) / 1000,
10556
le32_to_cpu(ns->v7.tavg[i]) % 1000);
10557
p += scnprintf(p, end - p, "max_t:%d.%03d]",
10558
le32_to_cpu(ns->v7.tmax[i]) / 1000,
10559
le32_to_cpu(ns->v7.tmax[i]) % 1000);
10560
}
10561
} else {
10562
for (i = 0; i < 2; i++) {
10563
p += scnprintf(p, end - p, " %-15s : ", "\n[NULL-STA]");
10564
p += scnprintf(p, end - p, "null-%d", i);
10565
p += scnprintf(p, end - p, "[Tx:%d/",
10566
le32_to_cpu(ns->v2.result[i][4]));
10567
p += scnprintf(p, end - p, "[ok:%d/",
10568
le32_to_cpu(ns->v2.result[i][1]));
10569
p += scnprintf(p, end - p, "fail:%d/",
10570
le32_to_cpu(ns->v2.result[i][0]));
10571
p += scnprintf(p, end - p, "on_time:%d/",
10572
le32_to_cpu(ns->v2.result[i][2]));
10573
p += scnprintf(p, end - p, "retry:%d/",
10574
le32_to_cpu(ns->v2.result[i][3]));
10575
p += scnprintf(p, end - p, "avg_t:%d.%03d/",
10576
le32_to_cpu(ns->v2.avg_t[i]) / 1000,
10577
le32_to_cpu(ns->v2.avg_t[i]) % 1000);
10578
p += scnprintf(p, end - p, "max_t:%d.%03d]",
10579
le32_to_cpu(ns->v2.max_t[i]) / 1000,
10580
le32_to_cpu(ns->v2.max_t[i]) % 1000);
10581
}
10582
}
10583
10584
return p - buf;
10585
}
10586
10587
static int _show_fbtc_step_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10588
{
10589
struct rtw89_btc *btc = &rtwdev->btc;
10590
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10591
struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10592
struct rtw89_btc_fbtc_steps_v2 *pstep = NULL;
10593
const struct rtw89_btc_ver *ver = btc->ver;
10594
char *p = buf, *end = buf + bufsz;
10595
u8 type, val, cnt = 0, state = 0;
10596
bool outloop = false;
10597
u16 i, diff_t, n_start = 0, n_stop = 0;
10598
u16 pos_old, pos_new, trace_step;
10599
10600
pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
10601
if (!pcinfo->valid)
10602
return 0;
10603
10604
pstep = &pfwinfo->rpt_fbtc_step.finfo.v2;
10605
pos_old = le16_to_cpu(pstep->pos_old);
10606
pos_new = le16_to_cpu(pstep->pos_new);
10607
10608
if (pcinfo->req_fver != pstep->fver)
10609
return 0;
10610
10611
/* store step info by using ring instead of FIFO*/
10612
do {
10613
switch (state) {
10614
case 0:
10615
if (ver->fcxctrl == 7 || ver->fcxctrl == 1)
10616
trace_step = 50;
10617
else
10618
trace_step = btc->ctrl.ctrl.trace_step;
10619
10620
n_start = pos_old;
10621
if (pos_new >= pos_old)
10622
n_stop = pos_new;
10623
else
10624
n_stop = trace_step - 1;
10625
10626
state = 1;
10627
break;
10628
case 1:
10629
for (i = n_start; i <= n_stop; i++) {
10630
type = pstep->step[i].type;
10631
val = pstep->step[i].val;
10632
diff_t = le16_to_cpu(pstep->step[i].difft);
10633
10634
if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
10635
continue;
10636
10637
if (cnt % 10 == 0)
10638
p += scnprintf(p, end - p,
10639
" %-15s : ", "[steps]");
10640
10641
p += scnprintf(p, end - p,
10642
"-> %s(%02d)(%02d)",
10643
(type == CXSTEP_SLOT ? "SLT" :
10644
"EVT"), (u32)val, diff_t);
10645
if (cnt % 10 == 9)
10646
p += scnprintf(p, end - p, "\n");
10647
cnt++;
10648
}
10649
10650
state = 2;
10651
break;
10652
case 2:
10653
if (pos_new < pos_old && n_start != 0) {
10654
n_start = 0;
10655
n_stop = pos_new;
10656
state = 1;
10657
} else {
10658
outloop = true;
10659
}
10660
break;
10661
}
10662
} while (!outloop);
10663
10664
return p - buf;
10665
}
10666
10667
static int _show_fbtc_step_v3(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10668
{
10669
struct rtw89_btc *btc = &rtwdev->btc;
10670
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10671
struct rtw89_btc_rpt_cmn_info *pcinfo;
10672
struct rtw89_btc_fbtc_steps_v3 *pstep;
10673
u32 i, n_begin, n_end, array_idx, cnt = 0;
10674
char *p = buf, *end = buf + bufsz;
10675
u8 type, val;
10676
u16 diff_t;
10677
10678
if ((pfwinfo->rpt_en_map &
10679
rtw89_btc_fw_rpt_ver(rtwdev, RPT_EN_FW_STEP_INFO)) == 0)
10680
return 0;
10681
10682
pcinfo = &pfwinfo->rpt_fbtc_step.cinfo;
10683
if (!pcinfo->valid)
10684
return 0;
10685
10686
pstep = &pfwinfo->rpt_fbtc_step.finfo.v3;
10687
if (pcinfo->req_fver != pstep->fver)
10688
return 0;
10689
10690
if (le32_to_cpu(pstep->cnt) <= FCXDEF_STEP)
10691
n_begin = 1;
10692
else
10693
n_begin = le32_to_cpu(pstep->cnt) - FCXDEF_STEP + 1;
10694
10695
n_end = le32_to_cpu(pstep->cnt);
10696
10697
if (n_begin > n_end)
10698
return 0;
10699
10700
/* restore step info by using ring instead of FIFO */
10701
for (i = n_begin; i <= n_end; i++) {
10702
array_idx = (i - 1) % FCXDEF_STEP;
10703
type = pstep->step[array_idx].type;
10704
val = pstep->step[array_idx].val;
10705
diff_t = le16_to_cpu(pstep->step[array_idx].difft);
10706
10707
if (type == CXSTEP_NONE || type >= CXSTEP_MAX)
10708
continue;
10709
10710
if (cnt % 10 == 0)
10711
p += scnprintf(p, end - p, " %-15s : ", "[steps]");
10712
10713
p += scnprintf(p, end - p, "-> %s(%02d)",
10714
(type == CXSTEP_SLOT ?
10715
id_to_slot((u32)val) :
10716
id_to_evt((u32)val)), diff_t);
10717
10718
if (cnt % 10 == 9)
10719
p += scnprintf(p, end - p, "\n");
10720
10721
cnt++;
10722
}
10723
10724
return p - buf;
10725
}
10726
10727
static int _show_fw_dm_msg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10728
{
10729
struct rtw89_btc *btc = &rtwdev->btc;
10730
const struct rtw89_btc_ver *ver = btc->ver;
10731
char *p = buf, *end = buf + bufsz;
10732
10733
if (!(btc->dm.coex_info_map & BTC_COEX_INFO_DM))
10734
goto out;
10735
10736
p += _show_error(rtwdev, p, end - p);
10737
p += _show_fbtc_tdma(rtwdev, p, end - p);
10738
p += _show_fbtc_slots(rtwdev, p, end - p);
10739
10740
if (ver->fcxcysta == 2)
10741
p += _show_fbtc_cysta_v2(rtwdev, p, end - p);
10742
else if (ver->fcxcysta == 3)
10743
p += _show_fbtc_cysta_v3(rtwdev, p, end - p);
10744
else if (ver->fcxcysta == 4)
10745
p += _show_fbtc_cysta_v4(rtwdev, p, end - p);
10746
else if (ver->fcxcysta == 5)
10747
p += _show_fbtc_cysta_v5(rtwdev, p, end - p);
10748
else if (ver->fcxcysta == 7)
10749
p += _show_fbtc_cysta_v7(rtwdev, p, end - p);
10750
10751
p += _show_fbtc_nullsta(rtwdev, p, end - p);
10752
10753
if (ver->fcxstep == 2)
10754
p += _show_fbtc_step_v2(rtwdev, p, end - p);
10755
else if (ver->fcxstep == 3)
10756
p += _show_fbtc_step_v3(rtwdev, p, end - p);
10757
10758
out:
10759
return p - buf;
10760
}
10761
10762
static void _get_gnt(struct rtw89_dev *rtwdev, struct rtw89_mac_ax_coex_gnt *gnt_cfg)
10763
{
10764
const struct rtw89_chip_info *chip = rtwdev->chip;
10765
struct rtw89_mac_ax_gnt *gnt;
10766
u32 val, status;
10767
10768
if (chip->chip_id == RTL8852A || chip->chip_id == RTL8852B ||
10769
chip->chip_id == RTL8851B || chip->chip_id == RTL8852BT) {
10770
rtw89_mac_read_lte(rtwdev, R_AX_LTE_SW_CFG_1, &val);
10771
rtw89_mac_read_lte(rtwdev, R_AX_GNT_VAL, &status);
10772
10773
gnt = &gnt_cfg->band[0];
10774
gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SW_CTRL);
10775
gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0_STA);
10776
gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SW_CTRL);
10777
gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0_STA);
10778
10779
gnt = &gnt_cfg->band[1];
10780
gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SW_CTRL);
10781
gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1_STA);
10782
gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SW_CTRL);
10783
gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1_STA);
10784
} else if (chip->chip_id == RTL8852C) {
10785
val = rtw89_read32(rtwdev, R_AX_GNT_SW_CTRL);
10786
status = rtw89_read32(rtwdev, R_AX_GNT_VAL_V1);
10787
10788
gnt = &gnt_cfg->band[0];
10789
gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S0_SWCTRL);
10790
gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S0);
10791
gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S0_SWCTRL);
10792
gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S0);
10793
10794
gnt = &gnt_cfg->band[1];
10795
gnt->gnt_bt_sw_en = !!(val & B_AX_GNT_BT_RFC_S1_SWCTRL);
10796
gnt->gnt_bt = !!(status & B_AX_GNT_BT_RFC_S1);
10797
gnt->gnt_wl_sw_en = !!(val & B_AX_GNT_WL_RFC_S1_SWCTRL);
10798
gnt->gnt_wl = !!(status & B_AX_GNT_WL_RFC_S1);
10799
} else {
10800
return;
10801
}
10802
}
10803
10804
static int _show_gpio_dbg(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10805
{
10806
struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
10807
const struct rtw89_btc_ver *ver = rtwdev->btc.ver;
10808
struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10809
union rtw89_btc_fbtc_gpio_dbg *gdbg = NULL;
10810
char *p = buf, *end = buf + bufsz;
10811
u8 *gpio_map, i;
10812
u32 en_map;
10813
10814
pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
10815
gdbg = &rtwdev->btc.fwinfo.rpt_fbtc_gpio_dbg.finfo;
10816
if (!pcinfo->valid) {
10817
rtw89_debug(rtwdev, RTW89_DBG_BTC,
10818
"[BTC], %s(): stop due rpt_fbtc_gpio_dbg.cinfo\n",
10819
__func__);
10820
goto out;
10821
}
10822
10823
if (ver->fcxgpiodbg == 7) {
10824
en_map = le32_to_cpu(gdbg->v7.en_map);
10825
gpio_map = gdbg->v7.gpio_map;
10826
} else {
10827
en_map = le32_to_cpu(gdbg->v1.en_map);
10828
gpio_map = gdbg->v1.gpio_map;
10829
}
10830
10831
if (!en_map)
10832
goto out;
10833
10834
p += scnprintf(p, end - p, " %-15s : enable_map:0x%08x",
10835
"[gpio_dbg]", en_map);
10836
10837
for (i = 0; i < BTC_DBG_MAX1; i++) {
10838
if (!(en_map & BIT(i)))
10839
continue;
10840
p += scnprintf(p, end - p, ", %s->GPIO%d", id_to_gdbg(i),
10841
gpio_map[i]);
10842
}
10843
p += scnprintf(p, end - p, "\n");
10844
10845
out:
10846
return p - buf;
10847
}
10848
10849
static int _show_mreg_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10850
{
10851
const struct rtw89_chip_info *chip = rtwdev->chip;
10852
struct rtw89_btc *btc = &rtwdev->btc;
10853
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10854
struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10855
struct rtw89_btc_fbtc_mreg_val_v1 *pmreg = NULL;
10856
struct rtw89_btc_cx *cx = &btc->cx;
10857
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
10858
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
10859
struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
10860
struct rtw89_mac_ax_gnt gnt;
10861
char *p = buf, *end = buf + bufsz;
10862
u8 i = 0, type = 0, cnt = 0;
10863
u32 val, offset;
10864
10865
if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
10866
return 0;
10867
10868
p += scnprintf(p, end - p, "========== [HW Status] ==========\n");
10869
10870
p += scnprintf(p, end - p,
10871
" %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
10872
"[scoreboard]", wl->scbd,
10873
cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
10874
bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
10875
cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
10876
10877
btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
10878
_get_gnt(rtwdev, &gnt_cfg);
10879
10880
gnt = gnt_cfg.band[0];
10881
p += scnprintf(p, end - p,
10882
" %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], ",
10883
"[gnt_status]",
10884
chip->chip_id == RTL8852C ? "HW" :
10885
btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
10886
gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
10887
gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt);
10888
10889
gnt = gnt_cfg.band[1];
10890
p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
10891
gnt.gnt_wl_sw_en ? "SW" : "HW",
10892
gnt.gnt_wl,
10893
gnt.gnt_bt_sw_en ? "SW" : "HW",
10894
gnt.gnt_bt);
10895
10896
pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
10897
if (!pcinfo->valid) {
10898
rtw89_debug(rtwdev, RTW89_DBG_BTC,
10899
"[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
10900
__func__);
10901
goto out;
10902
}
10903
10904
pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v1;
10905
rtw89_debug(rtwdev, RTW89_DBG_BTC,
10906
"[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
10907
__func__, pmreg->reg_num);
10908
10909
for (i = 0; i < pmreg->reg_num; i++) {
10910
type = (u8)le16_to_cpu(chip->mon_reg[i].type);
10911
offset = le32_to_cpu(chip->mon_reg[i].offset);
10912
val = le32_to_cpu(pmreg->mreg_val[i]);
10913
10914
if (cnt % 6 == 0)
10915
p += scnprintf(p, end - p,
10916
" %-15s : %d_0x%04x=0x%08x",
10917
"[reg]", (u32)type, offset, val);
10918
else
10919
p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x",
10920
(u32)type,
10921
offset, val);
10922
if (cnt % 6 == 5)
10923
p += scnprintf(p, end - p, "\n");
10924
cnt++;
10925
10926
if (i >= pmreg->reg_num)
10927
p += scnprintf(p, end - p, "\n");
10928
}
10929
10930
out:
10931
return p - buf;
10932
}
10933
10934
static int _show_mreg_v2(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
10935
{
10936
const struct rtw89_chip_info *chip = rtwdev->chip;
10937
struct rtw89_btc *btc = &rtwdev->btc;
10938
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
10939
struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
10940
struct rtw89_btc_fbtc_mreg_val_v2 *pmreg = NULL;
10941
struct rtw89_btc_cx *cx = &btc->cx;
10942
struct rtw89_btc_wl_info *wl = &btc->cx.wl;
10943
struct rtw89_btc_bt_info *bt = &btc->cx.bt;
10944
struct rtw89_mac_ax_coex_gnt gnt_cfg = {};
10945
struct rtw89_mac_ax_gnt gnt;
10946
char *p = buf, *end = buf + bufsz;
10947
u8 i = 0, type = 0, cnt = 0;
10948
u32 val, offset;
10949
10950
if (!(btc->dm.coex_info_map & BTC_COEX_INFO_MREG))
10951
return 0;
10952
10953
p += scnprintf(p, end - p, "========== [HW Status] ==========\n");
10954
10955
p += scnprintf(p, end - p,
10956
" %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)\n",
10957
"[scoreboard]", wl->scbd,
10958
cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
10959
bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
10960
cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
10961
10962
btc->dm.pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
10963
_get_gnt(rtwdev, &gnt_cfg);
10964
10965
gnt = gnt_cfg.band[0];
10966
p += scnprintf(p, end - p,
10967
" %-15s : pta_owner:%s, phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d], polut_type:%s",
10968
"[gnt_status]",
10969
chip->chip_id == RTL8852C ? "HW" :
10970
btc->dm.pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
10971
gnt.gnt_wl_sw_en ? "SW" : "HW", gnt.gnt_wl,
10972
gnt.gnt_bt_sw_en ? "SW" : "HW", gnt.gnt_bt,
10973
id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
10974
10975
gnt = gnt_cfg.band[1];
10976
p += scnprintf(p, end - p, "phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]\n",
10977
gnt.gnt_wl_sw_en ? "SW" : "HW",
10978
gnt.gnt_wl,
10979
gnt.gnt_bt_sw_en ? "SW" : "HW",
10980
gnt.gnt_bt);
10981
10982
pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
10983
if (!pcinfo->valid) {
10984
rtw89_debug(rtwdev, RTW89_DBG_BTC,
10985
"[BTC], %s(): stop due rpt_fbtc_mregval.cinfo\n",
10986
__func__);
10987
goto out;
10988
}
10989
10990
pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v2;
10991
rtw89_debug(rtwdev, RTW89_DBG_BTC,
10992
"[BTC], %s(): rpt_fbtc_mregval reg_num = %d\n",
10993
__func__, pmreg->reg_num);
10994
10995
for (i = 0; i < pmreg->reg_num; i++) {
10996
type = (u8)le16_to_cpu(chip->mon_reg[i].type);
10997
offset = le32_to_cpu(chip->mon_reg[i].offset);
10998
val = le32_to_cpu(pmreg->mreg_val[i]);
10999
11000
if (cnt % 6 == 0)
11001
p += scnprintf(p, end - p,
11002
" %-15s : %d_0x%04x=0x%08x",
11003
"[reg]", (u32)type, offset, val);
11004
else
11005
p += scnprintf(p, end - p, ", %d_0x%04x=0x%08x",
11006
(u32)type,
11007
offset, val);
11008
if (cnt % 6 == 5)
11009
p += scnprintf(p, end - p, "\n");
11010
cnt++;
11011
11012
if (i >= pmreg->reg_num)
11013
p += scnprintf(p, end - p, "\n");
11014
}
11015
11016
out:
11017
return p - buf;
11018
}
11019
11020
static int _show_mreg_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11021
{
11022
struct rtw89_btc *btc = &rtwdev->btc;
11023
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11024
struct rtw89_btc_fbtc_mreg_val_v7 *pmreg = NULL;
11025
struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11026
struct rtw89_btc_cx *cx = &btc->cx;
11027
struct rtw89_btc_wl_info *wl = &cx->wl;
11028
struct rtw89_btc_bt_info *bt = &cx->bt;
11029
struct rtw89_mac_ax_gnt *gnt = NULL;
11030
struct rtw89_btc_dm *dm = &btc->dm;
11031
char *p = buf, *end = buf + bufsz;
11032
u8 i, type, cnt = 0;
11033
u32 val, offset;
11034
11035
if (!(dm->coex_info_map & BTC_COEX_INFO_MREG))
11036
return 0;
11037
11038
p += scnprintf(p, end - p, "\n\r========== [HW Status] ==========");
11039
11040
p += scnprintf(p, end - p,
11041
"\n\r %-15s : WL->BT:0x%08x(cnt:%d), BT->WL:0x%08x(total:%d, bt_update:%d)",
11042
"[scoreboard]", wl->scbd,
11043
cx->cnt_wl[BTC_WCNT_SCBDUPDATE],
11044
bt->scbd, cx->cnt_bt[BTC_BCNT_SCBDREAD],
11045
cx->cnt_bt[BTC_BCNT_SCBDUPDATE]);
11046
11047
/* To avoid I/O if WL LPS or power-off */
11048
dm->pta_owner = rtw89_mac_get_ctrl_path(rtwdev);
11049
11050
p += scnprintf(p, end - p,
11051
"\n\r %-15s : pta_owner:%s, pta_req_mac:MAC%d, rf_gnt_source: polut_type:%s",
11052
"[gnt_status]",
11053
rtwdev->chip->para_ver & BTC_FEAT_PTA_ONOFF_CTRL ? "HW" :
11054
dm->pta_owner == BTC_CTRL_BY_WL ? "WL" : "BT",
11055
wl->pta_req_mac,
11056
id_to_polut(wl->bt_polut_type[wl->pta_req_mac]));
11057
11058
gnt = &dm->gnt.band[RTW89_PHY_0];
11059
11060
p += scnprintf(p, end - p, ", phy-0[gnt_wl:%s-%d/gnt_bt:%s-%d]",
11061
gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl,
11062
gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt);
11063
11064
if (rtwdev->dbcc_en) {
11065
gnt = &dm->gnt.band[RTW89_PHY_1];
11066
p += scnprintf(p, end - p,
11067
", phy-1[gnt_wl:%s-%d/gnt_bt:%s-%d]",
11068
gnt->gnt_wl_sw_en ? "SW" : "HW", gnt->gnt_wl,
11069
gnt->gnt_bt_sw_en ? "SW" : "HW", gnt->gnt_bt);
11070
}
11071
11072
pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
11073
if (!pcinfo->valid)
11074
goto out;
11075
11076
pmreg = &pfwinfo->rpt_fbtc_mregval.finfo.v7;
11077
11078
for (i = 0; i < pmreg->reg_num; i++) {
11079
type = (u8)le16_to_cpu(rtwdev->chip->mon_reg[i].type);
11080
offset = le32_to_cpu(rtwdev->chip->mon_reg[i].offset);
11081
val = le32_to_cpu(pmreg->mreg_val[i]);
11082
11083
if (cnt % 6 == 0)
11084
p += scnprintf(p, end - p,
11085
"\n\r %-15s : %s_0x%x=0x%x", "[reg]",
11086
id_to_regtype(type), offset, val);
11087
else
11088
p += scnprintf(p, end - p, ", %s_0x%x=0x%x",
11089
id_to_regtype(type), offset, val);
11090
cnt++;
11091
}
11092
11093
out:
11094
return p - buf;
11095
}
11096
11097
static int _show_summary_v1(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11098
{
11099
struct rtw89_btc *btc = &rtwdev->btc;
11100
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11101
struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11102
struct rtw89_btc_fbtc_rpt_ctrl_v1 *prptctrl = NULL;
11103
struct rtw89_btc_cx *cx = &btc->cx;
11104
struct rtw89_btc_dm *dm = &btc->dm;
11105
struct rtw89_btc_wl_info *wl = &cx->wl;
11106
struct rtw89_btc_bt_info *bt = &cx->bt;
11107
u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11108
char *p = buf, *end = buf + bufsz;
11109
u8 i;
11110
11111
if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11112
return 0;
11113
11114
p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11115
11116
pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11117
if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11118
prptctrl = &pfwinfo->rpt_ctrl.finfo.v1;
11119
11120
p += scnprintf(p, end - p,
11121
" %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
11122
"[summary]", pfwinfo->cnt_h2c,
11123
pfwinfo->cnt_h2c_fail, prptctrl->h2c_cnt,
11124
pfwinfo->cnt_c2h, prptctrl->c2h_cnt);
11125
11126
p += scnprintf(p, end - p,
11127
"rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
11128
pfwinfo->event[BTF_EVNT_RPT],
11129
prptctrl->rpt_cnt,
11130
prptctrl->rpt_enable, dm->error.val);
11131
11132
if (dm->error.map.wl_fw_hang)
11133
p += scnprintf(p, end - p, " (WL FW Hang!!)");
11134
p += scnprintf(p, end - p, "\n");
11135
p += scnprintf(p, end - p,
11136
" %-15s : send_ok:%d, send_fail:%d, recv:%d",
11137
"[mailbox]", prptctrl->mb_send_ok_cnt,
11138
prptctrl->mb_send_fail_cnt,
11139
prptctrl->mb_recv_cnt);
11140
11141
p += scnprintf(p, end - p,
11142
"(A2DP_empty:%d, A2DP_flowstop:%d, A2DP_full:%d)\n",
11143
prptctrl->mb_a2dp_empty_cnt,
11144
prptctrl->mb_a2dp_flct_cnt,
11145
prptctrl->mb_a2dp_full_cnt);
11146
11147
p += scnprintf(p, end - p,
11148
" %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
11149
"[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11150
cx->cnt_wl[BTC_WCNT_RFK_GO],
11151
cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11152
cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11153
11154
p += scnprintf(p, end - p,
11155
", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
11156
prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REQ],
11157
prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_GO],
11158
prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_REJECT],
11159
prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT],
11160
prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_FAIL]);
11161
11162
if (prptctrl->bt_rfk_cnt[BTC_BCNT_RFK_TIMEOUT] > 0)
11163
bt->rfk_info.map.timeout = 1;
11164
else
11165
bt->rfk_info.map.timeout = 0;
11166
11167
dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
11168
} else {
11169
p += scnprintf(p, end - p,
11170
" %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
11171
"[summary]", pfwinfo->cnt_h2c,
11172
pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
11173
pfwinfo->event[BTF_EVNT_RPT],
11174
btc->fwinfo.rpt_en_map);
11175
p += scnprintf(p, end - p, " (WL FW report invalid!!)\n");
11176
}
11177
11178
for (i = 0; i < BTC_NCNT_NUM; i++)
11179
cnt_sum += dm->cnt_notify[i];
11180
11181
p += scnprintf(p, end - p,
11182
" %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11183
"[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11184
cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11185
11186
p += scnprintf(p, end - p,
11187
"power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
11188
cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11189
cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11190
cnt[BTC_NCNT_WL_STA]);
11191
11192
p += scnprintf(p, end - p,
11193
" %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11194
"[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
11195
cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
11196
cnt[BTC_NCNT_SPECIAL_PACKET]);
11197
11198
p += scnprintf(p, end - p,
11199
"timer=%d, control=%d, customerize=%d\n",
11200
cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11201
cnt[BTC_NCNT_CUSTOMERIZE]);
11202
11203
return p - buf;
11204
}
11205
11206
static int _show_summary_v4(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11207
{
11208
struct rtw89_btc *btc = &rtwdev->btc;
11209
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11210
struct rtw89_btc_fbtc_rpt_ctrl_v4 *prptctrl;
11211
struct rtw89_btc_rpt_cmn_info *pcinfo;
11212
struct rtw89_btc_cx *cx = &btc->cx;
11213
struct rtw89_btc_dm *dm = &btc->dm;
11214
struct rtw89_btc_wl_info *wl = &cx->wl;
11215
struct rtw89_btc_bt_info *bt = &cx->bt;
11216
u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11217
char *p = buf, *end = buf + bufsz;
11218
u8 i;
11219
11220
if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11221
return 0;
11222
11223
p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11224
11225
pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11226
if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11227
prptctrl = &pfwinfo->rpt_ctrl.finfo.v4;
11228
11229
p += scnprintf(p, end - p,
11230
" %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d), ",
11231
"[summary]", pfwinfo->cnt_h2c,
11232
pfwinfo->cnt_h2c_fail,
11233
le32_to_cpu(prptctrl->rpt_info.cnt_h2c),
11234
pfwinfo->cnt_c2h,
11235
le32_to_cpu(prptctrl->rpt_info.cnt_c2h));
11236
11237
p += scnprintf(p, end - p,
11238
"rpt_cnt=%d(fw_send:%d), rpt_map=0x%x, dm_error_map:0x%x",
11239
pfwinfo->event[BTF_EVNT_RPT],
11240
le32_to_cpu(prptctrl->rpt_info.cnt),
11241
le32_to_cpu(prptctrl->rpt_info.en),
11242
dm->error.val);
11243
11244
if (dm->error.map.wl_fw_hang)
11245
p += scnprintf(p, end - p, " (WL FW Hang!!)");
11246
p += scnprintf(p, end - p, "\n");
11247
p += scnprintf(p, end - p,
11248
" %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11249
"[mailbox]",
11250
le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11251
le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11252
le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11253
11254
p += scnprintf(p, end - p,
11255
"A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
11256
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11257
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11258
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11259
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11260
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11261
11262
p += scnprintf(p, end - p,
11263
" %-15s : wl_rfk[req:%d/go:%d/reject:%d/timeout:%d]",
11264
"[RFK]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11265
cx->cnt_wl[BTC_WCNT_RFK_GO],
11266
cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11267
cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11268
11269
p += scnprintf(p, end - p,
11270
", bt_rfk[req:%d/go:%d/reject:%d/timeout:%d/fail:%d]\n",
11271
le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]),
11272
le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_GO]),
11273
le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REJECT]),
11274
le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]),
11275
le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_FAIL]));
11276
11277
if (le32_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
11278
bt->rfk_info.map.timeout = 1;
11279
else
11280
bt->rfk_info.map.timeout = 0;
11281
11282
dm->error.map.wl_rfk_timeout = bt->rfk_info.map.timeout;
11283
} else {
11284
p += scnprintf(p, end - p,
11285
" %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d, rpt_cnt=%d, rpt_map=0x%x",
11286
"[summary]", pfwinfo->cnt_h2c,
11287
pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h,
11288
pfwinfo->event[BTF_EVNT_RPT],
11289
btc->fwinfo.rpt_en_map);
11290
p += scnprintf(p, end - p, " (WL FW report invalid!!)\n");
11291
}
11292
11293
for (i = 0; i < BTC_NCNT_NUM; i++)
11294
cnt_sum += dm->cnt_notify[i];
11295
11296
p += scnprintf(p, end - p,
11297
" %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11298
"[notify_cnt]", cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11299
cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11300
11301
p += scnprintf(p, end - p,
11302
"power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d\n",
11303
cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11304
cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11305
cnt[BTC_NCNT_WL_STA]);
11306
11307
p += scnprintf(p, end - p,
11308
" %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11309
"[notify_cnt]", cnt[BTC_NCNT_SCAN_START],
11310
cnt[BTC_NCNT_SCAN_FINISH], cnt[BTC_NCNT_SWITCH_BAND],
11311
cnt[BTC_NCNT_SPECIAL_PACKET]);
11312
11313
p += scnprintf(p, end - p,
11314
"timer=%d, control=%d, customerize=%d\n",
11315
cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11316
cnt[BTC_NCNT_CUSTOMERIZE]);
11317
11318
return p - buf;
11319
}
11320
11321
static int _show_summary_v5(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11322
{
11323
struct rtw89_btc *btc = &rtwdev->btc;
11324
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11325
struct rtw89_btc_fbtc_rpt_ctrl_v5 *prptctrl;
11326
struct rtw89_btc_rpt_cmn_info *pcinfo;
11327
struct rtw89_btc_cx *cx = &btc->cx;
11328
struct rtw89_btc_dm *dm = &btc->dm;
11329
struct rtw89_btc_wl_info *wl = &cx->wl;
11330
u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11331
char *p = buf, *end = buf + bufsz;
11332
u8 i;
11333
11334
if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11335
return 0;
11336
11337
p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11338
11339
pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11340
if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11341
prptctrl = &pfwinfo->rpt_ctrl.finfo.v5;
11342
11343
p += scnprintf(p, end - p,
11344
" %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
11345
"[summary]", pfwinfo->cnt_h2c,
11346
pfwinfo->cnt_h2c_fail,
11347
le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11348
pfwinfo->cnt_c2h,
11349
le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11350
le16_to_cpu(prptctrl->rpt_info.len_c2h));
11351
11352
p += scnprintf(p, end - p,
11353
"rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11354
pfwinfo->event[BTF_EVNT_RPT],
11355
le16_to_cpu(prptctrl->rpt_info.cnt),
11356
le32_to_cpu(prptctrl->rpt_info.en));
11357
11358
if (dm->error.map.wl_fw_hang)
11359
p += scnprintf(p, end - p, " (WL FW Hang!!)");
11360
p += scnprintf(p, end - p, "\n");
11361
p += scnprintf(p, end - p,
11362
" %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11363
"[mailbox]",
11364
le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11365
le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11366
le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11367
11368
p += scnprintf(p, end - p,
11369
"A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
11370
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11371
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11372
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11373
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11374
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11375
11376
p += scnprintf(p, end - p,
11377
" %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
11378
"[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11379
cx->cnt_wl[BTC_WCNT_RFK_GO],
11380
cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11381
cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11382
11383
p += scnprintf(p, end - p,
11384
", bt_rfk[req:%d]",
11385
le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11386
11387
p += scnprintf(p, end - p,
11388
", AOAC[RF_on:%d/RF_off:%d]",
11389
le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11390
le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11391
} else {
11392
p += scnprintf(p, end - p,
11393
" %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
11394
"[summary]", pfwinfo->cnt_h2c,
11395
pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
11396
}
11397
11398
if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
11399
pfwinfo->err[BTFRE_EXCEPTION]) {
11400
p += scnprintf(p, end - p, "\n");
11401
p += scnprintf(p, end - p,
11402
" %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
11403
"0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
11404
"[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
11405
pfwinfo->fver_mismch,
11406
pfwinfo->err[BTFRE_EXCEPTION],
11407
wl->status.map.lps, wl->status.map.rf_off);
11408
}
11409
11410
for (i = 0; i < BTC_NCNT_NUM; i++)
11411
cnt_sum += dm->cnt_notify[i];
11412
11413
p += scnprintf(p, end - p, "\n");
11414
p += scnprintf(p, end - p,
11415
" %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11416
"[notify_cnt]",
11417
cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11418
cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11419
11420
p += scnprintf(p, end - p,
11421
"power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11422
cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11423
cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11424
cnt[BTC_NCNT_WL_STA]);
11425
11426
p += scnprintf(p, end - p, "\n");
11427
p += scnprintf(p, end - p,
11428
" %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11429
"[notify_cnt]",
11430
cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11431
cnt[BTC_NCNT_SWITCH_BAND],
11432
cnt[BTC_NCNT_SPECIAL_PACKET]);
11433
11434
p += scnprintf(p, end - p,
11435
"timer=%d, control=%d, customerize=%d",
11436
cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11437
cnt[BTC_NCNT_CUSTOMERIZE]);
11438
11439
return p - buf;
11440
}
11441
11442
static int _show_summary_v105(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11443
{
11444
struct rtw89_btc *btc = &rtwdev->btc;
11445
struct rtw89_btc_btf_fwinfo *pfwinfo = &btc->fwinfo;
11446
struct rtw89_btc_fbtc_rpt_ctrl_v105 *prptctrl;
11447
struct rtw89_btc_rpt_cmn_info *pcinfo;
11448
struct rtw89_btc_cx *cx = &btc->cx;
11449
struct rtw89_btc_dm *dm = &btc->dm;
11450
struct rtw89_btc_wl_info *wl = &cx->wl;
11451
u32 cnt_sum = 0, *cnt = btc->dm.cnt_notify;
11452
char *p = buf, *end = buf + bufsz;
11453
u8 i;
11454
11455
if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11456
return 0;
11457
11458
p += scnprintf(p, end - p, "========== [Statistics] ==========\n");
11459
11460
pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11461
if (pcinfo->valid && !wl->status.map.lps && !wl->status.map.rf_off) {
11462
prptctrl = &pfwinfo->rpt_ctrl.finfo.v105;
11463
11464
p += scnprintf(p, end - p,
11465
" %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d), ",
11466
"[summary]", pfwinfo->cnt_h2c,
11467
pfwinfo->cnt_h2c_fail,
11468
le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11469
pfwinfo->cnt_c2h,
11470
le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11471
le16_to_cpu(prptctrl->rpt_info.len_c2h));
11472
11473
p += scnprintf(p, end - p,
11474
"rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11475
pfwinfo->event[BTF_EVNT_RPT],
11476
le16_to_cpu(prptctrl->rpt_info.cnt),
11477
le32_to_cpu(prptctrl->rpt_info.en));
11478
11479
if (dm->error.map.wl_fw_hang)
11480
p += scnprintf(p, end - p, " (WL FW Hang!!)");
11481
p += scnprintf(p, end - p, "\n");
11482
p += scnprintf(p, end - p,
11483
" %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11484
"[mailbox]",
11485
le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11486
le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11487
le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11488
11489
p += scnprintf(p, end - p,
11490
"A2DP_empty:%d(stop:%d, tx:%d, ack:%d, nack:%d)\n",
11491
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11492
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11493
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11494
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11495
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11496
11497
p += scnprintf(p, end - p,
11498
" %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d]",
11499
"[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11500
cx->cnt_wl[BTC_WCNT_RFK_GO],
11501
cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11502
cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT]);
11503
11504
p += scnprintf(p, end - p,
11505
", bt_rfk[req:%d]",
11506
le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11507
11508
p += scnprintf(p, end - p,
11509
", AOAC[RF_on:%d/RF_off:%d]",
11510
le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11511
le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11512
} else {
11513
p += scnprintf(p, end - p,
11514
" %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d",
11515
"[summary]", pfwinfo->cnt_h2c,
11516
pfwinfo->cnt_h2c_fail, pfwinfo->cnt_c2h);
11517
}
11518
11519
if (!pcinfo->valid || pfwinfo->len_mismch || pfwinfo->fver_mismch ||
11520
pfwinfo->err[BTFRE_EXCEPTION]) {
11521
p += scnprintf(p, end - p, "\n");
11522
p += scnprintf(p, end - p,
11523
" %-15s : WL FW rpt error!![rpt_ctrl_valid:%d/len:"
11524
"0x%x/ver:0x%x/ex:%d/lps=%d/rf_off=%d]",
11525
"[ERROR]", pcinfo->valid, pfwinfo->len_mismch,
11526
pfwinfo->fver_mismch,
11527
pfwinfo->err[BTFRE_EXCEPTION],
11528
wl->status.map.lps, wl->status.map.rf_off);
11529
}
11530
11531
for (i = 0; i < BTC_NCNT_NUM; i++)
11532
cnt_sum += dm->cnt_notify[i];
11533
11534
p += scnprintf(p, end - p, "\n");
11535
p += scnprintf(p, end - p,
11536
" %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11537
"[notify_cnt]",
11538
cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11539
cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11540
11541
p += scnprintf(p, end - p,
11542
"power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11543
cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11544
cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11545
cnt[BTC_NCNT_WL_STA]);
11546
11547
p += scnprintf(p, end - p, "\n");
11548
p += scnprintf(p, end - p,
11549
" %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, special_pkt=%d, ",
11550
"[notify_cnt]",
11551
cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11552
cnt[BTC_NCNT_SWITCH_BAND],
11553
cnt[BTC_NCNT_SPECIAL_PACKET]);
11554
11555
p += scnprintf(p, end - p,
11556
"timer=%d, control=%d, customerize=%d",
11557
cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CONTROL],
11558
cnt[BTC_NCNT_CUSTOMERIZE]);
11559
11560
return p - buf;
11561
}
11562
11563
static int _show_summary_v7(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11564
{
11565
struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
11566
struct rtw89_btc_fbtc_rpt_ctrl_v7 *prptctrl = NULL;
11567
struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11568
struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
11569
struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
11570
struct rtw89_btc_wl_info *wl = &cx->wl;
11571
u32 *cnt = rtwdev->btc.dm.cnt_notify;
11572
char *p = buf, *end = buf + bufsz;
11573
u32 cnt_sum = 0;
11574
u8 i;
11575
11576
if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11577
return 0;
11578
11579
p += scnprintf(p, end - p, "%s",
11580
"\n\r========== [Statistics] ==========");
11581
11582
pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11583
if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
11584
!wl->status.map.rf_off) {
11585
prptctrl = &pfwinfo->rpt_ctrl.finfo.v7;
11586
11587
p += scnprintf(p, end - p,
11588
"\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d),"
11589
"c2h_cnt=%d(fw_send:%d, len:%d, max:%d), ",
11590
"[summary]", pfwinfo->cnt_h2c,
11591
pfwinfo->cnt_h2c_fail,
11592
le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11593
pfwinfo->cnt_c2h,
11594
le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11595
le16_to_cpu(prptctrl->rpt_info.len_c2h),
11596
rtwdev->btc.ver->info_buf);
11597
11598
p += scnprintf(p, end - p,
11599
"rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11600
pfwinfo->event[BTF_EVNT_RPT],
11601
le16_to_cpu(prptctrl->rpt_info.cnt),
11602
le32_to_cpu(prptctrl->rpt_info.en));
11603
11604
if (dm->error.map.wl_fw_hang)
11605
p += scnprintf(p, end - p, " (WL FW Hang!!)");
11606
11607
p += scnprintf(p, end - p,
11608
"\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11609
"[mailbox]",
11610
le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11611
le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11612
le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11613
11614
p += scnprintf(p, end - p,
11615
"A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)",
11616
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11617
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11618
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11619
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11620
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11621
11622
p += scnprintf(p, end - p,
11623
"\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
11624
"[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11625
cx->cnt_wl[BTC_WCNT_RFK_GO],
11626
cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11627
cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT],
11628
wl->rfk_info.proc_time);
11629
11630
p += scnprintf(p, end - p, ", bt_rfk[req:%d]",
11631
le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11632
11633
p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]",
11634
le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11635
le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11636
} else {
11637
p += scnprintf(p, end - p,
11638
"\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)",
11639
"[summary]",
11640
pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
11641
pfwinfo->cnt_c2h,
11642
wl->status.map.lps, wl->status.map.rf_off);
11643
}
11644
11645
for (i = 0; i < BTC_NCNT_NUM; i++)
11646
cnt_sum += dm->cnt_notify[i];
11647
11648
p += scnprintf(p, end - p,
11649
"\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11650
"[notify_cnt]",
11651
cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11652
cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11653
11654
p += scnprintf(p, end - p,
11655
"power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11656
cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11657
cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11658
cnt[BTC_NCNT_WL_STA]);
11659
11660
p += scnprintf(p, end - p,
11661
"\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
11662
"[notify_cnt]",
11663
cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11664
cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
11665
cnt[BTC_NCNT_SPECIAL_PACKET]);
11666
11667
p += scnprintf(p, end - p,
11668
"timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
11669
cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
11670
rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
11671
cnt[BTC_NCNT_COUNTRYCODE]);
11672
11673
return p - buf;
11674
}
11675
11676
static int _show_summary_v8(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11677
{
11678
struct rtw89_btc_btf_fwinfo *pfwinfo = &rtwdev->btc.fwinfo;
11679
struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
11680
struct rtw89_btc_fbtc_rpt_ctrl_v8 *prptctrl = NULL;
11681
struct rtw89_btc_cx *cx = &rtwdev->btc.cx;
11682
struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
11683
struct rtw89_btc_wl_info *wl = &cx->wl;
11684
u32 *cnt = rtwdev->btc.dm.cnt_notify;
11685
char *p = buf, *end = buf + bufsz;
11686
u32 cnt_sum = 0;
11687
u8 i;
11688
11689
if (!(dm->coex_info_map & BTC_COEX_INFO_SUMMARY))
11690
return 0;
11691
11692
p += scnprintf(p, end - p, "%s",
11693
"\n\r========== [Statistics] ==========");
11694
11695
pcinfo = &pfwinfo->rpt_ctrl.cinfo;
11696
if (pcinfo->valid && wl->status.map.lps != BTC_LPS_RF_OFF &&
11697
!wl->status.map.rf_off) {
11698
prptctrl = &pfwinfo->rpt_ctrl.finfo.v8;
11699
11700
p += scnprintf(p, end - p,
11701
"\n\r %-15s : h2c_cnt=%d(fail:%d, fw_recv:%d), c2h_cnt=%d(fw_send:%d, len:%d, max:fw-%d/drv-%d), ",
11702
"[summary]", pfwinfo->cnt_h2c,
11703
pfwinfo->cnt_h2c_fail,
11704
le16_to_cpu(prptctrl->rpt_info.cnt_h2c),
11705
pfwinfo->cnt_c2h,
11706
le16_to_cpu(prptctrl->rpt_info.cnt_c2h),
11707
le16_to_cpu(prptctrl->rpt_info.len_c2h),
11708
(prptctrl->rpt_len_max_h << 8) + prptctrl->rpt_len_max_l,
11709
rtwdev->btc.ver->info_buf);
11710
11711
p += scnprintf(p, end - p,
11712
"rpt_cnt=%d(fw_send:%d), rpt_map=0x%x",
11713
pfwinfo->event[BTF_EVNT_RPT],
11714
le16_to_cpu(prptctrl->rpt_info.cnt),
11715
le32_to_cpu(prptctrl->rpt_info.en));
11716
11717
if (dm->error.map.wl_fw_hang)
11718
p += scnprintf(p, end - p, " (WL FW Hang!!)");
11719
11720
p += scnprintf(p, end - p,
11721
"\n\r %-15s : send_ok:%d, send_fail:%d, recv:%d, ",
11722
"[mailbox]",
11723
le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_ok),
11724
le32_to_cpu(prptctrl->bt_mbx_info.cnt_send_fail),
11725
le32_to_cpu(prptctrl->bt_mbx_info.cnt_recv));
11726
11727
p += scnprintf(p, end - p,
11728
"A2DP_empty:%d(stop:%d/tx:%d/ack:%d/nack:%d)",
11729
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_empty),
11730
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_flowctrl),
11731
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_tx),
11732
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_ack),
11733
le32_to_cpu(prptctrl->bt_mbx_info.a2dp.cnt_nack));
11734
11735
p += scnprintf(p, end - p,
11736
"\n\r %-15s : wl_rfk[req:%d/go:%d/reject:%d/tout:%d/time:%dms]",
11737
"[RFK/LPS]", cx->cnt_wl[BTC_WCNT_RFK_REQ],
11738
cx->cnt_wl[BTC_WCNT_RFK_GO],
11739
cx->cnt_wl[BTC_WCNT_RFK_REJECT],
11740
cx->cnt_wl[BTC_WCNT_RFK_TIMEOUT],
11741
wl->rfk_info.proc_time);
11742
11743
p += scnprintf(p, end - p, ", bt_rfk[req:%d]",
11744
le16_to_cpu(prptctrl->bt_cnt[BTC_BCNT_RFK_REQ]));
11745
11746
p += scnprintf(p, end - p, ", AOAC[RF_on:%d/RF_off:%d]",
11747
le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_on),
11748
le16_to_cpu(prptctrl->rpt_info.cnt_aoac_rf_off));
11749
} else {
11750
p += scnprintf(p, end - p,
11751
"\n\r %-15s : h2c_cnt=%d(fail:%d), c2h_cnt=%d (lps=%d/rf_off=%d)",
11752
"[summary]",
11753
pfwinfo->cnt_h2c, pfwinfo->cnt_h2c_fail,
11754
pfwinfo->cnt_c2h,
11755
wl->status.map.lps, wl->status.map.rf_off);
11756
}
11757
11758
for (i = 0; i < BTC_NCNT_NUM; i++)
11759
cnt_sum += dm->cnt_notify[i];
11760
11761
p += scnprintf(p, end - p,
11762
"\n\r %-15s : total=%d, show_coex_info=%d, power_on=%d, init_coex=%d, ",
11763
"[notify_cnt]",
11764
cnt_sum, cnt[BTC_NCNT_SHOW_COEX_INFO],
11765
cnt[BTC_NCNT_POWER_ON], cnt[BTC_NCNT_INIT_COEX]);
11766
11767
p += scnprintf(p, end - p,
11768
"power_off=%d, radio_state=%d, role_info=%d, wl_rfk=%d, wl_sta=%d",
11769
cnt[BTC_NCNT_POWER_OFF], cnt[BTC_NCNT_RADIO_STATE],
11770
cnt[BTC_NCNT_ROLE_INFO], cnt[BTC_NCNT_WL_RFK],
11771
cnt[BTC_NCNT_WL_STA]);
11772
11773
p += scnprintf(p, end - p,
11774
"\n\r %-15s : scan_start=%d, scan_finish=%d, switch_band=%d, switch_chbw=%d, special_pkt=%d, ",
11775
"[notify_cnt]",
11776
cnt[BTC_NCNT_SCAN_START], cnt[BTC_NCNT_SCAN_FINISH],
11777
cnt[BTC_NCNT_SWITCH_BAND], cnt[BTC_NCNT_SWITCH_CHBW],
11778
cnt[BTC_NCNT_SPECIAL_PACKET]);
11779
11780
p += scnprintf(p, end - p,
11781
"timer=%d, customerize=%d, hub_msg=%d, chg_fw=%d, send_cc=%d",
11782
cnt[BTC_NCNT_TIMER], cnt[BTC_NCNT_CUSTOMERIZE],
11783
rtwdev->btc.hubmsg_cnt, cnt[BTC_NCNT_RESUME_DL_FW],
11784
cnt[BTC_NCNT_COUNTRYCODE]);
11785
11786
return p - buf;
11787
}
11788
11789
ssize_t rtw89_btc_dump_info(struct rtw89_dev *rtwdev, char *buf, size_t bufsz)
11790
{
11791
struct rtw89_btc *btc = &rtwdev->btc;
11792
struct rtw89_btc_ver *fwsubver = &btc->fwinfo.fw_subver;
11793
const struct rtw89_btc_ver *ver = btc->ver;
11794
struct rtw89_btc_dm *dm = &btc->dm;
11795
char *p = buf, *end = buf + bufsz;
11796
11797
dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO]++;
11798
11799
p += scnprintf(p, end - p,
11800
"\n\n\n** Page:%3d/RunCNT:%3d **",
11801
dm->cnt_notify[BTC_NCNT_SHOW_COEX_INFO],
11802
dm->cnt_dm[BTC_DCNT_RUN]);
11803
p += scnprintf(p, end - p,
11804
"\n========== [BTC FEATURE SUB VER] ==========");
11805
p += scnprintf(p, end - p,
11806
"\n %-15s : fcxbtcrpt[%d/%d], fcxtdma[%d/%d], fcxslots[%d/%d], fcxcysta[%d/%d]",
11807
"[FW/DRV]", fwsubver->fcxbtcrpt, ver->fcxbtcrpt,
11808
fwsubver->fcxtdma, ver->fcxtdma, fwsubver->fcxslots,
11809
ver->fcxslots, fwsubver->fcxcysta, ver->fcxcysta);
11810
p += scnprintf(p, end - p,
11811
"\n %-15s : fcxstep[%d/%d], fcxnullsta[%d/%d], fcxmreg[%d/%d], fcxgpiodbg[%d/%d]",
11812
"[FW/DRV]", fwsubver->fcxstep, ver->fcxstep,
11813
fwsubver->fcxnullsta, ver->fcxnullsta, fwsubver->fcxmreg,
11814
ver->fcxmreg, fwsubver->fcxgpiodbg, ver->fcxgpiodbg);
11815
p += scnprintf(p, end - p,
11816
"\n %-15s : fcxbtver[%d/%d], fcxbtscan[%d/%d], fcxbtafh[%d/%d], fcxbtdevinfo[%d/%d]",
11817
"[FW/DRV]", fwsubver->fcxbtver, ver->fcxbtver,
11818
fwsubver->fcxbtscan, ver->fcxbtscan, fwsubver->fcxbtafh,
11819
ver->fcxbtafh, fwsubver->fcxbtdevinfo, ver->fcxbtdevinfo);
11820
p += scnprintf(p, end - p,
11821
"\n %-15s : fcxosi[%d/%d], fcxmlo[%d/%d],",
11822
"[FW/DRV]", fwsubver->fcxosi, ver->fcxosi,
11823
fwsubver->fcxmlo, ver->fcxmlo);
11824
11825
p += _show_cx_info(rtwdev, p, end - p);
11826
p += _show_wl_info(rtwdev, p, end - p);
11827
p += _show_bt_info(rtwdev, p, end - p);
11828
p += _show_dm_info(rtwdev, p, end - p);
11829
p += _show_fw_dm_msg(rtwdev, p, end - p);
11830
11831
if (ver->fcxmreg == 1)
11832
p += _show_mreg_v1(rtwdev, p, end - p);
11833
else if (ver->fcxmreg == 2)
11834
p += _show_mreg_v2(rtwdev, p, end - p);
11835
else if (ver->fcxmreg == 7)
11836
p += _show_mreg_v7(rtwdev, p, end - p);
11837
11838
p += _show_gpio_dbg(rtwdev, p, end - p);
11839
11840
if (ver->fcxbtcrpt == 1)
11841
p += _show_summary_v1(rtwdev, p, end - p);
11842
else if (ver->fcxbtcrpt == 4)
11843
p += _show_summary_v4(rtwdev, p, end - p);
11844
else if (ver->fcxbtcrpt == 5)
11845
p += _show_summary_v5(rtwdev, p, end - p);
11846
else if (ver->fcxbtcrpt == 105)
11847
p += _show_summary_v105(rtwdev, p, end - p);
11848
else if (ver->fcxbtcrpt == 7)
11849
p += _show_summary_v7(rtwdev, p, end - p);
11850
else if (ver->fcxbtcrpt == 8)
11851
p += _show_summary_v8(rtwdev, p, end - p);
11852
11853
return p - buf;
11854
}
11855
11856
void rtw89_coex_recognize_ver(struct rtw89_dev *rtwdev)
11857
{
11858
const struct rtw89_chip_info *chip = rtwdev->chip;
11859
struct rtw89_btc *btc = &rtwdev->btc;
11860
const struct rtw89_btc_ver *btc_ver_def;
11861
const struct rtw89_fw_suit *fw_suit;
11862
u32 suit_ver_code;
11863
int i;
11864
11865
fw_suit = rtw89_fw_suit_get(rtwdev, RTW89_FW_NORMAL);
11866
suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit);
11867
11868
for (i = 0; i < ARRAY_SIZE(rtw89_btc_ver_defs); i++) {
11869
btc_ver_def = &rtw89_btc_ver_defs[i];
11870
11871
if (chip->chip_id != btc_ver_def->chip_id)
11872
continue;
11873
11874
if (suit_ver_code >= btc_ver_def->fw_ver_code) {
11875
btc->ver = btc_ver_def;
11876
goto out;
11877
}
11878
}
11879
11880
btc->ver = &rtw89_btc_ver_defs[RTW89_DEFAULT_BTC_VER_IDX];
11881
11882
out:
11883
rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC] use version def[%d] = 0x%08x\n",
11884
(int)(btc->ver - rtw89_btc_ver_defs), btc->ver->fw_ver_code);
11885
}
11886
11887
void rtw89_btc_ntfy_preserve_bt_time(struct rtw89_dev *rtwdev, u32 ms)
11888
{
11889
struct rtw89_btc_bt_link_info *bt_linfo = &rtwdev->btc.cx.bt.link_info;
11890
struct rtw89_btc_bt_a2dp_desc a2dp = bt_linfo->a2dp_desc;
11891
11892
if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags))
11893
return;
11894
11895
if (!a2dp.exist)
11896
return;
11897
11898
fsleep(ms * 1000);
11899
}
11900
EXPORT_SYMBOL(rtw89_btc_ntfy_preserve_bt_time);
11901
11902
void rtw89_btc_ntfy_conn_rfk(struct rtw89_dev *rtwdev, bool state)
11903
{
11904
rtwdev->btc.cx.wl.rfk_info.con_rfk = state;
11905
}
11906
EXPORT_SYMBOL(rtw89_btc_ntfy_conn_rfk);
11907
11908