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