Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/athk/ath10k/debugfs_sta.c
104863 views
1
// SPDX-License-Identifier: ISC
2
/*
3
* Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
4
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
5
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
6
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
7
*/
8
9
#include "core.h"
10
#include "wmi-ops.h"
11
#include "txrx.h"
12
#include "debug.h"
13
14
static void ath10k_rx_stats_update_amsdu_subfrm(struct ath10k *ar,
15
struct ath10k_sta_tid_stats *stats,
16
u32 msdu_count)
17
{
18
if (msdu_count == 1)
19
stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_1]++;
20
else if (msdu_count == 2)
21
stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_2]++;
22
else if (msdu_count == 3)
23
stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_3]++;
24
else if (msdu_count == 4)
25
stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_4]++;
26
else if (msdu_count > 4)
27
stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MORE]++;
28
}
29
30
static void ath10k_rx_stats_update_ampdu_subfrm(struct ath10k *ar,
31
struct ath10k_sta_tid_stats *stats,
32
u32 mpdu_count)
33
{
34
if (mpdu_count <= 10)
35
stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_10]++;
36
else if (mpdu_count <= 20)
37
stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_20]++;
38
else if (mpdu_count <= 30)
39
stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_30]++;
40
else if (mpdu_count <= 40)
41
stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_40]++;
42
else if (mpdu_count <= 50)
43
stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_50]++;
44
else if (mpdu_count <= 60)
45
stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_60]++;
46
else if (mpdu_count > 60)
47
stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MORE]++;
48
}
49
50
void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar, u16 peer_id, u8 tid,
51
struct htt_rx_indication_mpdu_range *ranges,
52
int num_ranges)
53
{
54
struct ath10k_sta *arsta;
55
struct ath10k_peer *peer;
56
int i;
57
58
if (tid > IEEE80211_NUM_TIDS || !(ar->sta_tid_stats_mask & BIT(tid)))
59
return;
60
61
rcu_read_lock();
62
spin_lock_bh(&ar->data_lock);
63
64
peer = ath10k_peer_find_by_id(ar, peer_id);
65
if (!peer || !peer->sta)
66
goto out;
67
68
arsta = (struct ath10k_sta *)peer->sta->drv_priv;
69
70
for (i = 0; i < num_ranges; i++)
71
ath10k_rx_stats_update_ampdu_subfrm(ar,
72
&arsta->tid_stats[tid],
73
ranges[i].mpdu_count);
74
75
out:
76
spin_unlock_bh(&ar->data_lock);
77
rcu_read_unlock();
78
}
79
80
void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr,
81
unsigned long num_msdus,
82
enum ath10k_pkt_rx_err err,
83
unsigned long unchain_cnt,
84
unsigned long drop_cnt,
85
unsigned long drop_cnt_filter,
86
unsigned long queued_msdus)
87
{
88
struct ieee80211_sta *sta;
89
struct ath10k_sta *arsta;
90
struct ieee80211_hdr *hdr;
91
struct ath10k_sta_tid_stats *stats;
92
u8 tid = IEEE80211_NUM_TIDS;
93
bool non_data_frm = false;
94
95
hdr = (struct ieee80211_hdr *)first_hdr;
96
if (!ieee80211_is_data(hdr->frame_control))
97
non_data_frm = true;
98
99
if (ieee80211_is_data_qos(hdr->frame_control))
100
tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
101
102
if (!(ar->sta_tid_stats_mask & BIT(tid)) || non_data_frm)
103
return;
104
105
rcu_read_lock();
106
107
sta = ieee80211_find_sta_by_ifaddr(ar->hw, hdr->addr2, NULL);
108
if (!sta)
109
goto exit;
110
111
arsta = (struct ath10k_sta *)sta->drv_priv;
112
113
spin_lock_bh(&ar->data_lock);
114
stats = &arsta->tid_stats[tid];
115
stats->rx_pkt_from_fw += num_msdus;
116
stats->rx_pkt_unchained += unchain_cnt;
117
stats->rx_pkt_drop_chained += drop_cnt;
118
stats->rx_pkt_drop_filter += drop_cnt_filter;
119
if (err != ATH10K_PKT_RX_ERR_MAX)
120
stats->rx_pkt_err[err] += queued_msdus;
121
stats->rx_pkt_queued_for_mac += queued_msdus;
122
ath10k_rx_stats_update_amsdu_subfrm(ar, &arsta->tid_stats[tid],
123
num_msdus);
124
spin_unlock_bh(&ar->data_lock);
125
126
exit:
127
rcu_read_unlock();
128
}
129
130
static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar,
131
struct ath10k_fw_stats *stats)
132
{
133
struct ath10k_fw_extd_stats_peer *peer;
134
struct ieee80211_sta *sta;
135
struct ath10k_sta *arsta;
136
137
rcu_read_lock();
138
list_for_each_entry(peer, &stats->peers_extd, list) {
139
sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
140
NULL);
141
if (!sta)
142
continue;
143
arsta = (struct ath10k_sta *)sta->drv_priv;
144
arsta->rx_duration += (u64)peer->rx_duration;
145
}
146
rcu_read_unlock();
147
}
148
149
static void ath10k_sta_update_stats_rx_duration(struct ath10k *ar,
150
struct ath10k_fw_stats *stats)
151
{
152
struct ath10k_fw_stats_peer *peer;
153
struct ieee80211_sta *sta;
154
struct ath10k_sta *arsta;
155
156
rcu_read_lock();
157
list_for_each_entry(peer, &stats->peers, list) {
158
sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
159
NULL);
160
if (!sta)
161
continue;
162
arsta = (struct ath10k_sta *)sta->drv_priv;
163
arsta->rx_duration += (u64)peer->rx_duration;
164
}
165
rcu_read_unlock();
166
}
167
168
void ath10k_sta_update_rx_duration(struct ath10k *ar,
169
struct ath10k_fw_stats *stats)
170
{
171
if (stats->extended)
172
ath10k_sta_update_extd_stats_rx_duration(ar, stats);
173
else
174
ath10k_sta_update_stats_rx_duration(ar, stats);
175
}
176
177
static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
178
char __user *user_buf,
179
size_t count, loff_t *ppos)
180
{
181
struct ieee80211_sta *sta = file->private_data;
182
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
183
struct ath10k *ar = arsta->arvif->ar;
184
char buf[32];
185
int len = 0;
186
187
mutex_lock(&ar->conf_mutex);
188
len = scnprintf(buf, sizeof(buf) - len, "aggregation mode: %s\n",
189
(arsta->aggr_mode == ATH10K_DBG_AGGR_MODE_AUTO) ?
190
"auto" : "manual");
191
mutex_unlock(&ar->conf_mutex);
192
193
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
194
}
195
196
static ssize_t ath10k_dbg_sta_write_aggr_mode(struct file *file,
197
const char __user *user_buf,
198
size_t count, loff_t *ppos)
199
{
200
struct ieee80211_sta *sta = file->private_data;
201
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
202
struct ath10k *ar = arsta->arvif->ar;
203
u32 aggr_mode;
204
int ret;
205
206
if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode))
207
return -EINVAL;
208
209
if (aggr_mode >= ATH10K_DBG_AGGR_MODE_MAX)
210
return -EINVAL;
211
212
mutex_lock(&ar->conf_mutex);
213
if ((ar->state != ATH10K_STATE_ON) ||
214
(aggr_mode == arsta->aggr_mode)) {
215
ret = count;
216
goto out;
217
}
218
219
ret = ath10k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr);
220
if (ret) {
221
ath10k_warn(ar, "failed to clear addba session ret: %d\n", ret);
222
goto out;
223
}
224
225
arsta->aggr_mode = aggr_mode;
226
out:
227
mutex_unlock(&ar->conf_mutex);
228
return ret;
229
}
230
231
static const struct file_operations fops_aggr_mode = {
232
.read = ath10k_dbg_sta_read_aggr_mode,
233
.write = ath10k_dbg_sta_write_aggr_mode,
234
.open = simple_open,
235
.owner = THIS_MODULE,
236
.llseek = default_llseek,
237
};
238
239
static ssize_t ath10k_dbg_sta_write_addba(struct file *file,
240
const char __user *user_buf,
241
size_t count, loff_t *ppos)
242
{
243
struct ieee80211_sta *sta = file->private_data;
244
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
245
struct ath10k *ar = arsta->arvif->ar;
246
u32 tid, buf_size;
247
int ret;
248
char buf[64] = {};
249
250
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
251
user_buf, count);
252
if (ret <= 0)
253
return ret;
254
255
ret = sscanf(buf, "%u %u", &tid, &buf_size);
256
if (ret != 2)
257
return -EINVAL;
258
259
/* Valid TID values are 0 through 15 */
260
if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
261
return -EINVAL;
262
263
mutex_lock(&ar->conf_mutex);
264
if ((ar->state != ATH10K_STATE_ON) ||
265
(arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
266
ret = count;
267
goto out;
268
}
269
270
ret = ath10k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
271
tid, buf_size);
272
if (ret) {
273
ath10k_warn(ar, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
274
arsta->arvif->vdev_id, sta->addr, tid, buf_size);
275
}
276
277
ret = count;
278
out:
279
mutex_unlock(&ar->conf_mutex);
280
return ret;
281
}
282
283
static const struct file_operations fops_addba = {
284
.write = ath10k_dbg_sta_write_addba,
285
.open = simple_open,
286
.owner = THIS_MODULE,
287
.llseek = default_llseek,
288
};
289
290
static ssize_t ath10k_dbg_sta_write_addba_resp(struct file *file,
291
const char __user *user_buf,
292
size_t count, loff_t *ppos)
293
{
294
struct ieee80211_sta *sta = file->private_data;
295
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
296
struct ath10k *ar = arsta->arvif->ar;
297
u32 tid, status;
298
int ret;
299
char buf[64] = {};
300
301
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
302
user_buf, count);
303
if (ret <= 0)
304
return ret;
305
306
ret = sscanf(buf, "%u %u", &tid, &status);
307
if (ret != 2)
308
return -EINVAL;
309
310
/* Valid TID values are 0 through 15 */
311
if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
312
return -EINVAL;
313
314
mutex_lock(&ar->conf_mutex);
315
if ((ar->state != ATH10K_STATE_ON) ||
316
(arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
317
ret = count;
318
goto out;
319
}
320
321
ret = ath10k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
322
tid, status);
323
if (ret) {
324
ath10k_warn(ar, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
325
arsta->arvif->vdev_id, sta->addr, tid, status);
326
}
327
ret = count;
328
out:
329
mutex_unlock(&ar->conf_mutex);
330
return ret;
331
}
332
333
static const struct file_operations fops_addba_resp = {
334
.write = ath10k_dbg_sta_write_addba_resp,
335
.open = simple_open,
336
.owner = THIS_MODULE,
337
.llseek = default_llseek,
338
};
339
340
static ssize_t ath10k_dbg_sta_write_delba(struct file *file,
341
const char __user *user_buf,
342
size_t count, loff_t *ppos)
343
{
344
struct ieee80211_sta *sta = file->private_data;
345
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
346
struct ath10k *ar = arsta->arvif->ar;
347
u32 tid, initiator, reason;
348
int ret;
349
char buf[64] = {};
350
351
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
352
user_buf, count);
353
if (ret <= 0)
354
return ret;
355
356
ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
357
if (ret != 3)
358
return -EINVAL;
359
360
/* Valid TID values are 0 through 15 */
361
if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
362
return -EINVAL;
363
364
mutex_lock(&ar->conf_mutex);
365
if ((ar->state != ATH10K_STATE_ON) ||
366
(arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
367
ret = count;
368
goto out;
369
}
370
371
ret = ath10k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
372
tid, initiator, reason);
373
if (ret) {
374
ath10k_warn(ar, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
375
arsta->arvif->vdev_id, sta->addr, tid, initiator,
376
reason);
377
}
378
ret = count;
379
out:
380
mutex_unlock(&ar->conf_mutex);
381
return ret;
382
}
383
384
static const struct file_operations fops_delba = {
385
.write = ath10k_dbg_sta_write_delba,
386
.open = simple_open,
387
.owner = THIS_MODULE,
388
.llseek = default_llseek,
389
};
390
391
static ssize_t ath10k_dbg_sta_read_peer_debug_trigger(struct file *file,
392
char __user *user_buf,
393
size_t count,
394
loff_t *ppos)
395
{
396
struct ieee80211_sta *sta = file->private_data;
397
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
398
struct ath10k *ar = arsta->arvif->ar;
399
char buf[8];
400
int len = 0;
401
402
mutex_lock(&ar->conf_mutex);
403
len = scnprintf(buf, sizeof(buf) - len,
404
"Write 1 to once trigger the debug logs\n");
405
mutex_unlock(&ar->conf_mutex);
406
407
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
408
}
409
410
static ssize_t
411
ath10k_dbg_sta_write_peer_debug_trigger(struct file *file,
412
const char __user *user_buf,
413
size_t count, loff_t *ppos)
414
{
415
struct ieee80211_sta *sta = file->private_data;
416
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
417
struct ath10k *ar = arsta->arvif->ar;
418
u8 peer_debug_trigger;
419
int ret;
420
421
if (kstrtou8_from_user(user_buf, count, 0, &peer_debug_trigger))
422
return -EINVAL;
423
424
if (peer_debug_trigger != 1)
425
return -EINVAL;
426
427
mutex_lock(&ar->conf_mutex);
428
429
if (ar->state != ATH10K_STATE_ON) {
430
ret = -ENETDOWN;
431
goto out;
432
}
433
434
ret = ath10k_wmi_peer_set_param(ar, arsta->arvif->vdev_id, sta->addr,
435
ar->wmi.peer_param->debug, peer_debug_trigger);
436
if (ret) {
437
ath10k_warn(ar, "failed to set param to trigger peer tid logs for station ret: %d\n",
438
ret);
439
goto out;
440
}
441
out:
442
mutex_unlock(&ar->conf_mutex);
443
return ret ?: count;
444
}
445
446
static const struct file_operations fops_peer_debug_trigger = {
447
.open = simple_open,
448
.read = ath10k_dbg_sta_read_peer_debug_trigger,
449
.write = ath10k_dbg_sta_write_peer_debug_trigger,
450
.owner = THIS_MODULE,
451
.llseek = default_llseek,
452
};
453
454
static ssize_t ath10k_dbg_sta_read_peer_ps_state(struct file *file,
455
char __user *user_buf,
456
size_t count, loff_t *ppos)
457
{
458
struct ieee80211_sta *sta = file->private_data;
459
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
460
struct ath10k *ar = arsta->arvif->ar;
461
char buf[20];
462
int len = 0;
463
464
spin_lock_bh(&ar->data_lock);
465
466
len = scnprintf(buf, sizeof(buf) - len, "%d\n",
467
arsta->peer_ps_state);
468
469
spin_unlock_bh(&ar->data_lock);
470
471
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
472
}
473
474
static const struct file_operations fops_peer_ps_state = {
475
.open = simple_open,
476
.read = ath10k_dbg_sta_read_peer_ps_state,
477
.owner = THIS_MODULE,
478
.llseek = default_llseek,
479
};
480
481
static char *get_err_str(enum ath10k_pkt_rx_err i)
482
{
483
switch (i) {
484
case ATH10K_PKT_RX_ERR_FCS:
485
return "fcs_err";
486
case ATH10K_PKT_RX_ERR_TKIP:
487
return "tkip_err";
488
case ATH10K_PKT_RX_ERR_CRYPT:
489
return "crypt_err";
490
case ATH10K_PKT_RX_ERR_PEER_IDX_INVAL:
491
return "peer_idx_inval";
492
case ATH10K_PKT_RX_ERR_MAX:
493
return "unknown";
494
}
495
496
return "unknown";
497
}
498
499
static char *get_num_ampdu_subfrm_str(enum ath10k_ampdu_subfrm_num i)
500
{
501
switch (i) {
502
case ATH10K_AMPDU_SUBFRM_NUM_10:
503
return "up to 10";
504
case ATH10K_AMPDU_SUBFRM_NUM_20:
505
return "11-20";
506
case ATH10K_AMPDU_SUBFRM_NUM_30:
507
return "21-30";
508
case ATH10K_AMPDU_SUBFRM_NUM_40:
509
return "31-40";
510
case ATH10K_AMPDU_SUBFRM_NUM_50:
511
return "41-50";
512
case ATH10K_AMPDU_SUBFRM_NUM_60:
513
return "51-60";
514
case ATH10K_AMPDU_SUBFRM_NUM_MORE:
515
return ">60";
516
case ATH10K_AMPDU_SUBFRM_NUM_MAX:
517
return "0";
518
}
519
520
return "0";
521
}
522
523
static char *get_num_amsdu_subfrm_str(enum ath10k_amsdu_subfrm_num i)
524
{
525
switch (i) {
526
case ATH10K_AMSDU_SUBFRM_NUM_1:
527
return "1";
528
case ATH10K_AMSDU_SUBFRM_NUM_2:
529
return "2";
530
case ATH10K_AMSDU_SUBFRM_NUM_3:
531
return "3";
532
case ATH10K_AMSDU_SUBFRM_NUM_4:
533
return "4";
534
case ATH10K_AMSDU_SUBFRM_NUM_MORE:
535
return ">4";
536
case ATH10K_AMSDU_SUBFRM_NUM_MAX:
537
return "0";
538
}
539
540
return "0";
541
}
542
543
#define PRINT_TID_STATS(_field, _tabs) \
544
do { \
545
int k = 0; \
546
for (j = 0; j <= IEEE80211_NUM_TIDS; j++) { \
547
if (ar->sta_tid_stats_mask & BIT(j)) { \
548
len += scnprintf(buf + len, buf_len - len, \
549
"[%02d] %-10lu ", \
550
j, stats[j]._field); \
551
k++; \
552
if (k % 8 == 0) { \
553
len += scnprintf(buf + len, \
554
buf_len - len, "\n"); \
555
len += scnprintf(buf + len, \
556
buf_len - len, \
557
_tabs); \
558
} \
559
} \
560
} \
561
len += scnprintf(buf + len, buf_len - len, "\n"); \
562
} while (0)
563
564
static ssize_t ath10k_dbg_sta_read_tid_stats(struct file *file,
565
char __user *user_buf,
566
size_t count, loff_t *ppos)
567
{
568
struct ieee80211_sta *sta = file->private_data;
569
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
570
struct ath10k *ar = arsta->arvif->ar;
571
struct ath10k_sta_tid_stats *stats = arsta->tid_stats;
572
size_t len = 0, buf_len = 1048 * IEEE80211_NUM_TIDS;
573
char *buf;
574
int i, j;
575
ssize_t ret;
576
577
buf = kzalloc(buf_len, GFP_KERNEL);
578
if (!buf)
579
return -ENOMEM;
580
581
mutex_lock(&ar->conf_mutex);
582
583
spin_lock_bh(&ar->data_lock);
584
585
len += scnprintf(buf + len, buf_len - len,
586
"\n\t\tDriver Rx pkt stats per tid, ([tid] count)\n");
587
len += scnprintf(buf + len, buf_len - len,
588
"\t\t------------------------------------------\n");
589
len += scnprintf(buf + len, buf_len - len, "MSDUs from FW\t\t\t");
590
PRINT_TID_STATS(rx_pkt_from_fw, "\t\t\t\t");
591
592
len += scnprintf(buf + len, buf_len - len, "MSDUs unchained\t\t\t");
593
PRINT_TID_STATS(rx_pkt_unchained, "\t\t\t\t");
594
595
len += scnprintf(buf + len, buf_len - len,
596
"MSDUs locally dropped:chained\t");
597
PRINT_TID_STATS(rx_pkt_drop_chained, "\t\t\t\t");
598
599
len += scnprintf(buf + len, buf_len - len,
600
"MSDUs locally dropped:filtered\t");
601
PRINT_TID_STATS(rx_pkt_drop_filter, "\t\t\t\t");
602
603
len += scnprintf(buf + len, buf_len - len,
604
"MSDUs queued for mac80211\t");
605
PRINT_TID_STATS(rx_pkt_queued_for_mac, "\t\t\t\t");
606
607
for (i = 0; i < ATH10K_PKT_RX_ERR_MAX; i++) {
608
len += scnprintf(buf + len, buf_len - len,
609
"MSDUs with error:%s\t", get_err_str(i));
610
PRINT_TID_STATS(rx_pkt_err[i], "\t\t\t\t");
611
}
612
613
len += scnprintf(buf + len, buf_len - len, "\n");
614
for (i = 0; i < ATH10K_AMPDU_SUBFRM_NUM_MAX; i++) {
615
len += scnprintf(buf + len, buf_len - len,
616
"A-MPDU num subframes %s\t",
617
get_num_ampdu_subfrm_str(i));
618
PRINT_TID_STATS(rx_pkt_ampdu[i], "\t\t\t\t");
619
}
620
621
len += scnprintf(buf + len, buf_len - len, "\n");
622
for (i = 0; i < ATH10K_AMSDU_SUBFRM_NUM_MAX; i++) {
623
len += scnprintf(buf + len, buf_len - len,
624
"A-MSDU num subframes %s\t\t",
625
get_num_amsdu_subfrm_str(i));
626
PRINT_TID_STATS(rx_pkt_amsdu[i], "\t\t\t\t");
627
}
628
629
spin_unlock_bh(&ar->data_lock);
630
631
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
632
633
kfree(buf);
634
635
mutex_unlock(&ar->conf_mutex);
636
637
return ret;
638
}
639
640
static const struct file_operations fops_tid_stats_dump = {
641
.open = simple_open,
642
.read = ath10k_dbg_sta_read_tid_stats,
643
.owner = THIS_MODULE,
644
.llseek = default_llseek,
645
};
646
647
static ssize_t ath10k_dbg_sta_dump_tx_stats(struct file *file,
648
char __user *user_buf,
649
size_t count, loff_t *ppos)
650
{
651
struct ieee80211_sta *sta = file->private_data;
652
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
653
struct ath10k *ar = arsta->arvif->ar;
654
struct ath10k_htt_data_stats *stats;
655
const char *str_name[ATH10K_STATS_TYPE_MAX] = {"succ", "fail",
656
"retry", "ampdu"};
657
const char *str[ATH10K_COUNTER_TYPE_MAX] = {"bytes", "packets"};
658
int len = 0, i, j, k, retval = 0;
659
const int size = 16 * 4096;
660
char *buf;
661
662
buf = kzalloc(size, GFP_KERNEL);
663
if (!buf)
664
return -ENOMEM;
665
666
mutex_lock(&ar->conf_mutex);
667
668
if (!arsta->tx_stats) {
669
ath10k_warn(ar, "failed to get tx stats");
670
mutex_unlock(&ar->conf_mutex);
671
kfree(buf);
672
return 0;
673
}
674
675
spin_lock_bh(&ar->data_lock);
676
for (k = 0; k < ATH10K_STATS_TYPE_MAX; k++) {
677
for (j = 0; j < ATH10K_COUNTER_TYPE_MAX; j++) {
678
stats = &arsta->tx_stats->stats[k];
679
len += scnprintf(buf + len, size - len, "%s_%s\n",
680
str_name[k],
681
str[j]);
682
len += scnprintf(buf + len, size - len,
683
" VHT MCS %s\n",
684
str[j]);
685
for (i = 0; i < ATH10K_VHT_MCS_NUM; i++)
686
len += scnprintf(buf + len, size - len,
687
" %llu ",
688
stats->vht[j][i]);
689
len += scnprintf(buf + len, size - len, "\n");
690
len += scnprintf(buf + len, size - len, " HT MCS %s\n",
691
str[j]);
692
for (i = 0; i < ATH10K_HT_MCS_NUM; i++)
693
len += scnprintf(buf + len, size - len,
694
" %llu ", stats->ht[j][i]);
695
len += scnprintf(buf + len, size - len, "\n");
696
len += scnprintf(buf + len, size - len,
697
" BW %s (20,5,10,40,80,160 MHz)\n", str[j]);
698
len += scnprintf(buf + len, size - len,
699
" %llu %llu %llu %llu %llu %llu\n",
700
stats->bw[j][0], stats->bw[j][1],
701
stats->bw[j][2], stats->bw[j][3],
702
stats->bw[j][4], stats->bw[j][5]);
703
len += scnprintf(buf + len, size - len,
704
" NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
705
len += scnprintf(buf + len, size - len,
706
" %llu %llu %llu %llu\n",
707
stats->nss[j][0], stats->nss[j][1],
708
stats->nss[j][2], stats->nss[j][3]);
709
len += scnprintf(buf + len, size - len,
710
" GI %s (LGI,SGI)\n",
711
str[j]);
712
len += scnprintf(buf + len, size - len, " %llu %llu\n",
713
stats->gi[j][0], stats->gi[j][1]);
714
len += scnprintf(buf + len, size - len,
715
" legacy rate %s (1,2 ... Mbps)\n ",
716
str[j]);
717
for (i = 0; i < ATH10K_LEGACY_NUM; i++)
718
len += scnprintf(buf + len, size - len, "%llu ",
719
stats->legacy[j][i]);
720
len += scnprintf(buf + len, size - len, "\n");
721
len += scnprintf(buf + len, size - len,
722
" Rate table %s (1,2 ... Mbps)\n ",
723
str[j]);
724
for (i = 0; i < ATH10K_RATE_TABLE_NUM; i++) {
725
len += scnprintf(buf + len, size - len, "%llu ",
726
stats->rate_table[j][i]);
727
if (!((i + 1) % 8))
728
len +=
729
scnprintf(buf + len, size - len, "\n ");
730
}
731
}
732
}
733
734
len += scnprintf(buf + len, size - len,
735
"\nTX duration\n %llu usecs\n",
736
arsta->tx_stats->tx_duration);
737
len += scnprintf(buf + len, size - len,
738
"BA fails\n %llu\n", arsta->tx_stats->ba_fails);
739
len += scnprintf(buf + len, size - len,
740
"ack fails\n %llu\n", arsta->tx_stats->ack_fails);
741
spin_unlock_bh(&ar->data_lock);
742
743
if (len > size)
744
len = size;
745
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
746
kfree(buf);
747
748
mutex_unlock(&ar->conf_mutex);
749
return retval;
750
}
751
752
static const struct file_operations fops_tx_stats = {
753
.read = ath10k_dbg_sta_dump_tx_stats,
754
.open = simple_open,
755
.owner = THIS_MODULE,
756
.llseek = default_llseek,
757
};
758
759
void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
760
struct ieee80211_sta *sta, struct dentry *dir)
761
{
762
struct ath10k *ar = hw->priv;
763
764
debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
765
debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
766
debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
767
debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
768
debugfs_create_file("peer_debug_trigger", 0600, dir, sta,
769
&fops_peer_debug_trigger);
770
debugfs_create_file("dump_tid_stats", 0400, dir, sta,
771
&fops_tid_stats_dump);
772
773
if (ath10k_peer_stats_enabled(ar) &&
774
ath10k_debug_is_extd_tx_stats_enabled(ar))
775
debugfs_create_file("tx_stats", 0400, dir, sta,
776
&fops_tx_stats);
777
debugfs_create_file("peer_ps_state", 0400, dir, sta,
778
&fops_peer_ps_state);
779
}
780
781