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