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