Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/athk/ath12k/debugfs_sta.c
178701 views
1
// SPDX-License-Identifier: BSD-3-Clause-Clear
2
/*
3
* Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
4
*/
5
6
#include <linux/vmalloc.h>
7
8
#include "debugfs_sta.h"
9
#include "core.h"
10
#include "peer.h"
11
#include "debug.h"
12
#include "debugfs_htt_stats.h"
13
#include "debugfs.h"
14
15
static
16
u32 ath12k_dbg_sta_dump_rate_stats(u8 *buf, u32 offset, const int size,
17
bool he_rates_avail,
18
const struct ath12k_rx_peer_rate_stats *stats)
19
{
20
static const char *legacy_rate_str[HAL_RX_MAX_NUM_LEGACY_RATES] = {
21
"1 Mbps", "2 Mbps", "5.5 Mbps", "6 Mbps",
22
"9 Mbps", "11 Mbps", "12 Mbps", "18 Mbps",
23
"24 Mbps", "36 Mbps", "48 Mbps", "54 Mbps"};
24
u8 max_bw = HAL_RX_BW_MAX, max_gi = HAL_RX_GI_MAX, max_mcs = HAL_RX_MAX_NSS;
25
int mcs = 0, bw = 0, nss = 0, gi = 0, bw_num = 0;
26
u32 i, len = offset, max = max_bw * max_gi * max_mcs;
27
bool found;
28
29
len += scnprintf(buf + len, size - len, "\nEHT stats:\n");
30
for (i = 0; i <= HAL_RX_MAX_MCS_BE; i++)
31
len += scnprintf(buf + len, size - len,
32
"MCS %d: %llu%s", i, stats->be_mcs_count[i],
33
(i + 1) % 8 ? "\t" : "\n");
34
35
len += scnprintf(buf + len, size - len, "\nHE stats:\n");
36
for (i = 0; i <= HAL_RX_MAX_MCS_HE; i++)
37
len += scnprintf(buf + len, size - len,
38
"MCS %d: %llu%s", i, stats->he_mcs_count[i],
39
(i + 1) % 6 ? "\t" : "\n");
40
41
len += scnprintf(buf + len, size - len, "\nVHT stats:\n");
42
for (i = 0; i <= HAL_RX_MAX_MCS_VHT; i++)
43
len += scnprintf(buf + len, size - len,
44
"MCS %d: %llu%s", i, stats->vht_mcs_count[i],
45
(i + 1) % 5 ? "\t" : "\n");
46
47
len += scnprintf(buf + len, size - len, "\nHT stats:\n");
48
for (i = 0; i <= HAL_RX_MAX_MCS_HT; i++)
49
len += scnprintf(buf + len, size - len,
50
"MCS %d: %llu%s", i, stats->ht_mcs_count[i],
51
(i + 1) % 8 ? "\t" : "\n");
52
53
len += scnprintf(buf + len, size - len, "\nLegacy stats:\n");
54
for (i = 0; i < HAL_RX_MAX_NUM_LEGACY_RATES; i++)
55
len += scnprintf(buf + len, size - len,
56
"%s: %llu%s", legacy_rate_str[i],
57
stats->legacy_count[i],
58
(i + 1) % 4 ? "\t" : "\n");
59
60
len += scnprintf(buf + len, size - len, "\nNSS stats:\n");
61
for (i = 0; i < HAL_RX_MAX_NSS; i++)
62
len += scnprintf(buf + len, size - len,
63
"%dx%d: %llu ", i + 1, i + 1,
64
stats->nss_count[i]);
65
66
len += scnprintf(buf + len, size - len,
67
"\n\nGI: 0.8 us %llu 0.4 us %llu 1.6 us %llu 3.2 us %llu\n",
68
stats->gi_count[0],
69
stats->gi_count[1],
70
stats->gi_count[2],
71
stats->gi_count[3]);
72
73
len += scnprintf(buf + len, size - len,
74
"BW: 20 MHz %llu 40 MHz %llu 80 MHz %llu 160 MHz %llu 320 MHz %llu\n",
75
stats->bw_count[0],
76
stats->bw_count[1],
77
stats->bw_count[2],
78
stats->bw_count[3],
79
stats->bw_count[4]);
80
81
for (i = 0; i < max; i++) {
82
found = false;
83
84
for (mcs = 0; mcs <= HAL_RX_MAX_MCS_HT; mcs++) {
85
if (stats->rx_rate[bw][gi][nss][mcs]) {
86
found = true;
87
break;
88
}
89
}
90
91
if (!found)
92
goto skip_report;
93
94
switch (bw) {
95
case HAL_RX_BW_20MHZ:
96
bw_num = 20;
97
break;
98
case HAL_RX_BW_40MHZ:
99
bw_num = 40;
100
break;
101
case HAL_RX_BW_80MHZ:
102
bw_num = 80;
103
break;
104
case HAL_RX_BW_160MHZ:
105
bw_num = 160;
106
break;
107
case HAL_RX_BW_320MHZ:
108
bw_num = 320;
109
break;
110
}
111
112
len += scnprintf(buf + len, size - len, "\n%d Mhz gi %d us %dx%d : ",
113
bw_num, gi, nss + 1, nss + 1);
114
115
for (mcs = 0; mcs <= HAL_RX_MAX_MCS_HT; mcs++) {
116
if (stats->rx_rate[bw][gi][nss][mcs])
117
len += scnprintf(buf + len, size - len,
118
" %d:%llu", mcs,
119
stats->rx_rate[bw][gi][nss][mcs]);
120
}
121
122
skip_report:
123
if (nss++ >= max_mcs - 1) {
124
nss = 0;
125
if (gi++ >= max_gi - 1) {
126
gi = 0;
127
if (bw < max_bw - 1)
128
bw++;
129
}
130
}
131
}
132
133
len += scnprintf(buf + len, size - len, "\n");
134
135
return len - offset;
136
}
137
138
static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file,
139
char __user *user_buf,
140
size_t count, loff_t *ppos)
141
{
142
struct ieee80211_link_sta *link_sta = file->private_data;
143
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(link_sta->sta);
144
const int size = ATH12K_STA_RX_STATS_BUF_SIZE;
145
struct ath12k_hw *ah = ahsta->ahvif->ah;
146
struct ath12k_rx_peer_stats *rx_stats;
147
struct ath12k_link_sta *arsta;
148
u8 link_id = link_sta->link_id;
149
int len = 0, i, ret = 0;
150
bool he_rates_avail;
151
struct ath12k *ar;
152
153
wiphy_lock(ah->hw->wiphy);
154
155
if (!(BIT(link_id) & ahsta->links_map)) {
156
wiphy_unlock(ah->hw->wiphy);
157
return -ENOENT;
158
}
159
160
arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);
161
if (!arsta || !arsta->arvif->ar) {
162
wiphy_unlock(ah->hw->wiphy);
163
return -ENOENT;
164
}
165
166
ar = arsta->arvif->ar;
167
168
u8 *buf __free(kfree) = kzalloc(size, GFP_KERNEL);
169
if (!buf) {
170
ret = -ENOENT;
171
goto out;
172
}
173
174
spin_lock_bh(&ar->ab->base_lock);
175
176
rx_stats = arsta->rx_stats;
177
if (!rx_stats) {
178
ret = -ENOENT;
179
goto unlock;
180
}
181
182
len += scnprintf(buf + len, size - len, "RX peer stats:\n\n");
183
len += scnprintf(buf + len, size - len, "Num of MSDUs: %llu\n",
184
rx_stats->num_msdu);
185
len += scnprintf(buf + len, size - len, "Num of MSDUs with TCP L4: %llu\n",
186
rx_stats->tcp_msdu_count);
187
len += scnprintf(buf + len, size - len, "Num of MSDUs with UDP L4: %llu\n",
188
rx_stats->udp_msdu_count);
189
len += scnprintf(buf + len, size - len, "Num of other MSDUs: %llu\n",
190
rx_stats->other_msdu_count);
191
len += scnprintf(buf + len, size - len, "Num of MSDUs part of AMPDU: %llu\n",
192
rx_stats->ampdu_msdu_count);
193
len += scnprintf(buf + len, size - len, "Num of MSDUs not part of AMPDU: %llu\n",
194
rx_stats->non_ampdu_msdu_count);
195
len += scnprintf(buf + len, size - len, "Num of MSDUs using STBC: %llu\n",
196
rx_stats->stbc_count);
197
len += scnprintf(buf + len, size - len, "Num of MSDUs beamformed: %llu\n",
198
rx_stats->beamformed_count);
199
len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS ok: %llu\n",
200
rx_stats->num_mpdu_fcs_ok);
201
len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS error: %llu\n",
202
rx_stats->num_mpdu_fcs_err);
203
204
he_rates_avail = (rx_stats->pream_cnt[HAL_RX_PREAMBLE_11AX] > 1) ? true : false;
205
206
len += scnprintf(buf + len, size - len,
207
"preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu 11BE %llu\n",
208
rx_stats->pream_cnt[0], rx_stats->pream_cnt[1],
209
rx_stats->pream_cnt[2], rx_stats->pream_cnt[3],
210
rx_stats->pream_cnt[4], rx_stats->pream_cnt[6]);
211
len += scnprintf(buf + len, size - len,
212
"reception type: SU %llu MU_MIMO %llu MU_OFDMA %llu MU_OFDMA_MIMO %llu\n",
213
rx_stats->reception_type[0], rx_stats->reception_type[1],
214
rx_stats->reception_type[2], rx_stats->reception_type[3]);
215
216
len += scnprintf(buf + len, size - len, "TID(0-15) Legacy TID(16):");
217
for (i = 0; i <= IEEE80211_NUM_TIDS; i++)
218
len += scnprintf(buf + len, size - len, "%llu ", rx_stats->tid_count[i]);
219
220
len += scnprintf(buf + len, size - len, "\nRX Duration:%llu\n",
221
rx_stats->rx_duration);
222
223
len += scnprintf(buf + len, size - len,
224
"\nDCM: %llu\nRU26: %llu\nRU52: %llu\nRU106: %llu\nRU242: %llu\nRU484: %llu\nRU996: %llu\nRU996x2: %llu\n",
225
rx_stats->dcm_count, rx_stats->ru_alloc_cnt[0],
226
rx_stats->ru_alloc_cnt[1], rx_stats->ru_alloc_cnt[2],
227
rx_stats->ru_alloc_cnt[3], rx_stats->ru_alloc_cnt[4],
228
rx_stats->ru_alloc_cnt[5], rx_stats->ru_alloc_cnt[6]);
229
230
len += scnprintf(buf + len, size - len, "\nRX success packet stats:\n");
231
len += ath12k_dbg_sta_dump_rate_stats(buf, len, size, he_rates_avail,
232
&rx_stats->pkt_stats);
233
234
len += scnprintf(buf + len, size - len, "\n");
235
236
len += scnprintf(buf + len, size - len, "\nRX success byte stats:\n");
237
len += ath12k_dbg_sta_dump_rate_stats(buf, len, size, he_rates_avail,
238
&rx_stats->byte_stats);
239
240
unlock:
241
spin_unlock_bh(&ar->ab->base_lock);
242
243
if (len)
244
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
245
out:
246
wiphy_unlock(ah->hw->wiphy);
247
return ret;
248
}
249
250
static const struct file_operations fops_rx_stats = {
251
.read = ath12k_dbg_sta_dump_rx_stats,
252
.open = simple_open,
253
.owner = THIS_MODULE,
254
.llseek = default_llseek,
255
};
256
257
static ssize_t ath12k_dbg_sta_reset_rx_stats(struct file *file,
258
const char __user *buf,
259
size_t count, loff_t *ppos)
260
{
261
struct ieee80211_link_sta *link_sta = file->private_data;
262
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(link_sta->sta);
263
struct ath12k_hw *ah = ahsta->ahvif->ah;
264
struct ath12k_rx_peer_stats *rx_stats;
265
struct ath12k_link_sta *arsta;
266
u8 link_id = link_sta->link_id;
267
struct ath12k *ar;
268
bool reset;
269
int ret;
270
271
ret = kstrtobool_from_user(buf, count, &reset);
272
if (ret)
273
return ret;
274
275
if (!reset)
276
return -EINVAL;
277
278
wiphy_lock(ah->hw->wiphy);
279
280
if (!(BIT(link_id) & ahsta->links_map)) {
281
ret = -ENOENT;
282
goto out;
283
}
284
285
arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);
286
if (!arsta || !arsta->arvif->ar) {
287
ret = -ENOENT;
288
goto out;
289
}
290
291
ar = arsta->arvif->ar;
292
293
spin_lock_bh(&ar->ab->base_lock);
294
295
rx_stats = arsta->rx_stats;
296
if (!rx_stats) {
297
spin_unlock_bh(&ar->ab->base_lock);
298
ret = -ENOENT;
299
goto out;
300
}
301
302
memset(rx_stats, 0, sizeof(*rx_stats));
303
spin_unlock_bh(&ar->ab->base_lock);
304
305
ret = count;
306
out:
307
wiphy_unlock(ah->hw->wiphy);
308
return ret;
309
}
310
311
static const struct file_operations fops_reset_rx_stats = {
312
.write = ath12k_dbg_sta_reset_rx_stats,
313
.open = simple_open,
314
.owner = THIS_MODULE,
315
.llseek = default_llseek,
316
};
317
318
void ath12k_debugfs_link_sta_op_add(struct ieee80211_hw *hw,
319
struct ieee80211_vif *vif,
320
struct ieee80211_link_sta *link_sta,
321
struct dentry *dir)
322
{
323
struct ath12k *ar;
324
325
lockdep_assert_wiphy(hw->wiphy);
326
327
ar = ath12k_get_ar_by_vif(hw, vif, link_sta->link_id);
328
if (!ar)
329
return;
330
331
if (ath12k_debugfs_is_extd_rx_stats_enabled(ar)) {
332
debugfs_create_file("rx_stats", 0400, dir, link_sta,
333
&fops_rx_stats);
334
debugfs_create_file("reset_rx_stats", 0200, dir, link_sta,
335
&fops_reset_rx_stats);
336
}
337
}
338
339