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