1 // SPDX-License-Identifier: BSD-3-Clause-Clear
3 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
6 #include <linux/vmalloc.h>
8 #include "debugfs_sta.h"
13 #include "debugfs_htt_stats.h"
15 void ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta
*arsta
,
16 struct ath11k_per_peer_tx_stats
*peer_stats
,
19 struct rate_info
*txrate
= &arsta
->txrate
;
20 struct ath11k_htt_tx_stats
*tx_stats
;
26 tx_stats
= arsta
->tx_stats
;
27 gi
= FIELD_GET(RATE_INFO_FLAGS_SHORT_GI
, arsta
->txrate
.flags
);
29 bw
= ath11k_mac_mac80211_bw_to_ath11k_bw(txrate
->bw
);
30 nss
= txrate
->nss
- 1;
32 #define STATS_OP_FMT(name) tx_stats->stats[ATH11K_STATS_TYPE_##name]
34 if (txrate
->flags
& RATE_INFO_FLAGS_HE_MCS
) {
35 STATS_OP_FMT(SUCC
).he
[0][mcs
] += peer_stats
->succ_bytes
;
36 STATS_OP_FMT(SUCC
).he
[1][mcs
] += peer_stats
->succ_pkts
;
37 STATS_OP_FMT(FAIL
).he
[0][mcs
] += peer_stats
->failed_bytes
;
38 STATS_OP_FMT(FAIL
).he
[1][mcs
] += peer_stats
->failed_pkts
;
39 STATS_OP_FMT(RETRY
).he
[0][mcs
] += peer_stats
->retry_bytes
;
40 STATS_OP_FMT(RETRY
).he
[1][mcs
] += peer_stats
->retry_pkts
;
41 } else if (txrate
->flags
& RATE_INFO_FLAGS_VHT_MCS
) {
42 STATS_OP_FMT(SUCC
).vht
[0][mcs
] += peer_stats
->succ_bytes
;
43 STATS_OP_FMT(SUCC
).vht
[1][mcs
] += peer_stats
->succ_pkts
;
44 STATS_OP_FMT(FAIL
).vht
[0][mcs
] += peer_stats
->failed_bytes
;
45 STATS_OP_FMT(FAIL
).vht
[1][mcs
] += peer_stats
->failed_pkts
;
46 STATS_OP_FMT(RETRY
).vht
[0][mcs
] += peer_stats
->retry_bytes
;
47 STATS_OP_FMT(RETRY
).vht
[1][mcs
] += peer_stats
->retry_pkts
;
48 } else if (txrate
->flags
& RATE_INFO_FLAGS_MCS
) {
49 STATS_OP_FMT(SUCC
).ht
[0][mcs
] += peer_stats
->succ_bytes
;
50 STATS_OP_FMT(SUCC
).ht
[1][mcs
] += peer_stats
->succ_pkts
;
51 STATS_OP_FMT(FAIL
).ht
[0][mcs
] += peer_stats
->failed_bytes
;
52 STATS_OP_FMT(FAIL
).ht
[1][mcs
] += peer_stats
->failed_pkts
;
53 STATS_OP_FMT(RETRY
).ht
[0][mcs
] += peer_stats
->retry_bytes
;
54 STATS_OP_FMT(RETRY
).ht
[1][mcs
] += peer_stats
->retry_pkts
;
56 mcs
= legacy_rate_idx
;
58 STATS_OP_FMT(SUCC
).legacy
[0][mcs
] += peer_stats
->succ_bytes
;
59 STATS_OP_FMT(SUCC
).legacy
[1][mcs
] += peer_stats
->succ_pkts
;
60 STATS_OP_FMT(FAIL
).legacy
[0][mcs
] += peer_stats
->failed_bytes
;
61 STATS_OP_FMT(FAIL
).legacy
[1][mcs
] += peer_stats
->failed_pkts
;
62 STATS_OP_FMT(RETRY
).legacy
[0][mcs
] += peer_stats
->retry_bytes
;
63 STATS_OP_FMT(RETRY
).legacy
[1][mcs
] += peer_stats
->retry_pkts
;
66 if (peer_stats
->is_ampdu
) {
67 tx_stats
->ba_fails
+= peer_stats
->ba_fails
;
69 if (txrate
->flags
& RATE_INFO_FLAGS_HE_MCS
) {
70 STATS_OP_FMT(AMPDU
).he
[0][mcs
] +=
71 peer_stats
->succ_bytes
+ peer_stats
->retry_bytes
;
72 STATS_OP_FMT(AMPDU
).he
[1][mcs
] +=
73 peer_stats
->succ_pkts
+ peer_stats
->retry_pkts
;
74 } else if (txrate
->flags
& RATE_INFO_FLAGS_MCS
) {
75 STATS_OP_FMT(AMPDU
).ht
[0][mcs
] +=
76 peer_stats
->succ_bytes
+ peer_stats
->retry_bytes
;
77 STATS_OP_FMT(AMPDU
).ht
[1][mcs
] +=
78 peer_stats
->succ_pkts
+ peer_stats
->retry_pkts
;
80 STATS_OP_FMT(AMPDU
).vht
[0][mcs
] +=
81 peer_stats
->succ_bytes
+ peer_stats
->retry_bytes
;
82 STATS_OP_FMT(AMPDU
).vht
[1][mcs
] +=
83 peer_stats
->succ_pkts
+ peer_stats
->retry_pkts
;
85 STATS_OP_FMT(AMPDU
).bw
[0][bw
] +=
86 peer_stats
->succ_bytes
+ peer_stats
->retry_bytes
;
87 STATS_OP_FMT(AMPDU
).nss
[0][nss
] +=
88 peer_stats
->succ_bytes
+ peer_stats
->retry_bytes
;
89 STATS_OP_FMT(AMPDU
).gi
[0][gi
] +=
90 peer_stats
->succ_bytes
+ peer_stats
->retry_bytes
;
91 STATS_OP_FMT(AMPDU
).bw
[1][bw
] +=
92 peer_stats
->succ_pkts
+ peer_stats
->retry_pkts
;
93 STATS_OP_FMT(AMPDU
).nss
[1][nss
] +=
94 peer_stats
->succ_pkts
+ peer_stats
->retry_pkts
;
95 STATS_OP_FMT(AMPDU
).gi
[1][gi
] +=
96 peer_stats
->succ_pkts
+ peer_stats
->retry_pkts
;
98 tx_stats
->ack_fails
+= peer_stats
->ba_fails
;
101 STATS_OP_FMT(SUCC
).bw
[0][bw
] += peer_stats
->succ_bytes
;
102 STATS_OP_FMT(SUCC
).nss
[0][nss
] += peer_stats
->succ_bytes
;
103 STATS_OP_FMT(SUCC
).gi
[0][gi
] += peer_stats
->succ_bytes
;
105 STATS_OP_FMT(SUCC
).bw
[1][bw
] += peer_stats
->succ_pkts
;
106 STATS_OP_FMT(SUCC
).nss
[1][nss
] += peer_stats
->succ_pkts
;
107 STATS_OP_FMT(SUCC
).gi
[1][gi
] += peer_stats
->succ_pkts
;
109 STATS_OP_FMT(FAIL
).bw
[0][bw
] += peer_stats
->failed_bytes
;
110 STATS_OP_FMT(FAIL
).nss
[0][nss
] += peer_stats
->failed_bytes
;
111 STATS_OP_FMT(FAIL
).gi
[0][gi
] += peer_stats
->failed_bytes
;
113 STATS_OP_FMT(FAIL
).bw
[1][bw
] += peer_stats
->failed_pkts
;
114 STATS_OP_FMT(FAIL
).nss
[1][nss
] += peer_stats
->failed_pkts
;
115 STATS_OP_FMT(FAIL
).gi
[1][gi
] += peer_stats
->failed_pkts
;
117 STATS_OP_FMT(RETRY
).bw
[0][bw
] += peer_stats
->retry_bytes
;
118 STATS_OP_FMT(RETRY
).nss
[0][nss
] += peer_stats
->retry_bytes
;
119 STATS_OP_FMT(RETRY
).gi
[0][gi
] += peer_stats
->retry_bytes
;
121 STATS_OP_FMT(RETRY
).bw
[1][bw
] += peer_stats
->retry_pkts
;
122 STATS_OP_FMT(RETRY
).nss
[1][nss
] += peer_stats
->retry_pkts
;
123 STATS_OP_FMT(RETRY
).gi
[1][gi
] += peer_stats
->retry_pkts
;
125 tx_stats
->tx_duration
+= peer_stats
->duration
;
128 void ath11k_debugfs_sta_update_txcompl(struct ath11k
*ar
,
129 struct sk_buff
*msdu
,
130 struct hal_tx_status
*ts
)
132 struct ath11k_base
*ab
= ar
->ab
;
133 struct ath11k_per_peer_tx_stats
*peer_stats
= &ar
->cached_stats
;
134 enum hal_tx_rate_stats_pkt_type pkt_type
;
135 enum hal_tx_rate_stats_sgi sgi
;
136 enum hal_tx_rate_stats_bw bw
;
137 struct ath11k_peer
*peer
;
138 struct ath11k_sta
*arsta
;
139 struct ieee80211_sta
*sta
;
146 spin_lock_bh(&ab
->base_lock
);
147 peer
= ath11k_peer_find_by_id(ab
, ts
->peer_id
);
148 if (!peer
|| !peer
->sta
) {
149 ath11k_warn(ab
, "failed to find the peer\n");
150 spin_unlock_bh(&ab
->base_lock
);
156 arsta
= (struct ath11k_sta
*)sta
->drv_priv
;
158 memset(&arsta
->txrate
, 0, sizeof(arsta
->txrate
));
159 pkt_type
= FIELD_GET(HAL_TX_RATE_STATS_INFO0_PKT_TYPE
,
161 mcs
= FIELD_GET(HAL_TX_RATE_STATS_INFO0_MCS
,
163 sgi
= FIELD_GET(HAL_TX_RATE_STATS_INFO0_SGI
,
165 bw
= FIELD_GET(HAL_TX_RATE_STATS_INFO0_BW
, ts
->rate_stats
);
167 if (pkt_type
== HAL_TX_RATE_STATS_PKT_TYPE_11A
||
168 pkt_type
== HAL_TX_RATE_STATS_PKT_TYPE_11B
) {
169 ret
= ath11k_mac_hw_ratecode_to_legacy_rate(mcs
,
175 arsta
->txrate
.legacy
= rate
;
176 } else if (pkt_type
== HAL_TX_RATE_STATS_PKT_TYPE_11N
) {
178 ath11k_warn(ab
, "Invalid HT mcs index %d\n", mcs
);
182 arsta
->txrate
.mcs
= mcs
+ 8 * (arsta
->last_txrate
.nss
- 1);
183 arsta
->txrate
.flags
= RATE_INFO_FLAGS_MCS
;
185 arsta
->txrate
.flags
|= RATE_INFO_FLAGS_SHORT_GI
;
186 } else if (pkt_type
== HAL_TX_RATE_STATS_PKT_TYPE_11AC
) {
188 ath11k_warn(ab
, "Invalid VHT mcs index %d\n", mcs
);
192 arsta
->txrate
.mcs
= mcs
;
193 arsta
->txrate
.flags
= RATE_INFO_FLAGS_VHT_MCS
;
195 arsta
->txrate
.flags
|= RATE_INFO_FLAGS_SHORT_GI
;
196 } else if (pkt_type
== HAL_TX_RATE_STATS_PKT_TYPE_11AX
) {
200 arsta
->txrate
.nss
= arsta
->last_txrate
.nss
;
201 arsta
->txrate
.bw
= ath11k_mac_bw_to_mac80211_bw(bw
);
203 ath11k_debugfs_sta_add_tx_stats(arsta
, peer_stats
, rate_idx
);
206 spin_unlock_bh(&ab
->base_lock
);
210 static ssize_t
ath11k_dbg_sta_dump_tx_stats(struct file
*file
,
211 char __user
*user_buf
,
212 size_t count
, loff_t
*ppos
)
214 struct ieee80211_sta
*sta
= file
->private_data
;
215 struct ath11k_sta
*arsta
= (struct ath11k_sta
*)sta
->drv_priv
;
216 struct ath11k
*ar
= arsta
->arvif
->ar
;
217 struct ath11k_htt_data_stats
*stats
;
218 static const char *str_name
[ATH11K_STATS_TYPE_MAX
] = {"succ", "fail",
220 static const char *str
[ATH11K_COUNTER_TYPE_MAX
] = {"bytes", "packets"};
221 int len
= 0, i
, j
, k
, retval
= 0;
222 const int size
= 2 * 4096;
225 if (!arsta
->tx_stats
)
228 buf
= kzalloc(size
, GFP_KERNEL
);
232 mutex_lock(&ar
->conf_mutex
);
234 spin_lock_bh(&ar
->data_lock
);
235 for (k
= 0; k
< ATH11K_STATS_TYPE_MAX
; k
++) {
236 for (j
= 0; j
< ATH11K_COUNTER_TYPE_MAX
; j
++) {
237 stats
= &arsta
->tx_stats
->stats
[k
];
238 len
+= scnprintf(buf
+ len
, size
- len
, "%s_%s\n",
241 len
+= scnprintf(buf
+ len
, size
- len
,
244 for (i
= 0; i
< ATH11K_HE_MCS_NUM
; i
++)
245 len
+= scnprintf(buf
+ len
, size
- len
,
248 len
+= scnprintf(buf
+ len
, size
- len
, "\n");
249 len
+= scnprintf(buf
+ len
, size
- len
,
252 for (i
= 0; i
< ATH11K_VHT_MCS_NUM
; i
++)
253 len
+= scnprintf(buf
+ len
, size
- len
,
256 len
+= scnprintf(buf
+ len
, size
- len
, "\n");
257 len
+= scnprintf(buf
+ len
, size
- len
, " HT MCS %s\n",
259 for (i
= 0; i
< ATH11K_HT_MCS_NUM
; i
++)
260 len
+= scnprintf(buf
+ len
, size
- len
,
261 " %llu ", stats
->ht
[j
][i
]);
262 len
+= scnprintf(buf
+ len
, size
- len
, "\n");
263 len
+= scnprintf(buf
+ len
, size
- len
,
264 " BW %s (20,40,80,160 MHz)\n", str
[j
]);
265 len
+= scnprintf(buf
+ len
, size
- len
,
266 " %llu %llu %llu %llu\n",
267 stats
->bw
[j
][0], stats
->bw
[j
][1],
268 stats
->bw
[j
][2], stats
->bw
[j
][3]);
269 len
+= scnprintf(buf
+ len
, size
- len
,
270 " NSS %s (1x1,2x2,3x3,4x4)\n", str
[j
]);
271 len
+= scnprintf(buf
+ len
, size
- len
,
272 " %llu %llu %llu %llu\n",
273 stats
->nss
[j
][0], stats
->nss
[j
][1],
274 stats
->nss
[j
][2], stats
->nss
[j
][3]);
275 len
+= scnprintf(buf
+ len
, size
- len
,
276 " GI %s (0.4us,0.8us,1.6us,3.2us)\n",
278 len
+= scnprintf(buf
+ len
, size
- len
,
279 " %llu %llu %llu %llu\n",
280 stats
->gi
[j
][0], stats
->gi
[j
][1],
281 stats
->gi
[j
][2], stats
->gi
[j
][3]);
282 len
+= scnprintf(buf
+ len
, size
- len
,
283 " legacy rate %s (1,2 ... Mbps)\n ",
285 for (i
= 0; i
< ATH11K_LEGACY_NUM
; i
++)
286 len
+= scnprintf(buf
+ len
, size
- len
, "%llu ",
287 stats
->legacy
[j
][i
]);
288 len
+= scnprintf(buf
+ len
, size
- len
, "\n");
292 len
+= scnprintf(buf
+ len
, size
- len
,
293 "\nTX duration\n %llu usecs\n",
294 arsta
->tx_stats
->tx_duration
);
295 len
+= scnprintf(buf
+ len
, size
- len
,
296 "BA fails\n %llu\n", arsta
->tx_stats
->ba_fails
);
297 len
+= scnprintf(buf
+ len
, size
- len
,
298 "ack fails\n %llu\n", arsta
->tx_stats
->ack_fails
);
299 spin_unlock_bh(&ar
->data_lock
);
303 retval
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
306 mutex_unlock(&ar
->conf_mutex
);
310 static const struct file_operations fops_tx_stats
= {
311 .read
= ath11k_dbg_sta_dump_tx_stats
,
313 .owner
= THIS_MODULE
,
314 .llseek
= default_llseek
,
317 static ssize_t
ath11k_dbg_sta_dump_rx_stats(struct file
*file
,
318 char __user
*user_buf
,
319 size_t count
, loff_t
*ppos
)
321 struct ieee80211_sta
*sta
= file
->private_data
;
322 struct ath11k_sta
*arsta
= (struct ath11k_sta
*)sta
->drv_priv
;
323 struct ath11k
*ar
= arsta
->arvif
->ar
;
324 struct ath11k_rx_peer_stats
*rx_stats
= arsta
->rx_stats
;
325 int len
= 0, i
, retval
= 0;
326 const int size
= 4096;
332 buf
= kzalloc(size
, GFP_KERNEL
);
336 mutex_lock(&ar
->conf_mutex
);
337 spin_lock_bh(&ar
->ab
->base_lock
);
339 len
+= scnprintf(buf
+ len
, size
- len
, "RX peer stats:\n");
340 len
+= scnprintf(buf
+ len
, size
- len
, "Num of MSDUs: %llu\n",
342 len
+= scnprintf(buf
+ len
, size
- len
, "Num of MSDUs with TCP L4: %llu\n",
343 rx_stats
->tcp_msdu_count
);
344 len
+= scnprintf(buf
+ len
, size
- len
, "Num of MSDUs with UDP L4: %llu\n",
345 rx_stats
->udp_msdu_count
);
346 len
+= scnprintf(buf
+ len
, size
- len
, "Num of MSDUs part of AMPDU: %llu\n",
347 rx_stats
->ampdu_msdu_count
);
348 len
+= scnprintf(buf
+ len
, size
- len
, "Num of MSDUs not part of AMPDU: %llu\n",
349 rx_stats
->non_ampdu_msdu_count
);
350 len
+= scnprintf(buf
+ len
, size
- len
, "Num of MSDUs using STBC: %llu\n",
351 rx_stats
->stbc_count
);
352 len
+= scnprintf(buf
+ len
, size
- len
, "Num of MSDUs beamformed: %llu\n",
353 rx_stats
->beamformed_count
);
354 len
+= scnprintf(buf
+ len
, size
- len
, "Num of MPDUs with FCS ok: %llu\n",
355 rx_stats
->num_mpdu_fcs_ok
);
356 len
+= scnprintf(buf
+ len
, size
- len
, "Num of MPDUs with FCS error: %llu\n",
357 rx_stats
->num_mpdu_fcs_err
);
358 len
+= scnprintf(buf
+ len
, size
- len
,
359 "GI: 0.8us %llu 0.4us %llu 1.6us %llu 3.2us %llu\n",
360 rx_stats
->gi_count
[0], rx_stats
->gi_count
[1],
361 rx_stats
->gi_count
[2], rx_stats
->gi_count
[3]);
362 len
+= scnprintf(buf
+ len
, size
- len
,
363 "BW: 20Mhz %llu 40Mhz %llu 80Mhz %llu 160Mhz %llu\n",
364 rx_stats
->bw_count
[0], rx_stats
->bw_count
[1],
365 rx_stats
->bw_count
[2], rx_stats
->bw_count
[3]);
366 len
+= scnprintf(buf
+ len
, size
- len
, "BCC %llu LDPC %llu\n",
367 rx_stats
->coding_count
[0], rx_stats
->coding_count
[1]);
368 len
+= scnprintf(buf
+ len
, size
- len
,
369 "preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu\n",
370 rx_stats
->pream_cnt
[0], rx_stats
->pream_cnt
[1],
371 rx_stats
->pream_cnt
[2], rx_stats
->pream_cnt
[3],
372 rx_stats
->pream_cnt
[4]);
373 len
+= scnprintf(buf
+ len
, size
- len
,
374 "reception type: SU %llu MU_MIMO %llu MU_OFDMA %llu MU_OFDMA_MIMO %llu\n",
375 rx_stats
->reception_type
[0], rx_stats
->reception_type
[1],
376 rx_stats
->reception_type
[2], rx_stats
->reception_type
[3]);
377 len
+= scnprintf(buf
+ len
, size
- len
, "TID(0-15) Legacy TID(16):");
378 for (i
= 0; i
<= IEEE80211_NUM_TIDS
; i
++)
379 len
+= scnprintf(buf
+ len
, size
- len
, "%llu ", rx_stats
->tid_count
[i
]);
380 len
+= scnprintf(buf
+ len
, size
- len
, "\nMCS(0-11) Legacy MCS(12):");
381 for (i
= 0; i
< HAL_RX_MAX_MCS
+ 1; i
++)
382 len
+= scnprintf(buf
+ len
, size
- len
, "%llu ", rx_stats
->mcs_count
[i
]);
383 len
+= scnprintf(buf
+ len
, size
- len
, "\nNSS(1-8):");
384 for (i
= 0; i
< HAL_RX_MAX_NSS
; i
++)
385 len
+= scnprintf(buf
+ len
, size
- len
, "%llu ", rx_stats
->nss_count
[i
]);
386 len
+= scnprintf(buf
+ len
, size
- len
, "\nRX Duration:%llu ",
387 rx_stats
->rx_duration
);
388 len
+= scnprintf(buf
+ len
, size
- len
,
389 "\nDCM: %llu\nRU: 26 %llu 52: %llu 106: %llu 242: %llu 484: %llu 996: %llu\n",
390 rx_stats
->dcm_count
, rx_stats
->ru_alloc_cnt
[0],
391 rx_stats
->ru_alloc_cnt
[1], rx_stats
->ru_alloc_cnt
[2],
392 rx_stats
->ru_alloc_cnt
[3], rx_stats
->ru_alloc_cnt
[4],
393 rx_stats
->ru_alloc_cnt
[5]);
395 len
+= scnprintf(buf
+ len
, size
- len
, "\n");
397 spin_unlock_bh(&ar
->ab
->base_lock
);
401 retval
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
404 mutex_unlock(&ar
->conf_mutex
);
408 static const struct file_operations fops_rx_stats
= {
409 .read
= ath11k_dbg_sta_dump_rx_stats
,
411 .owner
= THIS_MODULE
,
412 .llseek
= default_llseek
,
416 ath11k_dbg_sta_open_htt_peer_stats(struct inode
*inode
, struct file
*file
)
418 struct ieee80211_sta
*sta
= inode
->i_private
;
419 struct ath11k_sta
*arsta
= (struct ath11k_sta
*)sta
->drv_priv
;
420 struct ath11k
*ar
= arsta
->arvif
->ar
;
421 struct debug_htt_stats_req
*stats_req
;
424 stats_req
= vzalloc(sizeof(*stats_req
) + ATH11K_HTT_STATS_BUF_SIZE
);
428 mutex_lock(&ar
->conf_mutex
);
429 ar
->debug
.htt_stats
.stats_req
= stats_req
;
430 stats_req
->type
= ATH11K_DBG_HTT_EXT_STATS_PEER_INFO
;
431 memcpy(stats_req
->peer_addr
, sta
->addr
, ETH_ALEN
);
432 ret
= ath11k_debugfs_htt_stats_req(ar
);
433 mutex_unlock(&ar
->conf_mutex
);
437 file
->private_data
= stats_req
;
441 ar
->debug
.htt_stats
.stats_req
= NULL
;
446 ath11k_dbg_sta_release_htt_peer_stats(struct inode
*inode
, struct file
*file
)
448 struct ieee80211_sta
*sta
= inode
->i_private
;
449 struct ath11k_sta
*arsta
= (struct ath11k_sta
*)sta
->drv_priv
;
450 struct ath11k
*ar
= arsta
->arvif
->ar
;
452 mutex_lock(&ar
->conf_mutex
);
453 vfree(file
->private_data
);
454 ar
->debug
.htt_stats
.stats_req
= NULL
;
455 mutex_unlock(&ar
->conf_mutex
);
460 static ssize_t
ath11k_dbg_sta_read_htt_peer_stats(struct file
*file
,
461 char __user
*user_buf
,
462 size_t count
, loff_t
*ppos
)
464 struct debug_htt_stats_req
*stats_req
= file
->private_data
;
468 buf
= stats_req
->buf
;
469 length
= min_t(u32
, stats_req
->buf_len
, ATH11K_HTT_STATS_BUF_SIZE
);
470 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, length
);
473 static const struct file_operations fops_htt_peer_stats
= {
474 .open
= ath11k_dbg_sta_open_htt_peer_stats
,
475 .release
= ath11k_dbg_sta_release_htt_peer_stats
,
476 .read
= ath11k_dbg_sta_read_htt_peer_stats
,
477 .owner
= THIS_MODULE
,
478 .llseek
= default_llseek
,
481 static ssize_t
ath11k_dbg_sta_write_peer_pktlog(struct file
*file
,
482 const char __user
*buf
,
483 size_t count
, loff_t
*ppos
)
485 struct ieee80211_sta
*sta
= file
->private_data
;
486 struct ath11k_sta
*arsta
= (struct ath11k_sta
*)sta
->drv_priv
;
487 struct ath11k
*ar
= arsta
->arvif
->ar
;
490 mutex_lock(&ar
->conf_mutex
);
492 if (ar
->state
!= ATH11K_STATE_ON
) {
497 ret
= kstrtoint_from_user(buf
, count
, 0, &enable
);
501 ar
->debug
.pktlog_peer_valid
= enable
;
502 memcpy(ar
->debug
.pktlog_peer_addr
, sta
->addr
, ETH_ALEN
);
504 /* Send peer based pktlog enable/disable */
505 ret
= ath11k_wmi_pdev_peer_pktlog_filter(ar
, sta
->addr
, enable
);
507 ath11k_warn(ar
->ab
, "failed to set peer pktlog filter %pM: %d\n",
512 ath11k_dbg(ar
->ab
, ATH11K_DBG_WMI
, "peer pktlog filter set to %d\n",
517 mutex_unlock(&ar
->conf_mutex
);
521 static ssize_t
ath11k_dbg_sta_read_peer_pktlog(struct file
*file
,
523 size_t count
, loff_t
*ppos
)
525 struct ieee80211_sta
*sta
= file
->private_data
;
526 struct ath11k_sta
*arsta
= (struct ath11k_sta
*)sta
->drv_priv
;
527 struct ath11k
*ar
= arsta
->arvif
->ar
;
531 mutex_lock(&ar
->conf_mutex
);
532 len
= scnprintf(buf
, sizeof(buf
), "%08x %pM\n",
533 ar
->debug
.pktlog_peer_valid
,
534 ar
->debug
.pktlog_peer_addr
);
535 mutex_unlock(&ar
->conf_mutex
);
537 return simple_read_from_buffer(ubuf
, count
, ppos
, buf
, len
);
540 static const struct file_operations fops_peer_pktlog
= {
541 .write
= ath11k_dbg_sta_write_peer_pktlog
,
542 .read
= ath11k_dbg_sta_read_peer_pktlog
,
544 .owner
= THIS_MODULE
,
545 .llseek
= default_llseek
,
548 static ssize_t
ath11k_dbg_sta_write_delba(struct file
*file
,
549 const char __user
*user_buf
,
550 size_t count
, loff_t
*ppos
)
552 struct ieee80211_sta
*sta
= file
->private_data
;
553 struct ath11k_sta
*arsta
= (struct ath11k_sta
*)sta
->drv_priv
;
554 struct ath11k
*ar
= arsta
->arvif
->ar
;
555 u32 tid
, initiator
, reason
;
559 ret
= simple_write_to_buffer(buf
, sizeof(buf
) - 1, ppos
,
564 ret
= sscanf(buf
, "%u %u %u", &tid
, &initiator
, &reason
);
568 /* Valid TID values are 0 through 15 */
569 if (tid
> HAL_DESC_REO_NON_QOS_TID
- 1)
572 mutex_lock(&ar
->conf_mutex
);
573 if (ar
->state
!= ATH11K_STATE_ON
||
574 arsta
->aggr_mode
!= ATH11K_DBG_AGGR_MODE_MANUAL
) {
579 ret
= ath11k_wmi_delba_send(ar
, arsta
->arvif
->vdev_id
, sta
->addr
,
580 tid
, initiator
, reason
);
582 ath11k_warn(ar
->ab
, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
583 arsta
->arvif
->vdev_id
, sta
->addr
, tid
, initiator
,
588 mutex_unlock(&ar
->conf_mutex
);
592 static const struct file_operations fops_delba
= {
593 .write
= ath11k_dbg_sta_write_delba
,
595 .owner
= THIS_MODULE
,
596 .llseek
= default_llseek
,
599 static ssize_t
ath11k_dbg_sta_write_addba_resp(struct file
*file
,
600 const char __user
*user_buf
,
601 size_t count
, loff_t
*ppos
)
603 struct ieee80211_sta
*sta
= file
->private_data
;
604 struct ath11k_sta
*arsta
= (struct ath11k_sta
*)sta
->drv_priv
;
605 struct ath11k
*ar
= arsta
->arvif
->ar
;
610 ret
= simple_write_to_buffer(buf
, sizeof(buf
) - 1, ppos
,
615 ret
= sscanf(buf
, "%u %u", &tid
, &status
);
619 /* Valid TID values are 0 through 15 */
620 if (tid
> HAL_DESC_REO_NON_QOS_TID
- 1)
623 mutex_lock(&ar
->conf_mutex
);
624 if (ar
->state
!= ATH11K_STATE_ON
||
625 arsta
->aggr_mode
!= ATH11K_DBG_AGGR_MODE_MANUAL
) {
630 ret
= ath11k_wmi_addba_set_resp(ar
, arsta
->arvif
->vdev_id
, sta
->addr
,
633 ath11k_warn(ar
->ab
, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
634 arsta
->arvif
->vdev_id
, sta
->addr
, tid
, status
);
638 mutex_unlock(&ar
->conf_mutex
);
642 static const struct file_operations fops_addba_resp
= {
643 .write
= ath11k_dbg_sta_write_addba_resp
,
645 .owner
= THIS_MODULE
,
646 .llseek
= default_llseek
,
649 static ssize_t
ath11k_dbg_sta_write_addba(struct file
*file
,
650 const char __user
*user_buf
,
651 size_t count
, loff_t
*ppos
)
653 struct ieee80211_sta
*sta
= file
->private_data
;
654 struct ath11k_sta
*arsta
= (struct ath11k_sta
*)sta
->drv_priv
;
655 struct ath11k
*ar
= arsta
->arvif
->ar
;
660 ret
= simple_write_to_buffer(buf
, sizeof(buf
) - 1, ppos
,
665 ret
= sscanf(buf
, "%u %u", &tid
, &buf_size
);
669 /* Valid TID values are 0 through 15 */
670 if (tid
> HAL_DESC_REO_NON_QOS_TID
- 1)
673 mutex_lock(&ar
->conf_mutex
);
674 if (ar
->state
!= ATH11K_STATE_ON
||
675 arsta
->aggr_mode
!= ATH11K_DBG_AGGR_MODE_MANUAL
) {
680 ret
= ath11k_wmi_addba_send(ar
, arsta
->arvif
->vdev_id
, sta
->addr
,
683 ath11k_warn(ar
->ab
, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
684 arsta
->arvif
->vdev_id
, sta
->addr
, tid
, buf_size
);
689 mutex_unlock(&ar
->conf_mutex
);
693 static const struct file_operations fops_addba
= {
694 .write
= ath11k_dbg_sta_write_addba
,
696 .owner
= THIS_MODULE
,
697 .llseek
= default_llseek
,
700 static ssize_t
ath11k_dbg_sta_read_aggr_mode(struct file
*file
,
701 char __user
*user_buf
,
702 size_t count
, loff_t
*ppos
)
704 struct ieee80211_sta
*sta
= file
->private_data
;
705 struct ath11k_sta
*arsta
= (struct ath11k_sta
*)sta
->drv_priv
;
706 struct ath11k
*ar
= arsta
->arvif
->ar
;
710 mutex_lock(&ar
->conf_mutex
);
711 len
= scnprintf(buf
, sizeof(buf
) - len
,
712 "aggregation mode: %s\n\n%s\n%s\n",
713 (arsta
->aggr_mode
== ATH11K_DBG_AGGR_MODE_AUTO
) ?
714 "auto" : "manual", "auto = 0", "manual = 1");
715 mutex_unlock(&ar
->conf_mutex
);
717 return simple_read_from_buffer(user_buf
, count
, ppos
, buf
, len
);
720 static ssize_t
ath11k_dbg_sta_write_aggr_mode(struct file
*file
,
721 const char __user
*user_buf
,
722 size_t count
, loff_t
*ppos
)
724 struct ieee80211_sta
*sta
= file
->private_data
;
725 struct ath11k_sta
*arsta
= (struct ath11k_sta
*)sta
->drv_priv
;
726 struct ath11k
*ar
= arsta
->arvif
->ar
;
730 if (kstrtouint_from_user(user_buf
, count
, 0, &aggr_mode
))
733 if (aggr_mode
>= ATH11K_DBG_AGGR_MODE_MAX
)
736 mutex_lock(&ar
->conf_mutex
);
737 if (ar
->state
!= ATH11K_STATE_ON
||
738 aggr_mode
== arsta
->aggr_mode
) {
743 ret
= ath11k_wmi_addba_clear_resp(ar
, arsta
->arvif
->vdev_id
, sta
->addr
);
745 ath11k_warn(ar
->ab
, "failed to clear addba session ret: %d\n",
750 arsta
->aggr_mode
= aggr_mode
;
752 mutex_unlock(&ar
->conf_mutex
);
756 static const struct file_operations fops_aggr_mode
= {
757 .read
= ath11k_dbg_sta_read_aggr_mode
,
758 .write
= ath11k_dbg_sta_write_aggr_mode
,
760 .owner
= THIS_MODULE
,
761 .llseek
= default_llseek
,
765 ath11k_write_htt_peer_stats_reset(struct file
*file
,
766 const char __user
*user_buf
,
767 size_t count
, loff_t
*ppos
)
769 struct ieee80211_sta
*sta
= file
->private_data
;
770 struct ath11k_sta
*arsta
= (struct ath11k_sta
*)sta
->drv_priv
;
771 struct ath11k
*ar
= arsta
->arvif
->ar
;
772 struct htt_ext_stats_cfg_params cfg_params
= { 0 };
776 ret
= kstrtou8_from_user(user_buf
, count
, 0, &type
);
783 mutex_lock(&ar
->conf_mutex
);
784 cfg_params
.cfg0
= HTT_STAT_PEER_INFO_MAC_ADDR
;
785 cfg_params
.cfg0
|= FIELD_PREP(GENMASK(15, 1),
786 HTT_PEER_STATS_REQ_MODE_FLUSH_TQM
);
788 cfg_params
.cfg1
= HTT_STAT_DEFAULT_PEER_REQ_TYPE
;
790 cfg_params
.cfg2
|= FIELD_PREP(GENMASK(7, 0), sta
->addr
[0]);
791 cfg_params
.cfg2
|= FIELD_PREP(GENMASK(15, 8), sta
->addr
[1]);
792 cfg_params
.cfg2
|= FIELD_PREP(GENMASK(23, 16), sta
->addr
[2]);
793 cfg_params
.cfg2
|= FIELD_PREP(GENMASK(31, 24), sta
->addr
[3]);
795 cfg_params
.cfg3
|= FIELD_PREP(GENMASK(7, 0), sta
->addr
[4]);
796 cfg_params
.cfg3
|= FIELD_PREP(GENMASK(15, 8), sta
->addr
[5]);
798 cfg_params
.cfg3
|= ATH11K_HTT_PEER_STATS_RESET
;
800 ret
= ath11k_dp_tx_htt_h2t_ext_stats_req(ar
,
801 ATH11K_DBG_HTT_EXT_STATS_PEER_INFO
,
805 ath11k_warn(ar
->ab
, "failed to send htt peer stats request: %d\n", ret
);
806 mutex_unlock(&ar
->conf_mutex
);
810 mutex_unlock(&ar
->conf_mutex
);
817 static const struct file_operations fops_htt_peer_stats_reset
= {
818 .write
= ath11k_write_htt_peer_stats_reset
,
820 .owner
= THIS_MODULE
,
821 .llseek
= default_llseek
,
824 void ath11k_debugfs_sta_op_add(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
825 struct ieee80211_sta
*sta
, struct dentry
*dir
)
827 struct ath11k
*ar
= hw
->priv
;
829 if (ath11k_debugfs_is_extd_tx_stats_enabled(ar
))
830 debugfs_create_file("tx_stats", 0400, dir
, sta
,
832 if (ath11k_debugfs_is_extd_rx_stats_enabled(ar
))
833 debugfs_create_file("rx_stats", 0400, dir
, sta
,
836 debugfs_create_file("htt_peer_stats", 0400, dir
, sta
,
837 &fops_htt_peer_stats
);
839 debugfs_create_file("peer_pktlog", 0644, dir
, sta
,
842 debugfs_create_file("aggr_mode", 0644, dir
, sta
, &fops_aggr_mode
);
843 debugfs_create_file("addba", 0200, dir
, sta
, &fops_addba
);
844 debugfs_create_file("addba_resp", 0200, dir
, sta
, &fops_addba_resp
);
845 debugfs_create_file("delba", 0200, dir
, sta
, &fops_delba
);
847 if (test_bit(WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET
,
848 ar
->ab
->wmi_ab
.svc_map
))
849 debugfs_create_file("htt_peer_stats_reset", 0600, dir
, sta
,
850 &fops_htt_peer_stats_reset
);