Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/athk/ath11k/debugfs_sta.c
106275 views
1
// SPDX-License-Identifier: BSD-3-Clause-Clear
2
/*
3
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
5
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
6
*/
7
8
#include <linux/vmalloc.h>
9
10
#include "debugfs_sta.h"
11
#include "core.h"
12
#include "peer.h"
13
#include "debug.h"
14
#include "dp_tx.h"
15
#include "debugfs_htt_stats.h"
16
17
void ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta *arsta,
18
struct ath11k_per_peer_tx_stats *peer_stats,
19
u8 legacy_rate_idx)
20
{
21
struct rate_info *txrate = &arsta->txrate;
22
struct ath11k_htt_tx_stats *tx_stats;
23
int gi, mcs, bw, nss;
24
25
if (!arsta->tx_stats)
26
return;
27
28
tx_stats = arsta->tx_stats;
29
gi = FIELD_GET(RATE_INFO_FLAGS_SHORT_GI, arsta->txrate.flags);
30
mcs = txrate->mcs;
31
bw = ath11k_mac_mac80211_bw_to_ath11k_bw(txrate->bw);
32
nss = txrate->nss - 1;
33
34
#define STATS_OP_FMT(name) tx_stats->stats[ATH11K_STATS_TYPE_##name]
35
36
if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) {
37
STATS_OP_FMT(SUCC).he[0][mcs] += peer_stats->succ_bytes;
38
STATS_OP_FMT(SUCC).he[1][mcs] += peer_stats->succ_pkts;
39
STATS_OP_FMT(FAIL).he[0][mcs] += peer_stats->failed_bytes;
40
STATS_OP_FMT(FAIL).he[1][mcs] += peer_stats->failed_pkts;
41
STATS_OP_FMT(RETRY).he[0][mcs] += peer_stats->retry_bytes;
42
STATS_OP_FMT(RETRY).he[1][mcs] += peer_stats->retry_pkts;
43
} else if (txrate->flags & RATE_INFO_FLAGS_VHT_MCS) {
44
STATS_OP_FMT(SUCC).vht[0][mcs] += peer_stats->succ_bytes;
45
STATS_OP_FMT(SUCC).vht[1][mcs] += peer_stats->succ_pkts;
46
STATS_OP_FMT(FAIL).vht[0][mcs] += peer_stats->failed_bytes;
47
STATS_OP_FMT(FAIL).vht[1][mcs] += peer_stats->failed_pkts;
48
STATS_OP_FMT(RETRY).vht[0][mcs] += peer_stats->retry_bytes;
49
STATS_OP_FMT(RETRY).vht[1][mcs] += peer_stats->retry_pkts;
50
} else if (txrate->flags & RATE_INFO_FLAGS_MCS) {
51
STATS_OP_FMT(SUCC).ht[0][mcs] += peer_stats->succ_bytes;
52
STATS_OP_FMT(SUCC).ht[1][mcs] += peer_stats->succ_pkts;
53
STATS_OP_FMT(FAIL).ht[0][mcs] += peer_stats->failed_bytes;
54
STATS_OP_FMT(FAIL).ht[1][mcs] += peer_stats->failed_pkts;
55
STATS_OP_FMT(RETRY).ht[0][mcs] += peer_stats->retry_bytes;
56
STATS_OP_FMT(RETRY).ht[1][mcs] += peer_stats->retry_pkts;
57
} else {
58
mcs = legacy_rate_idx;
59
60
STATS_OP_FMT(SUCC).legacy[0][mcs] += peer_stats->succ_bytes;
61
STATS_OP_FMT(SUCC).legacy[1][mcs] += peer_stats->succ_pkts;
62
STATS_OP_FMT(FAIL).legacy[0][mcs] += peer_stats->failed_bytes;
63
STATS_OP_FMT(FAIL).legacy[1][mcs] += peer_stats->failed_pkts;
64
STATS_OP_FMT(RETRY).legacy[0][mcs] += peer_stats->retry_bytes;
65
STATS_OP_FMT(RETRY).legacy[1][mcs] += peer_stats->retry_pkts;
66
}
67
68
if (peer_stats->is_ampdu) {
69
tx_stats->ba_fails += peer_stats->ba_fails;
70
71
if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) {
72
STATS_OP_FMT(AMPDU).he[0][mcs] +=
73
peer_stats->succ_bytes + peer_stats->retry_bytes;
74
STATS_OP_FMT(AMPDU).he[1][mcs] +=
75
peer_stats->succ_pkts + peer_stats->retry_pkts;
76
} else if (txrate->flags & RATE_INFO_FLAGS_MCS) {
77
STATS_OP_FMT(AMPDU).ht[0][mcs] +=
78
peer_stats->succ_bytes + peer_stats->retry_bytes;
79
STATS_OP_FMT(AMPDU).ht[1][mcs] +=
80
peer_stats->succ_pkts + peer_stats->retry_pkts;
81
} else {
82
STATS_OP_FMT(AMPDU).vht[0][mcs] +=
83
peer_stats->succ_bytes + peer_stats->retry_bytes;
84
STATS_OP_FMT(AMPDU).vht[1][mcs] +=
85
peer_stats->succ_pkts + peer_stats->retry_pkts;
86
}
87
STATS_OP_FMT(AMPDU).bw[0][bw] +=
88
peer_stats->succ_bytes + peer_stats->retry_bytes;
89
STATS_OP_FMT(AMPDU).nss[0][nss] +=
90
peer_stats->succ_bytes + peer_stats->retry_bytes;
91
STATS_OP_FMT(AMPDU).gi[0][gi] +=
92
peer_stats->succ_bytes + peer_stats->retry_bytes;
93
STATS_OP_FMT(AMPDU).bw[1][bw] +=
94
peer_stats->succ_pkts + peer_stats->retry_pkts;
95
STATS_OP_FMT(AMPDU).nss[1][nss] +=
96
peer_stats->succ_pkts + peer_stats->retry_pkts;
97
STATS_OP_FMT(AMPDU).gi[1][gi] +=
98
peer_stats->succ_pkts + peer_stats->retry_pkts;
99
} else {
100
tx_stats->ack_fails += peer_stats->ba_fails;
101
}
102
103
STATS_OP_FMT(SUCC).bw[0][bw] += peer_stats->succ_bytes;
104
STATS_OP_FMT(SUCC).nss[0][nss] += peer_stats->succ_bytes;
105
STATS_OP_FMT(SUCC).gi[0][gi] += peer_stats->succ_bytes;
106
107
STATS_OP_FMT(SUCC).bw[1][bw] += peer_stats->succ_pkts;
108
STATS_OP_FMT(SUCC).nss[1][nss] += peer_stats->succ_pkts;
109
STATS_OP_FMT(SUCC).gi[1][gi] += peer_stats->succ_pkts;
110
111
STATS_OP_FMT(FAIL).bw[0][bw] += peer_stats->failed_bytes;
112
STATS_OP_FMT(FAIL).nss[0][nss] += peer_stats->failed_bytes;
113
STATS_OP_FMT(FAIL).gi[0][gi] += peer_stats->failed_bytes;
114
115
STATS_OP_FMT(FAIL).bw[1][bw] += peer_stats->failed_pkts;
116
STATS_OP_FMT(FAIL).nss[1][nss] += peer_stats->failed_pkts;
117
STATS_OP_FMT(FAIL).gi[1][gi] += peer_stats->failed_pkts;
118
119
STATS_OP_FMT(RETRY).bw[0][bw] += peer_stats->retry_bytes;
120
STATS_OP_FMT(RETRY).nss[0][nss] += peer_stats->retry_bytes;
121
STATS_OP_FMT(RETRY).gi[0][gi] += peer_stats->retry_bytes;
122
123
STATS_OP_FMT(RETRY).bw[1][bw] += peer_stats->retry_pkts;
124
STATS_OP_FMT(RETRY).nss[1][nss] += peer_stats->retry_pkts;
125
STATS_OP_FMT(RETRY).gi[1][gi] += peer_stats->retry_pkts;
126
127
tx_stats->tx_duration += peer_stats->duration;
128
}
129
130
void ath11k_debugfs_sta_update_txcompl(struct ath11k *ar,
131
struct hal_tx_status *ts)
132
{
133
ath11k_dp_tx_update_txcompl(ar, ts);
134
}
135
136
static ssize_t ath11k_dbg_sta_dump_tx_stats(struct file *file,
137
char __user *user_buf,
138
size_t count, loff_t *ppos)
139
{
140
struct ieee80211_sta *sta = file->private_data;
141
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
142
struct ath11k *ar = arsta->arvif->ar;
143
struct ath11k_htt_data_stats *stats;
144
static const char *str_name[ATH11K_STATS_TYPE_MAX] = {"succ", "fail",
145
"retry", "ampdu"};
146
static const char *str[ATH11K_COUNTER_TYPE_MAX] = {"bytes", "packets"};
147
int len = 0, i, j, k, retval = 0;
148
const int size = 2 * 4096;
149
char *buf;
150
151
if (!arsta->tx_stats)
152
return -ENOENT;
153
154
buf = kzalloc(size, GFP_KERNEL);
155
if (!buf)
156
return -ENOMEM;
157
158
mutex_lock(&ar->conf_mutex);
159
160
spin_lock_bh(&ar->data_lock);
161
for (k = 0; k < ATH11K_STATS_TYPE_MAX; k++) {
162
for (j = 0; j < ATH11K_COUNTER_TYPE_MAX; j++) {
163
stats = &arsta->tx_stats->stats[k];
164
len += scnprintf(buf + len, size - len, "%s_%s\n",
165
str_name[k],
166
str[j]);
167
len += scnprintf(buf + len, size - len,
168
" HE MCS %s\n",
169
str[j]);
170
for (i = 0; i < ATH11K_HE_MCS_NUM; i++)
171
len += scnprintf(buf + len, size - len,
172
" %llu ",
173
stats->he[j][i]);
174
len += scnprintf(buf + len, size - len, "\n");
175
len += scnprintf(buf + len, size - len,
176
" VHT MCS %s\n",
177
str[j]);
178
for (i = 0; i < ATH11K_VHT_MCS_NUM; i++)
179
len += scnprintf(buf + len, size - len,
180
" %llu ",
181
stats->vht[j][i]);
182
len += scnprintf(buf + len, size - len, "\n");
183
len += scnprintf(buf + len, size - len, " HT MCS %s\n",
184
str[j]);
185
for (i = 0; i < ATH11K_HT_MCS_NUM; i++)
186
len += scnprintf(buf + len, size - len,
187
" %llu ", stats->ht[j][i]);
188
len += scnprintf(buf + len, size - len, "\n");
189
len += scnprintf(buf + len, size - len,
190
" BW %s (20,40,80,160 MHz)\n", str[j]);
191
len += scnprintf(buf + len, size - len,
192
" %llu %llu %llu %llu\n",
193
stats->bw[j][0], stats->bw[j][1],
194
stats->bw[j][2], stats->bw[j][3]);
195
len += scnprintf(buf + len, size - len,
196
" NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
197
len += scnprintf(buf + len, size - len,
198
" %llu %llu %llu %llu\n",
199
stats->nss[j][0], stats->nss[j][1],
200
stats->nss[j][2], stats->nss[j][3]);
201
len += scnprintf(buf + len, size - len,
202
" GI %s (0.4us,0.8us,1.6us,3.2us)\n",
203
str[j]);
204
len += scnprintf(buf + len, size - len,
205
" %llu %llu %llu %llu\n",
206
stats->gi[j][0], stats->gi[j][1],
207
stats->gi[j][2], stats->gi[j][3]);
208
len += scnprintf(buf + len, size - len,
209
" legacy rate %s (1,2 ... Mbps)\n ",
210
str[j]);
211
for (i = 0; i < ATH11K_LEGACY_NUM; i++)
212
len += scnprintf(buf + len, size - len, "%llu ",
213
stats->legacy[j][i]);
214
len += scnprintf(buf + len, size - len, "\n");
215
}
216
}
217
218
len += scnprintf(buf + len, size - len,
219
"\nTX duration\n %llu usecs\n",
220
arsta->tx_stats->tx_duration);
221
len += scnprintf(buf + len, size - len,
222
"BA fails\n %llu\n", arsta->tx_stats->ba_fails);
223
len += scnprintf(buf + len, size - len,
224
"ack fails\n %llu\n", arsta->tx_stats->ack_fails);
225
spin_unlock_bh(&ar->data_lock);
226
227
if (len > size)
228
len = size;
229
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
230
kfree(buf);
231
232
mutex_unlock(&ar->conf_mutex);
233
return retval;
234
}
235
236
static const struct file_operations fops_tx_stats = {
237
.read = ath11k_dbg_sta_dump_tx_stats,
238
.open = simple_open,
239
.owner = THIS_MODULE,
240
.llseek = default_llseek,
241
};
242
243
static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file,
244
char __user *user_buf,
245
size_t count, loff_t *ppos)
246
{
247
struct ieee80211_sta *sta = file->private_data;
248
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
249
struct ath11k *ar = arsta->arvif->ar;
250
struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats;
251
int len = 0, i, retval = 0;
252
const int size = 4096;
253
char *buf;
254
255
if (!rx_stats)
256
return -ENOENT;
257
258
buf = kzalloc(size, GFP_KERNEL);
259
if (!buf)
260
return -ENOMEM;
261
262
mutex_lock(&ar->conf_mutex);
263
spin_lock_bh(&ar->ab->base_lock);
264
265
len += scnprintf(buf + len, size - len, "RX peer stats:\n");
266
len += scnprintf(buf + len, size - len, "Num of MSDUs: %llu\n",
267
rx_stats->num_msdu);
268
len += scnprintf(buf + len, size - len, "Num of MSDUs with TCP L4: %llu\n",
269
rx_stats->tcp_msdu_count);
270
len += scnprintf(buf + len, size - len, "Num of MSDUs with UDP L4: %llu\n",
271
rx_stats->udp_msdu_count);
272
len += scnprintf(buf + len, size - len, "Num of MSDUs part of AMPDU: %llu\n",
273
rx_stats->ampdu_msdu_count);
274
len += scnprintf(buf + len, size - len, "Num of MSDUs not part of AMPDU: %llu\n",
275
rx_stats->non_ampdu_msdu_count);
276
len += scnprintf(buf + len, size - len, "Num of MSDUs using STBC: %llu\n",
277
rx_stats->stbc_count);
278
len += scnprintf(buf + len, size - len, "Num of MSDUs beamformed: %llu\n",
279
rx_stats->beamformed_count);
280
len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS ok: %llu\n",
281
rx_stats->num_mpdu_fcs_ok);
282
len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS error: %llu\n",
283
rx_stats->num_mpdu_fcs_err);
284
len += scnprintf(buf + len, size - len,
285
"GI: 0.8us %llu 0.4us %llu 1.6us %llu 3.2us %llu\n",
286
rx_stats->gi_count[0], rx_stats->gi_count[1],
287
rx_stats->gi_count[2], rx_stats->gi_count[3]);
288
len += scnprintf(buf + len, size - len,
289
"BW: 20Mhz %llu 40Mhz %llu 80Mhz %llu 160Mhz %llu\n",
290
rx_stats->bw_count[0], rx_stats->bw_count[1],
291
rx_stats->bw_count[2], rx_stats->bw_count[3]);
292
len += scnprintf(buf + len, size - len, "BCC %llu LDPC %llu\n",
293
rx_stats->coding_count[0], rx_stats->coding_count[1]);
294
len += scnprintf(buf + len, size - len,
295
"preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu\n",
296
rx_stats->pream_cnt[0], rx_stats->pream_cnt[1],
297
rx_stats->pream_cnt[2], rx_stats->pream_cnt[3],
298
rx_stats->pream_cnt[4]);
299
len += scnprintf(buf + len, size - len,
300
"reception type: SU %llu MU_MIMO %llu MU_OFDMA %llu MU_OFDMA_MIMO %llu\n",
301
rx_stats->reception_type[0], rx_stats->reception_type[1],
302
rx_stats->reception_type[2], rx_stats->reception_type[3]);
303
len += scnprintf(buf + len, size - len, "TID(0-15) Legacy TID(16):");
304
for (i = 0; i <= IEEE80211_NUM_TIDS; i++)
305
len += scnprintf(buf + len, size - len, "%llu ", rx_stats->tid_count[i]);
306
len += scnprintf(buf + len, size - len, "\nMCS(0-11) Legacy MCS(12):");
307
for (i = 0; i < HAL_RX_MAX_MCS + 1; i++)
308
len += scnprintf(buf + len, size - len, "%llu ", rx_stats->mcs_count[i]);
309
len += scnprintf(buf + len, size - len, "\nNSS(1-8):");
310
for (i = 0; i < HAL_RX_MAX_NSS; i++)
311
len += scnprintf(buf + len, size - len, "%llu ", rx_stats->nss_count[i]);
312
len += scnprintf(buf + len, size - len, "\nRX Duration:%llu ",
313
rx_stats->rx_duration);
314
len += scnprintf(buf + len, size - len,
315
"\nDCM: %llu\nRU: 26 %llu 52: %llu 106: %llu 242: %llu 484: %llu 996: %llu\n",
316
rx_stats->dcm_count, rx_stats->ru_alloc_cnt[0],
317
rx_stats->ru_alloc_cnt[1], rx_stats->ru_alloc_cnt[2],
318
rx_stats->ru_alloc_cnt[3], rx_stats->ru_alloc_cnt[4],
319
rx_stats->ru_alloc_cnt[5]);
320
321
len += scnprintf(buf + len, size - len, "\n");
322
323
spin_unlock_bh(&ar->ab->base_lock);
324
325
if (len > size)
326
len = size;
327
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
328
kfree(buf);
329
330
mutex_unlock(&ar->conf_mutex);
331
return retval;
332
}
333
334
static const struct file_operations fops_rx_stats = {
335
.read = ath11k_dbg_sta_dump_rx_stats,
336
.open = simple_open,
337
.owner = THIS_MODULE,
338
.llseek = default_llseek,
339
};
340
341
static int
342
ath11k_dbg_sta_open_htt_peer_stats(struct inode *inode, struct file *file)
343
{
344
struct ieee80211_sta *sta = inode->i_private;
345
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
346
struct ath11k *ar = arsta->arvif->ar;
347
struct debug_htt_stats_req *stats_req;
348
int type = ar->debug.htt_stats.type;
349
int ret;
350
351
if ((type != ATH11K_DBG_HTT_EXT_STATS_PEER_INFO &&
352
type != ATH11K_DBG_HTT_EXT_STATS_PEER_CTRL_PATH_TXRX_STATS) ||
353
type == ATH11K_DBG_HTT_EXT_STATS_RESET)
354
return -EPERM;
355
356
stats_req = vzalloc(sizeof(*stats_req) + ATH11K_HTT_STATS_BUF_SIZE);
357
if (!stats_req)
358
return -ENOMEM;
359
360
mutex_lock(&ar->conf_mutex);
361
ar->debug.htt_stats.stats_req = stats_req;
362
stats_req->type = type;
363
memcpy(stats_req->peer_addr, sta->addr, ETH_ALEN);
364
ret = ath11k_debugfs_htt_stats_req(ar);
365
mutex_unlock(&ar->conf_mutex);
366
if (ret < 0)
367
goto out;
368
369
file->private_data = stats_req;
370
return 0;
371
out:
372
vfree(stats_req);
373
ar->debug.htt_stats.stats_req = NULL;
374
return ret;
375
}
376
377
static int
378
ath11k_dbg_sta_release_htt_peer_stats(struct inode *inode, struct file *file)
379
{
380
struct ieee80211_sta *sta = inode->i_private;
381
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
382
struct ath11k *ar = arsta->arvif->ar;
383
384
mutex_lock(&ar->conf_mutex);
385
vfree(file->private_data);
386
ar->debug.htt_stats.stats_req = NULL;
387
mutex_unlock(&ar->conf_mutex);
388
389
return 0;
390
}
391
392
static ssize_t ath11k_dbg_sta_read_htt_peer_stats(struct file *file,
393
char __user *user_buf,
394
size_t count, loff_t *ppos)
395
{
396
struct debug_htt_stats_req *stats_req = file->private_data;
397
char *buf;
398
u32 length = 0;
399
400
buf = stats_req->buf;
401
length = min_t(u32, stats_req->buf_len, ATH11K_HTT_STATS_BUF_SIZE);
402
return simple_read_from_buffer(user_buf, count, ppos, buf, length);
403
}
404
405
static const struct file_operations fops_htt_peer_stats = {
406
.open = ath11k_dbg_sta_open_htt_peer_stats,
407
.release = ath11k_dbg_sta_release_htt_peer_stats,
408
.read = ath11k_dbg_sta_read_htt_peer_stats,
409
.owner = THIS_MODULE,
410
.llseek = default_llseek,
411
};
412
413
static ssize_t ath11k_dbg_sta_write_peer_pktlog(struct file *file,
414
const char __user *buf,
415
size_t count, loff_t *ppos)
416
{
417
struct ieee80211_sta *sta = file->private_data;
418
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
419
struct ath11k *ar = arsta->arvif->ar;
420
int ret, enable;
421
422
mutex_lock(&ar->conf_mutex);
423
424
if (ar->state != ATH11K_STATE_ON) {
425
ret = -ENETDOWN;
426
goto out;
427
}
428
429
ret = kstrtoint_from_user(buf, count, 0, &enable);
430
if (ret)
431
goto out;
432
433
ar->debug.pktlog_peer_valid = enable;
434
memcpy(ar->debug.pktlog_peer_addr, sta->addr, ETH_ALEN);
435
436
/* Send peer based pktlog enable/disable */
437
ret = ath11k_wmi_pdev_peer_pktlog_filter(ar, sta->addr, enable);
438
if (ret) {
439
ath11k_warn(ar->ab, "failed to set peer pktlog filter %pM: %d\n",
440
sta->addr, ret);
441
goto out;
442
}
443
444
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "peer pktlog filter set to %d\n",
445
enable);
446
ret = count;
447
448
out:
449
mutex_unlock(&ar->conf_mutex);
450
return ret;
451
}
452
453
static ssize_t ath11k_dbg_sta_read_peer_pktlog(struct file *file,
454
char __user *ubuf,
455
size_t count, loff_t *ppos)
456
{
457
struct ieee80211_sta *sta = file->private_data;
458
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
459
struct ath11k *ar = arsta->arvif->ar;
460
char buf[32] = {};
461
int len;
462
463
mutex_lock(&ar->conf_mutex);
464
len = scnprintf(buf, sizeof(buf), "%08x %pM\n",
465
ar->debug.pktlog_peer_valid,
466
ar->debug.pktlog_peer_addr);
467
mutex_unlock(&ar->conf_mutex);
468
469
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
470
}
471
472
static const struct file_operations fops_peer_pktlog = {
473
.write = ath11k_dbg_sta_write_peer_pktlog,
474
.read = ath11k_dbg_sta_read_peer_pktlog,
475
.open = simple_open,
476
.owner = THIS_MODULE,
477
.llseek = default_llseek,
478
};
479
480
static ssize_t ath11k_dbg_sta_write_delba(struct file *file,
481
const char __user *user_buf,
482
size_t count, loff_t *ppos)
483
{
484
struct ieee80211_sta *sta = file->private_data;
485
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
486
struct ath11k *ar = arsta->arvif->ar;
487
u32 tid, initiator, reason;
488
int ret;
489
char buf[64] = {};
490
491
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
492
user_buf, count);
493
if (ret <= 0)
494
return ret;
495
496
ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
497
if (ret != 3)
498
return -EINVAL;
499
500
/* Valid TID values are 0 through 15 */
501
if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
502
return -EINVAL;
503
504
mutex_lock(&ar->conf_mutex);
505
if (ar->state != ATH11K_STATE_ON ||
506
arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
507
ret = count;
508
goto out;
509
}
510
511
ret = ath11k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
512
tid, initiator, reason);
513
if (ret) {
514
ath11k_warn(ar->ab, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
515
arsta->arvif->vdev_id, sta->addr, tid, initiator,
516
reason);
517
}
518
ret = count;
519
out:
520
mutex_unlock(&ar->conf_mutex);
521
return ret;
522
}
523
524
static const struct file_operations fops_delba = {
525
.write = ath11k_dbg_sta_write_delba,
526
.open = simple_open,
527
.owner = THIS_MODULE,
528
.llseek = default_llseek,
529
};
530
531
static ssize_t ath11k_dbg_sta_write_addba_resp(struct file *file,
532
const char __user *user_buf,
533
size_t count, loff_t *ppos)
534
{
535
struct ieee80211_sta *sta = file->private_data;
536
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
537
struct ath11k *ar = arsta->arvif->ar;
538
u32 tid, status;
539
int ret;
540
char buf[64] = {};
541
542
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
543
user_buf, count);
544
if (ret <= 0)
545
return ret;
546
547
ret = sscanf(buf, "%u %u", &tid, &status);
548
if (ret != 2)
549
return -EINVAL;
550
551
/* Valid TID values are 0 through 15 */
552
if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
553
return -EINVAL;
554
555
mutex_lock(&ar->conf_mutex);
556
if (ar->state != ATH11K_STATE_ON ||
557
arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
558
ret = count;
559
goto out;
560
}
561
562
ret = ath11k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
563
tid, status);
564
if (ret) {
565
ath11k_warn(ar->ab, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
566
arsta->arvif->vdev_id, sta->addr, tid, status);
567
}
568
ret = count;
569
out:
570
mutex_unlock(&ar->conf_mutex);
571
return ret;
572
}
573
574
static const struct file_operations fops_addba_resp = {
575
.write = ath11k_dbg_sta_write_addba_resp,
576
.open = simple_open,
577
.owner = THIS_MODULE,
578
.llseek = default_llseek,
579
};
580
581
static ssize_t ath11k_dbg_sta_write_addba(struct file *file,
582
const char __user *user_buf,
583
size_t count, loff_t *ppos)
584
{
585
struct ieee80211_sta *sta = file->private_data;
586
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
587
struct ath11k *ar = arsta->arvif->ar;
588
u32 tid, buf_size;
589
int ret;
590
char buf[64] = {};
591
592
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
593
user_buf, count);
594
if (ret <= 0)
595
return ret;
596
597
ret = sscanf(buf, "%u %u", &tid, &buf_size);
598
if (ret != 2)
599
return -EINVAL;
600
601
/* Valid TID values are 0 through 15 */
602
if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
603
return -EINVAL;
604
605
mutex_lock(&ar->conf_mutex);
606
if (ar->state != ATH11K_STATE_ON ||
607
arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
608
ret = count;
609
goto out;
610
}
611
612
ret = ath11k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
613
tid, buf_size);
614
if (ret) {
615
ath11k_warn(ar->ab, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
616
arsta->arvif->vdev_id, sta->addr, tid, buf_size);
617
}
618
619
ret = count;
620
out:
621
mutex_unlock(&ar->conf_mutex);
622
return ret;
623
}
624
625
static const struct file_operations fops_addba = {
626
.write = ath11k_dbg_sta_write_addba,
627
.open = simple_open,
628
.owner = THIS_MODULE,
629
.llseek = default_llseek,
630
};
631
632
static ssize_t ath11k_dbg_sta_read_aggr_mode(struct file *file,
633
char __user *user_buf,
634
size_t count, loff_t *ppos)
635
{
636
struct ieee80211_sta *sta = file->private_data;
637
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
638
struct ath11k *ar = arsta->arvif->ar;
639
char buf[64];
640
int len = 0;
641
642
mutex_lock(&ar->conf_mutex);
643
len = scnprintf(buf, sizeof(buf) - len,
644
"aggregation mode: %s\n\n%s\n%s\n",
645
(arsta->aggr_mode == ATH11K_DBG_AGGR_MODE_AUTO) ?
646
"auto" : "manual", "auto = 0", "manual = 1");
647
mutex_unlock(&ar->conf_mutex);
648
649
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
650
}
651
652
static ssize_t ath11k_dbg_sta_write_aggr_mode(struct file *file,
653
const char __user *user_buf,
654
size_t count, loff_t *ppos)
655
{
656
struct ieee80211_sta *sta = file->private_data;
657
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
658
struct ath11k *ar = arsta->arvif->ar;
659
u32 aggr_mode;
660
int ret;
661
662
if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode))
663
return -EINVAL;
664
665
if (aggr_mode >= ATH11K_DBG_AGGR_MODE_MAX)
666
return -EINVAL;
667
668
mutex_lock(&ar->conf_mutex);
669
if (ar->state != ATH11K_STATE_ON ||
670
aggr_mode == arsta->aggr_mode) {
671
ret = count;
672
goto out;
673
}
674
675
ret = ath11k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr);
676
if (ret) {
677
ath11k_warn(ar->ab, "failed to clear addba session ret: %d\n",
678
ret);
679
goto out;
680
}
681
682
arsta->aggr_mode = aggr_mode;
683
out:
684
mutex_unlock(&ar->conf_mutex);
685
return ret;
686
}
687
688
static const struct file_operations fops_aggr_mode = {
689
.read = ath11k_dbg_sta_read_aggr_mode,
690
.write = ath11k_dbg_sta_write_aggr_mode,
691
.open = simple_open,
692
.owner = THIS_MODULE,
693
.llseek = default_llseek,
694
};
695
696
static ssize_t
697
ath11k_write_htt_peer_stats_reset(struct file *file,
698
const char __user *user_buf,
699
size_t count, loff_t *ppos)
700
{
701
struct ieee80211_sta *sta = file->private_data;
702
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
703
struct ath11k *ar = arsta->arvif->ar;
704
struct htt_ext_stats_cfg_params cfg_params = {};
705
int ret;
706
u8 type;
707
708
ret = kstrtou8_from_user(user_buf, count, 0, &type);
709
if (ret)
710
return ret;
711
712
if (!type)
713
return ret;
714
715
mutex_lock(&ar->conf_mutex);
716
cfg_params.cfg0 = HTT_STAT_PEER_INFO_MAC_ADDR;
717
cfg_params.cfg0 |= FIELD_PREP(GENMASK(15, 1),
718
HTT_PEER_STATS_REQ_MODE_FLUSH_TQM);
719
720
cfg_params.cfg1 = HTT_STAT_DEFAULT_PEER_REQ_TYPE;
721
722
cfg_params.cfg2 |= FIELD_PREP(GENMASK(7, 0), sta->addr[0]);
723
cfg_params.cfg2 |= FIELD_PREP(GENMASK(15, 8), sta->addr[1]);
724
cfg_params.cfg2 |= FIELD_PREP(GENMASK(23, 16), sta->addr[2]);
725
cfg_params.cfg2 |= FIELD_PREP(GENMASK(31, 24), sta->addr[3]);
726
727
cfg_params.cfg3 |= FIELD_PREP(GENMASK(7, 0), sta->addr[4]);
728
cfg_params.cfg3 |= FIELD_PREP(GENMASK(15, 8), sta->addr[5]);
729
730
cfg_params.cfg3 |= ATH11K_HTT_PEER_STATS_RESET;
731
732
ret = ath11k_dp_tx_htt_h2t_ext_stats_req(ar,
733
ATH11K_DBG_HTT_EXT_STATS_PEER_INFO,
734
&cfg_params,
735
0ULL);
736
if (ret) {
737
ath11k_warn(ar->ab, "failed to send htt peer stats request: %d\n", ret);
738
mutex_unlock(&ar->conf_mutex);
739
return ret;
740
}
741
742
mutex_unlock(&ar->conf_mutex);
743
744
ret = count;
745
746
return ret;
747
}
748
749
static const struct file_operations fops_htt_peer_stats_reset = {
750
.write = ath11k_write_htt_peer_stats_reset,
751
.open = simple_open,
752
.owner = THIS_MODULE,
753
.llseek = default_llseek,
754
};
755
756
static ssize_t ath11k_dbg_sta_read_peer_ps_state(struct file *file,
757
char __user *user_buf,
758
size_t count, loff_t *ppos)
759
{
760
struct ieee80211_sta *sta = file->private_data;
761
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
762
struct ath11k *ar = arsta->arvif->ar;
763
char buf[20];
764
int len;
765
766
spin_lock_bh(&ar->data_lock);
767
768
len = scnprintf(buf, sizeof(buf), "%d\n", arsta->peer_ps_state);
769
770
spin_unlock_bh(&ar->data_lock);
771
772
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
773
}
774
775
static const struct file_operations fops_peer_ps_state = {
776
.open = simple_open,
777
.read = ath11k_dbg_sta_read_peer_ps_state,
778
.owner = THIS_MODULE,
779
.llseek = default_llseek,
780
};
781
782
static ssize_t ath11k_dbg_sta_read_current_ps_duration(struct file *file,
783
char __user *user_buf,
784
size_t count,
785
loff_t *ppos)
786
{
787
struct ieee80211_sta *sta = file->private_data;
788
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
789
struct ath11k *ar = arsta->arvif->ar;
790
u64 time_since_station_in_power_save;
791
char buf[20];
792
int len;
793
794
spin_lock_bh(&ar->data_lock);
795
796
if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON &&
797
arsta->peer_current_ps_valid)
798
time_since_station_in_power_save = jiffies_to_msecs(jiffies
799
- arsta->ps_start_jiffies);
800
else
801
time_since_station_in_power_save = 0;
802
803
len = scnprintf(buf, sizeof(buf), "%llu\n",
804
time_since_station_in_power_save);
805
spin_unlock_bh(&ar->data_lock);
806
807
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
808
}
809
810
static const struct file_operations fops_current_ps_duration = {
811
.open = simple_open,
812
.read = ath11k_dbg_sta_read_current_ps_duration,
813
.owner = THIS_MODULE,
814
.llseek = default_llseek,
815
};
816
817
static ssize_t ath11k_dbg_sta_read_total_ps_duration(struct file *file,
818
char __user *user_buf,
819
size_t count, loff_t *ppos)
820
{
821
struct ieee80211_sta *sta = file->private_data;
822
struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
823
struct ath11k *ar = arsta->arvif->ar;
824
char buf[20];
825
u64 power_save_duration;
826
int len;
827
828
spin_lock_bh(&ar->data_lock);
829
830
if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON &&
831
arsta->peer_current_ps_valid)
832
power_save_duration = jiffies_to_msecs(jiffies
833
- arsta->ps_start_jiffies)
834
+ arsta->ps_total_duration;
835
else
836
power_save_duration = arsta->ps_total_duration;
837
838
len = scnprintf(buf, sizeof(buf), "%llu\n", power_save_duration);
839
840
spin_unlock_bh(&ar->data_lock);
841
842
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
843
}
844
845
static const struct file_operations fops_total_ps_duration = {
846
.open = simple_open,
847
.read = ath11k_dbg_sta_read_total_ps_duration,
848
.owner = THIS_MODULE,
849
.llseek = default_llseek,
850
};
851
852
void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
853
struct ieee80211_sta *sta, struct dentry *dir)
854
{
855
struct ath11k *ar = hw->priv;
856
857
if (ath11k_debugfs_is_extd_tx_stats_enabled(ar))
858
debugfs_create_file("tx_stats", 0400, dir, sta,
859
&fops_tx_stats);
860
if (ath11k_debugfs_is_extd_rx_stats_enabled(ar))
861
debugfs_create_file("rx_stats", 0400, dir, sta,
862
&fops_rx_stats);
863
864
debugfs_create_file("htt_peer_stats", 0400, dir, sta,
865
&fops_htt_peer_stats);
866
867
debugfs_create_file("peer_pktlog", 0644, dir, sta,
868
&fops_peer_pktlog);
869
870
debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
871
debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
872
debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
873
debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
874
875
if (test_bit(WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET,
876
ar->ab->wmi_ab.svc_map))
877
debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta,
878
&fops_htt_peer_stats_reset);
879
880
debugfs_create_file("peer_ps_state", 0400, dir, sta,
881
&fops_peer_ps_state);
882
883
if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,
884
ar->ab->wmi_ab.svc_map)) {
885
debugfs_create_file("current_ps_duration", 0440, dir, sta,
886
&fops_current_ps_duration);
887
debugfs_create_file("total_ps_duration", 0440, dir, sta,
888
&fops_total_ps_duration);
889
}
890
}
891
892