Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/athk/ath12k/debugfs.c
178699 views
1
// SPDX-License-Identifier: BSD-3-Clause-Clear
2
/*
3
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
5
*/
6
7
#include "core.h"
8
#include "dp_tx.h"
9
#include "debug.h"
10
#include "debugfs.h"
11
#include "debugfs_htt_stats.h"
12
13
static ssize_t ath12k_write_simulate_radar(struct file *file,
14
const char __user *user_buf,
15
size_t count, loff_t *ppos)
16
{
17
struct ath12k *ar = file->private_data;
18
int ret;
19
20
wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
21
ret = ath12k_wmi_simulate_radar(ar);
22
if (ret)
23
goto exit;
24
25
ret = count;
26
exit:
27
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
28
return ret;
29
}
30
31
static const struct file_operations fops_simulate_radar = {
32
.write = ath12k_write_simulate_radar,
33
.open = simple_open
34
};
35
36
static ssize_t ath12k_read_simulate_fw_crash(struct file *file,
37
char __user *user_buf,
38
size_t count, loff_t *ppos)
39
{
40
const char buf[] =
41
"To simulate firmware crash write one of the keywords to this file:\n"
42
"`assert` - send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\n";
43
44
return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
45
}
46
47
static ssize_t
48
ath12k_write_simulate_fw_crash(struct file *file,
49
const char __user *user_buf,
50
size_t count, loff_t *ppos)
51
{
52
struct ath12k_base *ab = file->private_data;
53
struct ath12k_pdev *pdev;
54
struct ath12k *ar = NULL;
55
char buf[32] = {};
56
int i, ret;
57
ssize_t rc;
58
59
/* filter partial writes and invalid commands */
60
if (*ppos != 0 || count >= sizeof(buf) || count == 0)
61
return -EINVAL;
62
63
rc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
64
if (rc < 0)
65
return rc;
66
67
/* drop the possible '\n' from the end */
68
if (buf[*ppos - 1] == '\n')
69
buf[*ppos - 1] = '\0';
70
71
for (i = 0; i < ab->num_radios; i++) {
72
pdev = &ab->pdevs[i];
73
ar = pdev->ar;
74
if (ar)
75
break;
76
}
77
78
if (!ar)
79
return -ENETDOWN;
80
81
if (!strcmp(buf, "assert")) {
82
ath12k_info(ab, "simulating firmware assert crash\n");
83
ret = ath12k_wmi_force_fw_hang_cmd(ar,
84
ATH12K_WMI_FW_HANG_ASSERT_TYPE,
85
ATH12K_WMI_FW_HANG_DELAY);
86
} else {
87
return -EINVAL;
88
}
89
90
if (ret) {
91
ath12k_warn(ab, "failed to simulate firmware crash: %d\n", ret);
92
return ret;
93
}
94
95
return count;
96
}
97
98
static const struct file_operations fops_simulate_fw_crash = {
99
.read = ath12k_read_simulate_fw_crash,
100
.write = ath12k_write_simulate_fw_crash,
101
.open = simple_open,
102
.owner = THIS_MODULE,
103
.llseek = default_llseek,
104
};
105
106
static ssize_t ath12k_write_tpc_stats_type(struct file *file,
107
const char __user *user_buf,
108
size_t count, loff_t *ppos)
109
{
110
struct ath12k *ar = file->private_data;
111
u8 type;
112
int ret;
113
114
ret = kstrtou8_from_user(user_buf, count, 0, &type);
115
if (ret)
116
return ret;
117
118
if (type >= WMI_HALPHY_PDEV_TX_STATS_MAX)
119
return -EINVAL;
120
121
spin_lock_bh(&ar->data_lock);
122
ar->debug.tpc_stats_type = type;
123
spin_unlock_bh(&ar->data_lock);
124
125
return count;
126
}
127
128
static int ath12k_debug_tpc_stats_request(struct ath12k *ar)
129
{
130
enum wmi_halphy_ctrl_path_stats_id tpc_stats_sub_id;
131
struct ath12k_base *ab = ar->ab;
132
int ret;
133
134
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
135
136
reinit_completion(&ar->debug.tpc_complete);
137
138
spin_lock_bh(&ar->data_lock);
139
ar->debug.tpc_request = true;
140
tpc_stats_sub_id = ar->debug.tpc_stats_type;
141
spin_unlock_bh(&ar->data_lock);
142
143
ret = ath12k_wmi_send_tpc_stats_request(ar, tpc_stats_sub_id);
144
if (ret) {
145
ath12k_warn(ab, "failed to request pdev tpc stats: %d\n", ret);
146
spin_lock_bh(&ar->data_lock);
147
ar->debug.tpc_request = false;
148
spin_unlock_bh(&ar->data_lock);
149
return ret;
150
}
151
152
return 0;
153
}
154
155
static int ath12k_get_tpc_ctl_mode_idx(struct wmi_tpc_stats_arg *tpc_stats,
156
enum wmi_tpc_pream_bw pream_bw, int *mode_idx)
157
{
158
u32 chan_freq = le32_to_cpu(tpc_stats->tpc_config.chan_freq);
159
u8 band;
160
161
band = ((chan_freq > ATH12K_MIN_6GHZ_FREQ) ? NL80211_BAND_6GHZ :
162
((chan_freq > ATH12K_MIN_5GHZ_FREQ) ? NL80211_BAND_5GHZ :
163
NL80211_BAND_2GHZ));
164
165
if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) {
166
switch (pream_bw) {
167
case WMI_TPC_PREAM_HT20:
168
case WMI_TPC_PREAM_VHT20:
169
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT_VHT20_5GHZ_6GHZ;
170
break;
171
case WMI_TPC_PREAM_HE20:
172
case WMI_TPC_PREAM_EHT20:
173
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT20_5GHZ_6GHZ;
174
break;
175
case WMI_TPC_PREAM_HT40:
176
case WMI_TPC_PREAM_VHT40:
177
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT_VHT40_5GHZ_6GHZ;
178
break;
179
case WMI_TPC_PREAM_HE40:
180
case WMI_TPC_PREAM_EHT40:
181
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT40_5GHZ_6GHZ;
182
break;
183
case WMI_TPC_PREAM_VHT80:
184
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_VHT80_5GHZ_6GHZ;
185
break;
186
case WMI_TPC_PREAM_EHT60:
187
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT80_SU_PUNC20;
188
break;
189
case WMI_TPC_PREAM_HE80:
190
case WMI_TPC_PREAM_EHT80:
191
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT80_5GHZ_6GHZ;
192
break;
193
case WMI_TPC_PREAM_VHT160:
194
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_VHT160_5GHZ_6GHZ;
195
break;
196
case WMI_TPC_PREAM_EHT120:
197
case WMI_TPC_PREAM_EHT140:
198
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT160_SU_PUNC20;
199
break;
200
case WMI_TPC_PREAM_HE160:
201
case WMI_TPC_PREAM_EHT160:
202
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT160_5GHZ_6GHZ;
203
break;
204
case WMI_TPC_PREAM_EHT200:
205
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT320_SU_PUNC120;
206
break;
207
case WMI_TPC_PREAM_EHT240:
208
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT320_SU_PUNC80;
209
break;
210
case WMI_TPC_PREAM_EHT280:
211
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_EHT320_SU_PUNC40;
212
break;
213
case WMI_TPC_PREAM_EHT320:
214
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HE_EHT320_5GHZ_6GHZ;
215
break;
216
default:
217
/* for 5GHZ and 6GHZ, default case will be for OFDM */
218
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_LEGACY_5GHZ_6GHZ;
219
break;
220
}
221
} else {
222
switch (pream_bw) {
223
case WMI_TPC_PREAM_OFDM:
224
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_LEGACY_2GHZ;
225
break;
226
case WMI_TPC_PREAM_HT20:
227
case WMI_TPC_PREAM_VHT20:
228
case WMI_TPC_PREAM_HE20:
229
case WMI_TPC_PREAM_EHT20:
230
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT20_2GHZ;
231
break;
232
case WMI_TPC_PREAM_HT40:
233
case WMI_TPC_PREAM_VHT40:
234
case WMI_TPC_PREAM_HE40:
235
case WMI_TPC_PREAM_EHT40:
236
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_HT40_2GHZ;
237
break;
238
default:
239
/* for 2GHZ, default case will be CCK */
240
*mode_idx = ATH12K_TPC_STATS_CTL_MODE_CCK_2GHZ;
241
break;
242
}
243
}
244
245
return 0;
246
}
247
248
static s16 ath12k_tpc_get_rate(struct ath12k *ar,
249
struct wmi_tpc_stats_arg *tpc_stats,
250
u32 rate_idx, u32 num_chains, u32 rate_code,
251
enum wmi_tpc_pream_bw pream_bw,
252
enum wmi_halphy_ctrl_path_stats_id type,
253
u32 eht_rate_idx)
254
{
255
u32 tot_nss, tot_modes, txbf_on_off, index_offset1, index_offset2, index_offset3;
256
u8 chain_idx, stm_idx, num_streams;
257
bool is_mu, txbf_enabled = 0;
258
s8 rates_ctl_min, tpc_ctl;
259
s16 rates, tpc, reg_pwr;
260
u16 rate1, rate2;
261
int mode, ret;
262
263
num_streams = 1 + ATH12K_HW_NSS(rate_code);
264
chain_idx = num_chains - 1;
265
stm_idx = num_streams - 1;
266
mode = -1;
267
268
ret = ath12k_get_tpc_ctl_mode_idx(tpc_stats, pream_bw, &mode);
269
if (ret) {
270
ath12k_warn(ar->ab, "Invalid mode index received\n");
271
tpc = TPC_INVAL;
272
goto out;
273
}
274
275
if (num_chains < num_streams) {
276
tpc = TPC_INVAL;
277
goto out;
278
}
279
280
if (le32_to_cpu(tpc_stats->tpc_config.num_tx_chain) <= 1) {
281
tpc = TPC_INVAL;
282
goto out;
283
}
284
285
if (type == WMI_HALPHY_PDEV_TX_SUTXBF_STATS ||
286
type == WMI_HALPHY_PDEV_TX_MUTXBF_STATS)
287
txbf_enabled = 1;
288
289
if (type == WMI_HALPHY_PDEV_TX_MU_STATS ||
290
type == WMI_HALPHY_PDEV_TX_MUTXBF_STATS) {
291
is_mu = true;
292
} else {
293
is_mu = false;
294
}
295
296
/* Below is the min calculation of ctl array, rates array and
297
* regulator power table. tpc is minimum of all 3
298
*/
299
if (pream_bw >= WMI_TPC_PREAM_EHT20 && pream_bw <= WMI_TPC_PREAM_EHT320) {
300
rate2 = tpc_stats->rates_array2.rate_array[eht_rate_idx];
301
if (is_mu)
302
rates = u32_get_bits(rate2, ATH12K_TPC_RATE_ARRAY_MU);
303
else
304
rates = u32_get_bits(rate2, ATH12K_TPC_RATE_ARRAY_SU);
305
} else {
306
rate1 = tpc_stats->rates_array1.rate_array[rate_idx];
307
if (is_mu)
308
rates = u32_get_bits(rate1, ATH12K_TPC_RATE_ARRAY_MU);
309
else
310
rates = u32_get_bits(rate1, ATH12K_TPC_RATE_ARRAY_SU);
311
}
312
313
if (tpc_stats->tlvs_rcvd & WMI_TPC_CTL_PWR_ARRAY) {
314
tot_nss = le32_to_cpu(tpc_stats->ctl_array.tpc_ctl_pwr.d1);
315
tot_modes = le32_to_cpu(tpc_stats->ctl_array.tpc_ctl_pwr.d2);
316
txbf_on_off = le32_to_cpu(tpc_stats->ctl_array.tpc_ctl_pwr.d3);
317
index_offset1 = txbf_on_off * tot_modes * tot_nss;
318
index_offset2 = tot_modes * tot_nss;
319
index_offset3 = tot_nss;
320
321
tpc_ctl = *(tpc_stats->ctl_array.ctl_pwr_table +
322
chain_idx * index_offset1 + txbf_enabled * index_offset2
323
+ mode * index_offset3 + stm_idx);
324
} else {
325
tpc_ctl = TPC_MAX;
326
ath12k_warn(ar->ab,
327
"ctl array for tpc stats not received from fw\n");
328
}
329
330
rates_ctl_min = min_t(s16, rates, tpc_ctl);
331
332
reg_pwr = tpc_stats->max_reg_allowed_power.reg_pwr_array[chain_idx];
333
334
if (reg_pwr < 0)
335
reg_pwr = TPC_INVAL;
336
337
tpc = min_t(s16, rates_ctl_min, reg_pwr);
338
339
/* MODULATION_LIMIT is the maximum power limit,tpc should not exceed
340
* modulation limit even if min tpc of all three array is greater
341
* modulation limit
342
*/
343
tpc = min_t(s16, tpc, MODULATION_LIMIT);
344
345
out:
346
return tpc;
347
}
348
349
static u16 ath12k_get_ratecode(u16 pream_idx, u16 nss, u16 mcs_rate)
350
{
351
u16 mode_type = ~0;
352
353
/* Below assignments are just for printing purpose only */
354
switch (pream_idx) {
355
case WMI_TPC_PREAM_CCK:
356
mode_type = WMI_RATE_PREAMBLE_CCK;
357
break;
358
case WMI_TPC_PREAM_OFDM:
359
mode_type = WMI_RATE_PREAMBLE_OFDM;
360
break;
361
case WMI_TPC_PREAM_HT20:
362
case WMI_TPC_PREAM_HT40:
363
mode_type = WMI_RATE_PREAMBLE_HT;
364
break;
365
case WMI_TPC_PREAM_VHT20:
366
case WMI_TPC_PREAM_VHT40:
367
case WMI_TPC_PREAM_VHT80:
368
case WMI_TPC_PREAM_VHT160:
369
mode_type = WMI_RATE_PREAMBLE_VHT;
370
break;
371
case WMI_TPC_PREAM_HE20:
372
case WMI_TPC_PREAM_HE40:
373
case WMI_TPC_PREAM_HE80:
374
case WMI_TPC_PREAM_HE160:
375
mode_type = WMI_RATE_PREAMBLE_HE;
376
break;
377
case WMI_TPC_PREAM_EHT20:
378
case WMI_TPC_PREAM_EHT40:
379
case WMI_TPC_PREAM_EHT60:
380
case WMI_TPC_PREAM_EHT80:
381
case WMI_TPC_PREAM_EHT120:
382
case WMI_TPC_PREAM_EHT140:
383
case WMI_TPC_PREAM_EHT160:
384
case WMI_TPC_PREAM_EHT200:
385
case WMI_TPC_PREAM_EHT240:
386
case WMI_TPC_PREAM_EHT280:
387
case WMI_TPC_PREAM_EHT320:
388
mode_type = WMI_RATE_PREAMBLE_EHT;
389
if (mcs_rate == 0 || mcs_rate == 1)
390
mcs_rate += 14;
391
else
392
mcs_rate -= 2;
393
break;
394
default:
395
return mode_type;
396
}
397
return ((mode_type << 8) | ((nss & 0x7) << 5) | (mcs_rate & 0x1F));
398
}
399
400
static bool ath12k_he_supports_extra_mcs(struct ath12k *ar, int freq)
401
{
402
struct ath12k_pdev_cap *cap = &ar->pdev->cap;
403
struct ath12k_band_cap *cap_band;
404
bool extra_mcs_supported;
405
406
if (freq <= ATH12K_2GHZ_MAX_FREQUENCY)
407
cap_band = &cap->band[NL80211_BAND_2GHZ];
408
else if (freq <= ATH12K_5GHZ_MAX_FREQUENCY)
409
cap_band = &cap->band[NL80211_BAND_5GHZ];
410
else
411
cap_band = &cap->band[NL80211_BAND_6GHZ];
412
413
extra_mcs_supported = u32_get_bits(cap_band->he_cap_info[1],
414
HE_EXTRA_MCS_SUPPORT);
415
return extra_mcs_supported;
416
}
417
418
static int ath12k_tpc_fill_pream(struct ath12k *ar, char *buf, int buf_len, int len,
419
enum wmi_tpc_pream_bw pream_bw, u32 max_rix,
420
int max_nss, int max_rates, int pream_type,
421
enum wmi_halphy_ctrl_path_stats_id tpc_type,
422
int rate_idx, int eht_rate_idx)
423
{
424
struct wmi_tpc_stats_arg *tpc_stats = ar->debug.tpc_stats;
425
int nss, rates, chains;
426
u8 active_tx_chains;
427
u16 rate_code;
428
s16 tpc;
429
430
static const char *const pream_str[] = {
431
[WMI_TPC_PREAM_CCK] = "CCK",
432
[WMI_TPC_PREAM_OFDM] = "OFDM",
433
[WMI_TPC_PREAM_HT20] = "HT20",
434
[WMI_TPC_PREAM_HT40] = "HT40",
435
[WMI_TPC_PREAM_VHT20] = "VHT20",
436
[WMI_TPC_PREAM_VHT40] = "VHT40",
437
[WMI_TPC_PREAM_VHT80] = "VHT80",
438
[WMI_TPC_PREAM_VHT160] = "VHT160",
439
[WMI_TPC_PREAM_HE20] = "HE20",
440
[WMI_TPC_PREAM_HE40] = "HE40",
441
[WMI_TPC_PREAM_HE80] = "HE80",
442
[WMI_TPC_PREAM_HE160] = "HE160",
443
[WMI_TPC_PREAM_EHT20] = "EHT20",
444
[WMI_TPC_PREAM_EHT40] = "EHT40",
445
[WMI_TPC_PREAM_EHT60] = "EHT60",
446
[WMI_TPC_PREAM_EHT80] = "EHT80",
447
[WMI_TPC_PREAM_EHT120] = "EHT120",
448
[WMI_TPC_PREAM_EHT140] = "EHT140",
449
[WMI_TPC_PREAM_EHT160] = "EHT160",
450
[WMI_TPC_PREAM_EHT200] = "EHT200",
451
[WMI_TPC_PREAM_EHT240] = "EHT240",
452
[WMI_TPC_PREAM_EHT280] = "EHT280",
453
[WMI_TPC_PREAM_EHT320] = "EHT320"};
454
455
active_tx_chains = ar->num_tx_chains;
456
457
for (nss = 0; nss < max_nss; nss++) {
458
for (rates = 0; rates < max_rates; rates++, rate_idx++, max_rix++) {
459
/* FW send extra MCS(10&11) for VHT and HE rates,
460
* this is not used. Hence skipping it here
461
*/
462
if (pream_type == WMI_RATE_PREAMBLE_VHT &&
463
rates > ATH12K_VHT_MCS_MAX)
464
continue;
465
466
if (pream_type == WMI_RATE_PREAMBLE_HE &&
467
rates > ATH12K_HE_MCS_MAX)
468
continue;
469
470
if (pream_type == WMI_RATE_PREAMBLE_EHT &&
471
rates > ATH12K_EHT_MCS_MAX)
472
continue;
473
474
rate_code = ath12k_get_ratecode(pream_bw, nss, rates);
475
len += scnprintf(buf + len, buf_len - len,
476
"%d\t %s\t 0x%03x\t", max_rix,
477
pream_str[pream_bw], rate_code);
478
479
for (chains = 0; chains < active_tx_chains; chains++) {
480
if (nss > chains) {
481
len += scnprintf(buf + len,
482
buf_len - len,
483
"\t%s", "NA");
484
} else {
485
tpc = ath12k_tpc_get_rate(ar, tpc_stats,
486
rate_idx, chains + 1,
487
rate_code, pream_bw,
488
tpc_type,
489
eht_rate_idx);
490
491
if (tpc == TPC_INVAL) {
492
len += scnprintf(buf + len,
493
buf_len - len, "\tNA");
494
} else {
495
len += scnprintf(buf + len,
496
buf_len - len, "\t%d",
497
tpc);
498
}
499
}
500
}
501
len += scnprintf(buf + len, buf_len - len, "\n");
502
503
if (pream_type == WMI_RATE_PREAMBLE_EHT)
504
/*For fetching the next eht rates pwr from rates array2*/
505
++eht_rate_idx;
506
}
507
}
508
509
return len;
510
}
511
512
static int ath12k_tpc_stats_print(struct ath12k *ar,
513
struct wmi_tpc_stats_arg *tpc_stats,
514
char *buf, size_t len,
515
enum wmi_halphy_ctrl_path_stats_id type)
516
{
517
u32 eht_idx = 0, pream_idx = 0, rate_pream_idx = 0, total_rates = 0, max_rix = 0;
518
u32 chan_freq, num_tx_chain, caps, i, j = 1;
519
size_t buf_len = ATH12K_TPC_STATS_BUF_SIZE;
520
u8 nss, active_tx_chains;
521
bool he_ext_mcs;
522
static const char *const type_str[WMI_HALPHY_PDEV_TX_STATS_MAX] = {
523
[WMI_HALPHY_PDEV_TX_SU_STATS] = "SU",
524
[WMI_HALPHY_PDEV_TX_SUTXBF_STATS] = "SU WITH TXBF",
525
[WMI_HALPHY_PDEV_TX_MU_STATS] = "MU",
526
[WMI_HALPHY_PDEV_TX_MUTXBF_STATS] = "MU WITH TXBF"};
527
528
u8 max_rates[WMI_TPC_PREAM_MAX] = {
529
[WMI_TPC_PREAM_CCK] = ATH12K_CCK_RATES,
530
[WMI_TPC_PREAM_OFDM] = ATH12K_OFDM_RATES,
531
[WMI_TPC_PREAM_HT20] = ATH12K_HT_RATES,
532
[WMI_TPC_PREAM_HT40] = ATH12K_HT_RATES,
533
[WMI_TPC_PREAM_VHT20] = ATH12K_VHT_RATES,
534
[WMI_TPC_PREAM_VHT40] = ATH12K_VHT_RATES,
535
[WMI_TPC_PREAM_VHT80] = ATH12K_VHT_RATES,
536
[WMI_TPC_PREAM_VHT160] = ATH12K_VHT_RATES,
537
[WMI_TPC_PREAM_HE20] = ATH12K_HE_RATES,
538
[WMI_TPC_PREAM_HE40] = ATH12K_HE_RATES,
539
[WMI_TPC_PREAM_HE80] = ATH12K_HE_RATES,
540
[WMI_TPC_PREAM_HE160] = ATH12K_HE_RATES,
541
[WMI_TPC_PREAM_EHT20] = ATH12K_EHT_RATES,
542
[WMI_TPC_PREAM_EHT40] = ATH12K_EHT_RATES,
543
[WMI_TPC_PREAM_EHT60] = ATH12K_EHT_RATES,
544
[WMI_TPC_PREAM_EHT80] = ATH12K_EHT_RATES,
545
[WMI_TPC_PREAM_EHT120] = ATH12K_EHT_RATES,
546
[WMI_TPC_PREAM_EHT140] = ATH12K_EHT_RATES,
547
[WMI_TPC_PREAM_EHT160] = ATH12K_EHT_RATES,
548
[WMI_TPC_PREAM_EHT200] = ATH12K_EHT_RATES,
549
[WMI_TPC_PREAM_EHT240] = ATH12K_EHT_RATES,
550
[WMI_TPC_PREAM_EHT280] = ATH12K_EHT_RATES,
551
[WMI_TPC_PREAM_EHT320] = ATH12K_EHT_RATES};
552
static const u8 max_nss[WMI_TPC_PREAM_MAX] = {
553
[WMI_TPC_PREAM_CCK] = ATH12K_NSS_1,
554
[WMI_TPC_PREAM_OFDM] = ATH12K_NSS_1,
555
[WMI_TPC_PREAM_HT20] = ATH12K_NSS_4,
556
[WMI_TPC_PREAM_HT40] = ATH12K_NSS_4,
557
[WMI_TPC_PREAM_VHT20] = ATH12K_NSS_8,
558
[WMI_TPC_PREAM_VHT40] = ATH12K_NSS_8,
559
[WMI_TPC_PREAM_VHT80] = ATH12K_NSS_8,
560
[WMI_TPC_PREAM_VHT160] = ATH12K_NSS_4,
561
[WMI_TPC_PREAM_HE20] = ATH12K_NSS_8,
562
[WMI_TPC_PREAM_HE40] = ATH12K_NSS_8,
563
[WMI_TPC_PREAM_HE80] = ATH12K_NSS_8,
564
[WMI_TPC_PREAM_HE160] = ATH12K_NSS_4,
565
[WMI_TPC_PREAM_EHT20] = ATH12K_NSS_4,
566
[WMI_TPC_PREAM_EHT40] = ATH12K_NSS_4,
567
[WMI_TPC_PREAM_EHT60] = ATH12K_NSS_4,
568
[WMI_TPC_PREAM_EHT80] = ATH12K_NSS_4,
569
[WMI_TPC_PREAM_EHT120] = ATH12K_NSS_4,
570
[WMI_TPC_PREAM_EHT140] = ATH12K_NSS_4,
571
[WMI_TPC_PREAM_EHT160] = ATH12K_NSS_4,
572
[WMI_TPC_PREAM_EHT200] = ATH12K_NSS_4,
573
[WMI_TPC_PREAM_EHT240] = ATH12K_NSS_4,
574
[WMI_TPC_PREAM_EHT280] = ATH12K_NSS_4,
575
[WMI_TPC_PREAM_EHT320] = ATH12K_NSS_4};
576
577
u16 rate_idx[WMI_TPC_PREAM_MAX] = {}, eht_rate_idx[WMI_TPC_PREAM_MAX] = {};
578
static const u8 pream_type[WMI_TPC_PREAM_MAX] = {
579
[WMI_TPC_PREAM_CCK] = WMI_RATE_PREAMBLE_CCK,
580
[WMI_TPC_PREAM_OFDM] = WMI_RATE_PREAMBLE_OFDM,
581
[WMI_TPC_PREAM_HT20] = WMI_RATE_PREAMBLE_HT,
582
[WMI_TPC_PREAM_HT40] = WMI_RATE_PREAMBLE_HT,
583
[WMI_TPC_PREAM_VHT20] = WMI_RATE_PREAMBLE_VHT,
584
[WMI_TPC_PREAM_VHT40] = WMI_RATE_PREAMBLE_VHT,
585
[WMI_TPC_PREAM_VHT80] = WMI_RATE_PREAMBLE_VHT,
586
[WMI_TPC_PREAM_VHT160] = WMI_RATE_PREAMBLE_VHT,
587
[WMI_TPC_PREAM_HE20] = WMI_RATE_PREAMBLE_HE,
588
[WMI_TPC_PREAM_HE40] = WMI_RATE_PREAMBLE_HE,
589
[WMI_TPC_PREAM_HE80] = WMI_RATE_PREAMBLE_HE,
590
[WMI_TPC_PREAM_HE160] = WMI_RATE_PREAMBLE_HE,
591
[WMI_TPC_PREAM_EHT20] = WMI_RATE_PREAMBLE_EHT,
592
[WMI_TPC_PREAM_EHT40] = WMI_RATE_PREAMBLE_EHT,
593
[WMI_TPC_PREAM_EHT60] = WMI_RATE_PREAMBLE_EHT,
594
[WMI_TPC_PREAM_EHT80] = WMI_RATE_PREAMBLE_EHT,
595
[WMI_TPC_PREAM_EHT120] = WMI_RATE_PREAMBLE_EHT,
596
[WMI_TPC_PREAM_EHT140] = WMI_RATE_PREAMBLE_EHT,
597
[WMI_TPC_PREAM_EHT160] = WMI_RATE_PREAMBLE_EHT,
598
[WMI_TPC_PREAM_EHT200] = WMI_RATE_PREAMBLE_EHT,
599
[WMI_TPC_PREAM_EHT240] = WMI_RATE_PREAMBLE_EHT,
600
[WMI_TPC_PREAM_EHT280] = WMI_RATE_PREAMBLE_EHT,
601
[WMI_TPC_PREAM_EHT320] = WMI_RATE_PREAMBLE_EHT};
602
603
chan_freq = le32_to_cpu(tpc_stats->tpc_config.chan_freq);
604
num_tx_chain = le32_to_cpu(tpc_stats->tpc_config.num_tx_chain);
605
caps = le32_to_cpu(tpc_stats->tpc_config.caps);
606
607
active_tx_chains = ar->num_tx_chains;
608
he_ext_mcs = ath12k_he_supports_extra_mcs(ar, chan_freq);
609
610
/* mcs 12&13 is sent by FW for certain HWs in rate array, skipping it as
611
* it is not supported
612
*/
613
if (he_ext_mcs) {
614
for (i = WMI_TPC_PREAM_HE20; i <= WMI_TPC_PREAM_HE160; ++i)
615
max_rates[i] = ATH12K_HE_RATES;
616
}
617
618
if (type == WMI_HALPHY_PDEV_TX_MU_STATS ||
619
type == WMI_HALPHY_PDEV_TX_MUTXBF_STATS) {
620
pream_idx = WMI_TPC_PREAM_VHT20;
621
622
for (i = WMI_TPC_PREAM_CCK; i <= WMI_TPC_PREAM_HT40; ++i)
623
max_rix += max_nss[i] * max_rates[i];
624
}
625
/* Enumerate all the rate indices */
626
for (i = rate_pream_idx + 1; i < WMI_TPC_PREAM_MAX; i++) {
627
nss = (max_nss[i - 1] < num_tx_chain ?
628
max_nss[i - 1] : num_tx_chain);
629
630
rate_idx[i] = rate_idx[i - 1] + max_rates[i - 1] * nss;
631
632
if (pream_type[i] == WMI_RATE_PREAMBLE_EHT) {
633
eht_rate_idx[j] = eht_rate_idx[j - 1] + max_rates[i] * nss;
634
++j;
635
}
636
}
637
638
for (i = 0; i < WMI_TPC_PREAM_MAX; i++) {
639
nss = (max_nss[i] < num_tx_chain ?
640
max_nss[i] : num_tx_chain);
641
total_rates += max_rates[i] * nss;
642
}
643
644
len += scnprintf(buf + len, buf_len - len,
645
"No.of rates-%d\n", total_rates);
646
647
len += scnprintf(buf + len, buf_len - len,
648
"**************** %s ****************\n",
649
type_str[type]);
650
len += scnprintf(buf + len, buf_len - len,
651
"\t\t\t\tTPC values for Active chains\n");
652
len += scnprintf(buf + len, buf_len - len,
653
"Rate idx Preamble Rate code");
654
655
for (i = 1; i <= active_tx_chains; ++i) {
656
len += scnprintf(buf + len, buf_len - len,
657
"\t%d-Chain", i);
658
}
659
660
len += scnprintf(buf + len, buf_len - len, "\n");
661
for (i = pream_idx; i < WMI_TPC_PREAM_MAX; i++) {
662
if (chan_freq <= 2483) {
663
if (i == WMI_TPC_PREAM_VHT80 ||
664
i == WMI_TPC_PREAM_VHT160 ||
665
i == WMI_TPC_PREAM_HE80 ||
666
i == WMI_TPC_PREAM_HE160 ||
667
(i >= WMI_TPC_PREAM_EHT60 &&
668
i <= WMI_TPC_PREAM_EHT320)) {
669
max_rix += max_nss[i] * max_rates[i];
670
continue;
671
}
672
} else {
673
if (i == WMI_TPC_PREAM_CCK) {
674
max_rix += max_rates[i];
675
continue;
676
}
677
}
678
679
nss = (max_nss[i] < ar->num_tx_chains ? max_nss[i] : ar->num_tx_chains);
680
681
if (!(caps &
682
(1 << ATH12K_TPC_STATS_SUPPORT_BE_PUNC))) {
683
if (i == WMI_TPC_PREAM_EHT60 || i == WMI_TPC_PREAM_EHT120 ||
684
i == WMI_TPC_PREAM_EHT140 || i == WMI_TPC_PREAM_EHT200 ||
685
i == WMI_TPC_PREAM_EHT240 || i == WMI_TPC_PREAM_EHT280) {
686
max_rix += max_nss[i] * max_rates[i];
687
continue;
688
}
689
}
690
691
len = ath12k_tpc_fill_pream(ar, buf, buf_len, len, i, max_rix, nss,
692
max_rates[i], pream_type[i],
693
type, rate_idx[i], eht_rate_idx[eht_idx]);
694
695
if (pream_type[i] == WMI_RATE_PREAMBLE_EHT)
696
/*For fetch the next index eht rates from rates array2*/
697
++eht_idx;
698
699
max_rix += max_nss[i] * max_rates[i];
700
}
701
return len;
702
}
703
704
static void ath12k_tpc_stats_fill(struct ath12k *ar,
705
struct wmi_tpc_stats_arg *tpc_stats,
706
char *buf)
707
{
708
size_t buf_len = ATH12K_TPC_STATS_BUF_SIZE;
709
struct wmi_tpc_config_params *tpc;
710
size_t len = 0;
711
712
if (!tpc_stats) {
713
ath12k_warn(ar->ab, "failed to find tpc stats\n");
714
return;
715
}
716
717
spin_lock_bh(&ar->data_lock);
718
719
tpc = &tpc_stats->tpc_config;
720
len += scnprintf(buf + len, buf_len - len, "\n");
721
len += scnprintf(buf + len, buf_len - len,
722
"*************** TPC config **************\n");
723
len += scnprintf(buf + len, buf_len - len,
724
"* powers are in 0.25 dBm steps\n");
725
len += scnprintf(buf + len, buf_len - len,
726
"reg domain-%d\t\tchan freq-%d\n",
727
tpc->reg_domain, tpc->chan_freq);
728
len += scnprintf(buf + len, buf_len - len,
729
"power limit-%d\t\tmax reg-domain Power-%d\n",
730
le32_to_cpu(tpc->twice_max_reg_power) / 2, tpc->power_limit);
731
len += scnprintf(buf + len, buf_len - len,
732
"No.of tx chain-%d\t",
733
ar->num_tx_chains);
734
735
ath12k_tpc_stats_print(ar, tpc_stats, buf, len,
736
ar->debug.tpc_stats_type);
737
738
spin_unlock_bh(&ar->data_lock);
739
}
740
741
static int ath12k_open_tpc_stats(struct inode *inode, struct file *file)
742
{
743
struct ath12k *ar = inode->i_private;
744
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
745
int ret;
746
747
guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
748
749
if (ah->state != ATH12K_HW_STATE_ON) {
750
ath12k_warn(ar->ab, "Interface not up\n");
751
return -ENETDOWN;
752
}
753
754
void *buf __free(kfree) = kzalloc(ATH12K_TPC_STATS_BUF_SIZE, GFP_KERNEL);
755
if (!buf)
756
return -ENOMEM;
757
758
ret = ath12k_debug_tpc_stats_request(ar);
759
if (ret) {
760
ath12k_warn(ar->ab, "failed to request tpc stats: %d\n",
761
ret);
762
return ret;
763
}
764
765
if (!wait_for_completion_timeout(&ar->debug.tpc_complete, TPC_STATS_WAIT_TIME)) {
766
spin_lock_bh(&ar->data_lock);
767
ath12k_wmi_free_tpc_stats_mem(ar);
768
ar->debug.tpc_request = false;
769
spin_unlock_bh(&ar->data_lock);
770
return -ETIMEDOUT;
771
}
772
773
ath12k_tpc_stats_fill(ar, ar->debug.tpc_stats, buf);
774
file->private_data = no_free_ptr(buf);
775
776
spin_lock_bh(&ar->data_lock);
777
ath12k_wmi_free_tpc_stats_mem(ar);
778
spin_unlock_bh(&ar->data_lock);
779
780
return 0;
781
}
782
783
static ssize_t ath12k_read_tpc_stats(struct file *file,
784
char __user *user_buf,
785
size_t count, loff_t *ppos)
786
{
787
const char *buf = file->private_data;
788
size_t len = strlen(buf);
789
790
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
791
}
792
793
static int ath12k_release_tpc_stats(struct inode *inode,
794
struct file *file)
795
{
796
kfree(file->private_data);
797
return 0;
798
}
799
800
static const struct file_operations fops_tpc_stats = {
801
.open = ath12k_open_tpc_stats,
802
.release = ath12k_release_tpc_stats,
803
.read = ath12k_read_tpc_stats,
804
.owner = THIS_MODULE,
805
.llseek = default_llseek,
806
};
807
808
static const struct file_operations fops_tpc_stats_type = {
809
.write = ath12k_write_tpc_stats_type,
810
.open = simple_open,
811
.llseek = default_llseek,
812
};
813
814
static ssize_t ath12k_write_extd_rx_stats(struct file *file,
815
const char __user *ubuf,
816
size_t count, loff_t *ppos)
817
{
818
struct ath12k *ar = file->private_data;
819
struct htt_rx_ring_tlv_filter tlv_filter = {};
820
u32 ring_id, rx_filter = 0;
821
bool enable;
822
int ret, i;
823
824
if (kstrtobool_from_user(ubuf, count, &enable))
825
return -EINVAL;
826
827
wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
828
829
if (!ar->ab->hw_params->rxdma1_enable) {
830
ret = count;
831
goto exit;
832
}
833
834
if (ar->ah->state != ATH12K_HW_STATE_ON) {
835
ret = -ENETDOWN;
836
goto exit;
837
}
838
839
if (enable == ar->debug.extd_rx_stats) {
840
ret = count;
841
goto exit;
842
}
843
844
if (enable) {
845
rx_filter = HTT_RX_FILTER_TLV_FLAGS_MPDU_START;
846
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START;
847
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END;
848
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS;
849
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_USER_STATS_EXT;
850
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_END_STATUS_DONE;
851
rx_filter |= HTT_RX_FILTER_TLV_FLAGS_PPDU_START_USER_INFO;
852
853
tlv_filter.rx_filter = rx_filter;
854
tlv_filter.pkt_filter_flags0 = HTT_RX_FP_MGMT_FILTER_FLAGS0;
855
tlv_filter.pkt_filter_flags1 = HTT_RX_FP_MGMT_FILTER_FLAGS1;
856
tlv_filter.pkt_filter_flags2 = HTT_RX_FP_CTRL_FILTER_FLASG2;
857
tlv_filter.pkt_filter_flags3 = HTT_RX_FP_CTRL_FILTER_FLASG3 |
858
HTT_RX_FP_DATA_FILTER_FLASG3;
859
} else {
860
tlv_filter = ath12k_mac_mon_status_filter_default;
861
}
862
863
ar->debug.rx_filter = tlv_filter.rx_filter;
864
865
for (i = 0; i < ar->ab->hw_params->num_rxdma_per_pdev; i++) {
866
ring_id = ar->dp.rxdma_mon_dst_ring[i].ring_id;
867
ret = ath12k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id + i,
868
HAL_RXDMA_MONITOR_DST,
869
DP_RXDMA_REFILL_RING_SIZE,
870
&tlv_filter);
871
if (ret) {
872
ath12k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
873
goto exit;
874
}
875
}
876
877
ar->debug.extd_rx_stats = !!enable;
878
ret = count;
879
exit:
880
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
881
return ret;
882
}
883
884
static ssize_t ath12k_read_extd_rx_stats(struct file *file,
885
char __user *ubuf,
886
size_t count, loff_t *ppos)
887
{
888
struct ath12k *ar = file->private_data;
889
char buf[32];
890
int len = 0;
891
892
wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
893
len = scnprintf(buf, sizeof(buf) - len, "%d\n",
894
ar->debug.extd_rx_stats);
895
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
896
897
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
898
}
899
900
static const struct file_operations fops_extd_rx_stats = {
901
.read = ath12k_read_extd_rx_stats,
902
.write = ath12k_write_extd_rx_stats,
903
.open = simple_open,
904
};
905
906
static int ath12k_open_link_stats(struct inode *inode, struct file *file)
907
{
908
struct ath12k_vif *ahvif = inode->i_private;
909
size_t len = 0, buf_len = (PAGE_SIZE * 2);
910
struct ath12k_link_stats linkstat;
911
struct ath12k_link_vif *arvif;
912
unsigned long links_map;
913
struct wiphy *wiphy;
914
int link_id, i;
915
char *buf;
916
917
if (!ahvif)
918
return -EINVAL;
919
920
buf = kzalloc(buf_len, GFP_KERNEL);
921
if (!buf)
922
return -ENOMEM;
923
924
wiphy = ahvif->ah->hw->wiphy;
925
wiphy_lock(wiphy);
926
927
links_map = ahvif->links_map;
928
for_each_set_bit(link_id, &links_map,
929
IEEE80211_MLD_MAX_NUM_LINKS) {
930
arvif = rcu_dereference_protected(ahvif->link[link_id],
931
lockdep_is_held(&wiphy->mtx));
932
933
spin_lock_bh(&arvif->link_stats_lock);
934
linkstat = arvif->link_stats;
935
spin_unlock_bh(&arvif->link_stats_lock);
936
937
len += scnprintf(buf + len, buf_len - len,
938
"link[%d] Tx Unicast Frames Enqueued = %d\n",
939
link_id, linkstat.tx_enqueued);
940
len += scnprintf(buf + len, buf_len - len,
941
"link[%d] Tx Broadcast Frames Enqueued = %d\n",
942
link_id, linkstat.tx_bcast_mcast);
943
len += scnprintf(buf + len, buf_len - len,
944
"link[%d] Tx Frames Completed = %d\n",
945
link_id, linkstat.tx_completed);
946
len += scnprintf(buf + len, buf_len - len,
947
"link[%d] Tx Frames Dropped = %d\n",
948
link_id, linkstat.tx_dropped);
949
950
len += scnprintf(buf + len, buf_len - len,
951
"link[%d] Tx Frame descriptor Encap Type = ",
952
link_id);
953
954
len += scnprintf(buf + len, buf_len - len,
955
" raw:%d",
956
linkstat.tx_encap_type[0]);
957
958
len += scnprintf(buf + len, buf_len - len,
959
" native_wifi:%d",
960
linkstat.tx_encap_type[1]);
961
962
len += scnprintf(buf + len, buf_len - len,
963
" ethernet:%d",
964
linkstat.tx_encap_type[2]);
965
966
len += scnprintf(buf + len, buf_len - len,
967
"\nlink[%d] Tx Frame descriptor Encrypt Type = ",
968
link_id);
969
970
for (i = 0; i < HAL_ENCRYPT_TYPE_MAX; i++) {
971
len += scnprintf(buf + len, buf_len - len,
972
" %d:%d", i,
973
linkstat.tx_encrypt_type[i]);
974
}
975
len += scnprintf(buf + len, buf_len - len,
976
"\nlink[%d] Tx Frame descriptor Type = buffer:%d extension:%d\n",
977
link_id, linkstat.tx_desc_type[0],
978
linkstat.tx_desc_type[1]);
979
980
len += scnprintf(buf + len, buf_len - len,
981
"------------------------------------------------------\n");
982
}
983
984
wiphy_unlock(wiphy);
985
986
file->private_data = buf;
987
988
return 0;
989
}
990
991
static int ath12k_release_link_stats(struct inode *inode, struct file *file)
992
{
993
kfree(file->private_data);
994
return 0;
995
}
996
997
static ssize_t ath12k_read_link_stats(struct file *file,
998
char __user *user_buf,
999
size_t count, loff_t *ppos)
1000
{
1001
const char *buf = file->private_data;
1002
size_t len = strlen(buf);
1003
1004
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1005
}
1006
1007
static const struct file_operations ath12k_fops_link_stats = {
1008
.open = ath12k_open_link_stats,
1009
.release = ath12k_release_link_stats,
1010
.read = ath12k_read_link_stats,
1011
.owner = THIS_MODULE,
1012
.llseek = default_llseek,
1013
};
1014
1015
void ath12k_debugfs_op_vif_add(struct ieee80211_hw *hw,
1016
struct ieee80211_vif *vif)
1017
{
1018
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
1019
1020
debugfs_create_file("link_stats", 0400, vif->debugfs_dir, ahvif,
1021
&ath12k_fops_link_stats);
1022
}
1023
1024
static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,
1025
char __user *user_buf,
1026
size_t count, loff_t *ppos)
1027
{
1028
struct ath12k_base *ab = file->private_data;
1029
struct ath12k_device_dp_stats *device_stats = &ab->device_stats;
1030
int len = 0, i, j, ret;
1031
struct ath12k *ar;
1032
const int size = 4096;
1033
static const char *rxdma_err[HAL_REO_ENTR_RING_RXDMA_ECODE_MAX] = {
1034
[HAL_REO_ENTR_RING_RXDMA_ECODE_OVERFLOW_ERR] = "Overflow",
1035
[HAL_REO_ENTR_RING_RXDMA_ECODE_MPDU_LEN_ERR] = "MPDU len",
1036
[HAL_REO_ENTR_RING_RXDMA_ECODE_FCS_ERR] = "FCS",
1037
[HAL_REO_ENTR_RING_RXDMA_ECODE_DECRYPT_ERR] = "Decrypt",
1038
[HAL_REO_ENTR_RING_RXDMA_ECODE_TKIP_MIC_ERR] = "TKIP MIC",
1039
[HAL_REO_ENTR_RING_RXDMA_ECODE_UNECRYPTED_ERR] = "Unencrypt",
1040
[HAL_REO_ENTR_RING_RXDMA_ECODE_MSDU_LEN_ERR] = "MSDU len",
1041
[HAL_REO_ENTR_RING_RXDMA_ECODE_MSDU_LIMIT_ERR] = "MSDU limit",
1042
[HAL_REO_ENTR_RING_RXDMA_ECODE_WIFI_PARSE_ERR] = "WiFi parse",
1043
[HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_PARSE_ERR] = "AMSDU parse",
1044
[HAL_REO_ENTR_RING_RXDMA_ECODE_SA_TIMEOUT_ERR] = "SA timeout",
1045
[HAL_REO_ENTR_RING_RXDMA_ECODE_DA_TIMEOUT_ERR] = "DA timeout",
1046
[HAL_REO_ENTR_RING_RXDMA_ECODE_FLOW_TIMEOUT_ERR] = "Flow timeout",
1047
[HAL_REO_ENTR_RING_RXDMA_ECODE_FLUSH_REQUEST_ERR] = "Flush req",
1048
[HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_FRAG_ERR] = "AMSDU frag",
1049
[HAL_REO_ENTR_RING_RXDMA_ECODE_MULTICAST_ECHO_ERR] = "Multicast echo",
1050
[HAL_REO_ENTR_RING_RXDMA_ECODE_AMSDU_MISMATCH_ERR] = "AMSDU mismatch",
1051
[HAL_REO_ENTR_RING_RXDMA_ECODE_UNAUTH_WDS_ERR] = "Unauth WDS",
1052
[HAL_REO_ENTR_RING_RXDMA_ECODE_GRPCAST_AMSDU_WDS_ERR] = "AMSDU or WDS"};
1053
1054
static const char *reo_err[HAL_REO_DEST_RING_ERROR_CODE_MAX] = {
1055
[HAL_REO_DEST_RING_ERROR_CODE_DESC_ADDR_ZERO] = "Desc addr zero",
1056
[HAL_REO_DEST_RING_ERROR_CODE_DESC_INVALID] = "Desc inval",
1057
[HAL_REO_DEST_RING_ERROR_CODE_AMPDU_IN_NON_BA] = "AMPDU in non BA",
1058
[HAL_REO_DEST_RING_ERROR_CODE_NON_BA_DUPLICATE] = "Non BA dup",
1059
[HAL_REO_DEST_RING_ERROR_CODE_BA_DUPLICATE] = "BA dup",
1060
[HAL_REO_DEST_RING_ERROR_CODE_FRAME_2K_JUMP] = "Frame 2k jump",
1061
[HAL_REO_DEST_RING_ERROR_CODE_BAR_2K_JUMP] = "BAR 2k jump",
1062
[HAL_REO_DEST_RING_ERROR_CODE_FRAME_OOR] = "Frame OOR",
1063
[HAL_REO_DEST_RING_ERROR_CODE_BAR_OOR] = "BAR OOR",
1064
[HAL_REO_DEST_RING_ERROR_CODE_NO_BA_SESSION] = "No BA session",
1065
[HAL_REO_DEST_RING_ERROR_CODE_FRAME_SN_EQUALS_SSN] = "Frame SN equal SSN",
1066
[HAL_REO_DEST_RING_ERROR_CODE_PN_CHECK_FAILED] = "PN check fail",
1067
[HAL_REO_DEST_RING_ERROR_CODE_2K_ERR_FLAG_SET] = "2k err",
1068
[HAL_REO_DEST_RING_ERROR_CODE_PN_ERR_FLAG_SET] = "PN err",
1069
[HAL_REO_DEST_RING_ERROR_CODE_DESC_BLOCKED] = "Desc blocked"};
1070
1071
static const char *wbm_rel_src[HAL_WBM_REL_SRC_MODULE_MAX] = {
1072
[HAL_WBM_REL_SRC_MODULE_TQM] = "TQM",
1073
[HAL_WBM_REL_SRC_MODULE_RXDMA] = "Rxdma",
1074
[HAL_WBM_REL_SRC_MODULE_REO] = "Reo",
1075
[HAL_WBM_REL_SRC_MODULE_FW] = "FW",
1076
[HAL_WBM_REL_SRC_MODULE_SW] = "SW"};
1077
1078
char *buf __free(kfree) = kzalloc(size, GFP_KERNEL);
1079
1080
if (!buf)
1081
return -ENOMEM;
1082
1083
len += scnprintf(buf + len, size - len, "DEVICE RX STATS:\n\n");
1084
len += scnprintf(buf + len, size - len, "err ring pkts: %u\n",
1085
device_stats->err_ring_pkts);
1086
len += scnprintf(buf + len, size - len, "Invalid RBM: %u\n\n",
1087
device_stats->invalid_rbm);
1088
len += scnprintf(buf + len, size - len, "RXDMA errors:\n");
1089
1090
for (i = 0; i < HAL_REO_ENTR_RING_RXDMA_ECODE_MAX; i++)
1091
len += scnprintf(buf + len, size - len, "%s: %u\n",
1092
rxdma_err[i], device_stats->rxdma_error[i]);
1093
1094
len += scnprintf(buf + len, size - len, "\nREO errors:\n");
1095
1096
for (i = 0; i < HAL_REO_DEST_RING_ERROR_CODE_MAX; i++)
1097
len += scnprintf(buf + len, size - len, "%s: %u\n",
1098
reo_err[i], device_stats->reo_error[i]);
1099
1100
len += scnprintf(buf + len, size - len, "\nHAL REO errors:\n");
1101
1102
for (i = 0; i < DP_REO_DST_RING_MAX; i++)
1103
len += scnprintf(buf + len, size - len,
1104
"ring%d: %u\n", i,
1105
device_stats->hal_reo_error[i]);
1106
1107
len += scnprintf(buf + len, size - len, "\nDEVICE TX STATS:\n");
1108
len += scnprintf(buf + len, size - len, "\nTCL Ring Full Failures:\n");
1109
1110
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
1111
len += scnprintf(buf + len, size - len, "ring%d: %u\n",
1112
i, device_stats->tx_err.desc_na[i]);
1113
1114
len += scnprintf(buf + len, size - len,
1115
"\nMisc Transmit Failures: %d\n",
1116
atomic_read(&device_stats->tx_err.misc_fail));
1117
1118
len += scnprintf(buf + len, size - len, "\ntx_wbm_rel_source:");
1119
1120
for (i = 0; i < HAL_WBM_REL_SRC_MODULE_MAX; i++)
1121
len += scnprintf(buf + len, size - len, " %d:%u",
1122
i, device_stats->tx_wbm_rel_source[i]);
1123
1124
len += scnprintf(buf + len, size - len, "\n");
1125
1126
len += scnprintf(buf + len, size - len, "\ntqm_rel_reason:");
1127
1128
for (i = 0; i < MAX_TQM_RELEASE_REASON; i++)
1129
len += scnprintf(buf + len, size - len, " %d:%u",
1130
i, device_stats->tqm_rel_reason[i]);
1131
1132
len += scnprintf(buf + len, size - len, "\n");
1133
1134
len += scnprintf(buf + len, size - len, "\nfw_tx_status:");
1135
1136
for (i = 0; i < MAX_FW_TX_STATUS; i++)
1137
len += scnprintf(buf + len, size - len, " %d:%u",
1138
i, device_stats->fw_tx_status[i]);
1139
1140
len += scnprintf(buf + len, size - len, "\n");
1141
1142
len += scnprintf(buf + len, size - len, "\ntx_enqueued:");
1143
1144
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
1145
len += scnprintf(buf + len, size - len, " %d:%u", i,
1146
device_stats->tx_enqueued[i]);
1147
1148
len += scnprintf(buf + len, size - len, "\n");
1149
1150
len += scnprintf(buf + len, size - len, "\ntx_completed:");
1151
1152
for (i = 0; i < DP_TCL_NUM_RING_MAX; i++)
1153
len += scnprintf(buf + len, size - len, " %d:%u",
1154
i, device_stats->tx_completed[i]);
1155
1156
len += scnprintf(buf + len, size - len, "\n");
1157
1158
for (i = 0; i < ab->num_radios; i++) {
1159
ar = ath12k_mac_get_ar_by_pdev_id(ab, DP_SW2HW_MACID(i));
1160
if (ar) {
1161
len += scnprintf(buf + len, size - len,
1162
"\nradio%d tx_pending: %u\n", i,
1163
atomic_read(&ar->dp.num_tx_pending));
1164
}
1165
}
1166
1167
len += scnprintf(buf + len, size - len, "\nREO Rx Received:\n");
1168
1169
for (i = 0; i < DP_REO_DST_RING_MAX; i++) {
1170
len += scnprintf(buf + len, size - len, "Ring%d:", i + 1);
1171
1172
for (j = 0; j < ATH12K_MAX_DEVICES; j++) {
1173
len += scnprintf(buf + len, size - len,
1174
"\t%d:%u", j,
1175
device_stats->reo_rx[i][j]);
1176
}
1177
1178
len += scnprintf(buf + len, size - len, "\n");
1179
}
1180
1181
len += scnprintf(buf + len, size - len, "\nREO excep MSDU buf type:%u\n",
1182
device_stats->reo_excep_msdu_buf_type);
1183
1184
len += scnprintf(buf + len, size - len, "\nRx WBM REL SRC Errors:\n");
1185
1186
for (i = 0; i < HAL_WBM_REL_SRC_MODULE_MAX; i++) {
1187
len += scnprintf(buf + len, size - len, "%s:", wbm_rel_src[i]);
1188
1189
for (j = 0; j < ATH12K_MAX_DEVICES; j++) {
1190
len += scnprintf(buf + len,
1191
size - len,
1192
"\t%d:%u", j,
1193
device_stats->rx_wbm_rel_source[i][j]);
1194
}
1195
1196
len += scnprintf(buf + len, size - len, "\n");
1197
}
1198
1199
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1200
1201
return ret;
1202
}
1203
1204
static const struct file_operations fops_device_dp_stats = {
1205
.read = ath12k_debugfs_dump_device_dp_stats,
1206
.open = simple_open,
1207
.owner = THIS_MODULE,
1208
.llseek = default_llseek,
1209
};
1210
1211
void ath12k_debugfs_pdev_create(struct ath12k_base *ab)
1212
{
1213
debugfs_create_file("simulate_fw_crash", 0600, ab->debugfs_soc, ab,
1214
&fops_simulate_fw_crash);
1215
1216
debugfs_create_file("device_dp_stats", 0400, ab->debugfs_soc, ab,
1217
&fops_device_dp_stats);
1218
}
1219
1220
void ath12k_debugfs_soc_create(struct ath12k_base *ab)
1221
{
1222
bool dput_needed;
1223
char soc_name[64] = {};
1224
struct dentry *debugfs_ath12k;
1225
1226
debugfs_ath12k = debugfs_lookup("ath12k", NULL);
1227
if (debugfs_ath12k) {
1228
/* a dentry from lookup() needs dput() after we don't use it */
1229
dput_needed = true;
1230
} else {
1231
debugfs_ath12k = debugfs_create_dir("ath12k", NULL);
1232
if (IS_ERR_OR_NULL(debugfs_ath12k))
1233
return;
1234
dput_needed = false;
1235
}
1236
1237
scnprintf(soc_name, sizeof(soc_name), "%s-%s", ath12k_bus_str(ab->hif.bus),
1238
dev_name(ab->dev));
1239
1240
ab->debugfs_soc = debugfs_create_dir(soc_name, debugfs_ath12k);
1241
1242
if (dput_needed)
1243
dput(debugfs_ath12k);
1244
}
1245
1246
void ath12k_debugfs_soc_destroy(struct ath12k_base *ab)
1247
{
1248
debugfs_remove_recursive(ab->debugfs_soc);
1249
ab->debugfs_soc = NULL;
1250
/* We are not removing ath12k directory on purpose, even if it
1251
* would be empty. This simplifies the directory handling and it's
1252
* a minor cosmetic issue to leave an empty ath12k directory to
1253
* debugfs.
1254
*/
1255
}
1256
1257
static int ath12k_open_vdev_stats(struct inode *inode, struct file *file)
1258
{
1259
struct ath12k *ar = inode->i_private;
1260
struct ath12k_fw_stats_req_params param;
1261
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
1262
int ret;
1263
1264
guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
1265
1266
if (!ah)
1267
return -ENETDOWN;
1268
1269
if (ah->state != ATH12K_HW_STATE_ON)
1270
return -ENETDOWN;
1271
1272
void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC);
1273
if (!buf)
1274
return -ENOMEM;
1275
1276
param.pdev_id = ath12k_mac_get_target_pdev_id(ar);
1277
/* VDEV stats is always sent for all active VDEVs from FW */
1278
param.vdev_id = 0;
1279
param.stats_id = WMI_REQUEST_VDEV_STAT;
1280
1281
ret = ath12k_mac_get_fw_stats(ar, &param);
1282
if (ret) {
1283
ath12k_warn(ar->ab, "failed to request fw vdev stats: %d\n", ret);
1284
return ret;
1285
}
1286
1287
ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id,
1288
buf);
1289
ath12k_fw_stats_reset(ar);
1290
1291
file->private_data = no_free_ptr(buf);
1292
1293
return 0;
1294
}
1295
1296
static int ath12k_release_vdev_stats(struct inode *inode, struct file *file)
1297
{
1298
kfree(file->private_data);
1299
1300
return 0;
1301
}
1302
1303
static ssize_t ath12k_read_vdev_stats(struct file *file,
1304
char __user *user_buf,
1305
size_t count, loff_t *ppos)
1306
{
1307
const char *buf = file->private_data;
1308
size_t len = strlen(buf);
1309
1310
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1311
}
1312
1313
static const struct file_operations fops_vdev_stats = {
1314
.open = ath12k_open_vdev_stats,
1315
.release = ath12k_release_vdev_stats,
1316
.read = ath12k_read_vdev_stats,
1317
.owner = THIS_MODULE,
1318
.llseek = default_llseek,
1319
};
1320
1321
static int ath12k_open_bcn_stats(struct inode *inode, struct file *file)
1322
{
1323
struct ath12k *ar = inode->i_private;
1324
struct ath12k_link_vif *arvif;
1325
struct ath12k_fw_stats_req_params param;
1326
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
1327
int ret;
1328
1329
guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
1330
1331
if (ah && ah->state != ATH12K_HW_STATE_ON)
1332
return -ENETDOWN;
1333
1334
void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC);
1335
if (!buf)
1336
return -ENOMEM;
1337
1338
param.pdev_id = ath12k_mac_get_target_pdev_id(ar);
1339
param.stats_id = WMI_REQUEST_BCN_STAT;
1340
1341
/* loop all active VDEVs for bcn stats */
1342
list_for_each_entry(arvif, &ar->arvifs, list) {
1343
if (!arvif->is_up)
1344
continue;
1345
1346
param.vdev_id = arvif->vdev_id;
1347
ret = ath12k_mac_get_fw_stats(ar, &param);
1348
if (ret) {
1349
ath12k_warn(ar->ab, "failed to request fw bcn stats: %d\n", ret);
1350
return ret;
1351
}
1352
}
1353
1354
ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id,
1355
buf);
1356
ath12k_fw_stats_reset(ar);
1357
1358
file->private_data = no_free_ptr(buf);
1359
1360
return 0;
1361
}
1362
1363
static int ath12k_release_bcn_stats(struct inode *inode, struct file *file)
1364
{
1365
kfree(file->private_data);
1366
1367
return 0;
1368
}
1369
1370
static ssize_t ath12k_read_bcn_stats(struct file *file,
1371
char __user *user_buf,
1372
size_t count, loff_t *ppos)
1373
{
1374
const char *buf = file->private_data;
1375
size_t len = strlen(buf);
1376
1377
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1378
}
1379
1380
static const struct file_operations fops_bcn_stats = {
1381
.open = ath12k_open_bcn_stats,
1382
.release = ath12k_release_bcn_stats,
1383
.read = ath12k_read_bcn_stats,
1384
.owner = THIS_MODULE,
1385
.llseek = default_llseek,
1386
};
1387
1388
static int ath12k_open_pdev_stats(struct inode *inode, struct file *file)
1389
{
1390
struct ath12k *ar = inode->i_private;
1391
struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
1392
struct ath12k_base *ab = ar->ab;
1393
struct ath12k_fw_stats_req_params param;
1394
int ret;
1395
1396
guard(wiphy)(ath12k_ar_to_hw(ar)->wiphy);
1397
1398
if (ah && ah->state != ATH12K_HW_STATE_ON)
1399
return -ENETDOWN;
1400
1401
void *buf __free(kfree) = kzalloc(ATH12K_FW_STATS_BUF_SIZE, GFP_ATOMIC);
1402
if (!buf)
1403
return -ENOMEM;
1404
1405
param.pdev_id = ath12k_mac_get_target_pdev_id(ar);
1406
param.vdev_id = 0;
1407
param.stats_id = WMI_REQUEST_PDEV_STAT;
1408
1409
ret = ath12k_mac_get_fw_stats(ar, &param);
1410
if (ret) {
1411
ath12k_warn(ab, "failed to request fw pdev stats: %d\n", ret);
1412
return ret;
1413
}
1414
1415
ath12k_wmi_fw_stats_dump(ar, &ar->fw_stats, param.stats_id,
1416
buf);
1417
ath12k_fw_stats_reset(ar);
1418
1419
file->private_data = no_free_ptr(buf);
1420
1421
return 0;
1422
}
1423
1424
static int ath12k_release_pdev_stats(struct inode *inode, struct file *file)
1425
{
1426
kfree(file->private_data);
1427
1428
return 0;
1429
}
1430
1431
static ssize_t ath12k_read_pdev_stats(struct file *file,
1432
char __user *user_buf,
1433
size_t count, loff_t *ppos)
1434
{
1435
const char *buf = file->private_data;
1436
size_t len = strlen(buf);
1437
1438
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1439
}
1440
1441
static const struct file_operations fops_pdev_stats = {
1442
.open = ath12k_open_pdev_stats,
1443
.release = ath12k_release_pdev_stats,
1444
.read = ath12k_read_pdev_stats,
1445
.owner = THIS_MODULE,
1446
.llseek = default_llseek,
1447
};
1448
1449
static
1450
void ath12k_debugfs_fw_stats_register(struct ath12k *ar)
1451
{
1452
struct dentry *fwstats_dir = debugfs_create_dir("fw_stats",
1453
ar->debug.debugfs_pdev);
1454
1455
/* all stats debugfs files created are under "fw_stats" directory
1456
* created per PDEV
1457
*/
1458
debugfs_create_file("vdev_stats", 0600, fwstats_dir, ar,
1459
&fops_vdev_stats);
1460
debugfs_create_file("beacon_stats", 0600, fwstats_dir, ar,
1461
&fops_bcn_stats);
1462
debugfs_create_file("pdev_stats", 0600, fwstats_dir, ar,
1463
&fops_pdev_stats);
1464
1465
ath12k_fw_stats_init(ar);
1466
}
1467
1468
void ath12k_debugfs_register(struct ath12k *ar)
1469
{
1470
struct ath12k_base *ab = ar->ab;
1471
struct ieee80211_hw *hw = ar->ah->hw;
1472
char pdev_name[5];
1473
char buf[100] = {};
1474
1475
scnprintf(pdev_name, sizeof(pdev_name), "%s%d", "mac", ar->pdev_idx);
1476
1477
ar->debug.debugfs_pdev = debugfs_create_dir(pdev_name, ab->debugfs_soc);
1478
1479
/* Create a symlink under ieee80211/phy* */
1480
scnprintf(buf, sizeof(buf), "../../ath12k/%pd2", ar->debug.debugfs_pdev);
1481
ar->debug.debugfs_pdev_symlink = debugfs_create_symlink("ath12k",
1482
hw->wiphy->debugfsdir,
1483
buf);
1484
1485
if (ar->mac.sbands[NL80211_BAND_5GHZ].channels) {
1486
debugfs_create_file("dfs_simulate_radar", 0200,
1487
ar->debug.debugfs_pdev, ar,
1488
&fops_simulate_radar);
1489
}
1490
1491
debugfs_create_file("tpc_stats", 0400, ar->debug.debugfs_pdev, ar,
1492
&fops_tpc_stats);
1493
debugfs_create_file("tpc_stats_type", 0200, ar->debug.debugfs_pdev,
1494
ar, &fops_tpc_stats_type);
1495
init_completion(&ar->debug.tpc_complete);
1496
1497
ath12k_debugfs_htt_stats_register(ar);
1498
ath12k_debugfs_fw_stats_register(ar);
1499
1500
debugfs_create_file("ext_rx_stats", 0644,
1501
ar->debug.debugfs_pdev, ar,
1502
&fops_extd_rx_stats);
1503
}
1504
1505
void ath12k_debugfs_unregister(struct ath12k *ar)
1506
{
1507
if (!ar->debug.debugfs_pdev)
1508
return;
1509
1510
/* Remove symlink under ieee80211/phy* */
1511
debugfs_remove(ar->debug.debugfs_pdev_symlink);
1512
debugfs_remove_recursive(ar->debug.debugfs_pdev);
1513
ar->debug.debugfs_pdev_symlink = NULL;
1514
ar->debug.debugfs_pdev = NULL;
1515
}
1516
1517