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
15void 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
128void 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
134static 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
234static 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
241static 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
332static 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
339static int
340ath11k_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;
369out:
370	vfree(stats_req);
371	ar->debug.htt_stats.stats_req = NULL;
372	return ret;
373}
374
375static int
376ath11k_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
390static 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
403static 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
411static 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
446out:
447	mutex_unlock(&ar->conf_mutex);
448	return ret;
449}
450
451static 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
470static 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
478static 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;
517out:
518	mutex_unlock(&ar->conf_mutex);
519	return ret;
520}
521
522static 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
529static 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;
567out:
568	mutex_unlock(&ar->conf_mutex);
569	return ret;
570}
571
572static 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
579static 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;
618out:
619	mutex_unlock(&ar->conf_mutex);
620	return ret;
621}
622
623static 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
630static 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
650static 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;
681out:
682	mutex_unlock(&ar->conf_mutex);
683	return ret;
684}
685
686static 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
694static ssize_t
695ath11k_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
747static 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
754static ssize_t ath11k_dbg_sta_read_peer_ps_state(struct file *file,
755						 char __user *user_buf,
756						 size_t count, loff_t *ppos)
757{
758	struct ieee80211_sta *sta = file->private_data;
759	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
760	struct ath11k *ar = arsta->arvif->ar;
761	char buf[20];
762	int len;
763
764	spin_lock_bh(&ar->data_lock);
765
766	len = scnprintf(buf, sizeof(buf), "%d\n", arsta->peer_ps_state);
767
768	spin_unlock_bh(&ar->data_lock);
769
770	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
771}
772
773static const struct file_operations fops_peer_ps_state = {
774	.open = simple_open,
775	.read = ath11k_dbg_sta_read_peer_ps_state,
776	.owner = THIS_MODULE,
777	.llseek = default_llseek,
778};
779
780static ssize_t ath11k_dbg_sta_read_current_ps_duration(struct file *file,
781						       char __user *user_buf,
782						       size_t count,
783						       loff_t *ppos)
784{
785	struct ieee80211_sta *sta = file->private_data;
786	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
787	struct ath11k *ar = arsta->arvif->ar;
788	u64 time_since_station_in_power_save;
789	char buf[20];
790	int len;
791
792	spin_lock_bh(&ar->data_lock);
793
794	if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON &&
795	    arsta->peer_current_ps_valid)
796		time_since_station_in_power_save = jiffies_to_msecs(jiffies
797						- arsta->ps_start_jiffies);
798	else
799		time_since_station_in_power_save = 0;
800
801	len = scnprintf(buf, sizeof(buf), "%llu\n",
802			time_since_station_in_power_save);
803	spin_unlock_bh(&ar->data_lock);
804
805	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
806}
807
808static const struct file_operations fops_current_ps_duration = {
809	.open = simple_open,
810	.read = ath11k_dbg_sta_read_current_ps_duration,
811	.owner = THIS_MODULE,
812	.llseek = default_llseek,
813};
814
815static ssize_t ath11k_dbg_sta_read_total_ps_duration(struct file *file,
816						     char __user *user_buf,
817						     size_t count, loff_t *ppos)
818{
819	struct ieee80211_sta *sta = file->private_data;
820	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
821	struct ath11k *ar = arsta->arvif->ar;
822	char buf[20];
823	u64 power_save_duration;
824	int len;
825
826	spin_lock_bh(&ar->data_lock);
827
828	if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON &&
829	    arsta->peer_current_ps_valid)
830		power_save_duration = jiffies_to_msecs(jiffies
831						- arsta->ps_start_jiffies)
832						+ arsta->ps_total_duration;
833	else
834		power_save_duration = arsta->ps_total_duration;
835
836	len = scnprintf(buf, sizeof(buf), "%llu\n", power_save_duration);
837
838	spin_unlock_bh(&ar->data_lock);
839
840	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
841}
842
843static const struct file_operations fops_total_ps_duration = {
844	.open = simple_open,
845	.read = ath11k_dbg_sta_read_total_ps_duration,
846	.owner = THIS_MODULE,
847	.llseek = default_llseek,
848};
849
850void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
851			       struct ieee80211_sta *sta, struct dentry *dir)
852{
853	struct ath11k *ar = hw->priv;
854
855	if (ath11k_debugfs_is_extd_tx_stats_enabled(ar))
856		debugfs_create_file("tx_stats", 0400, dir, sta,
857				    &fops_tx_stats);
858	if (ath11k_debugfs_is_extd_rx_stats_enabled(ar))
859		debugfs_create_file("rx_stats", 0400, dir, sta,
860				    &fops_rx_stats);
861
862	debugfs_create_file("htt_peer_stats", 0400, dir, sta,
863			    &fops_htt_peer_stats);
864
865	debugfs_create_file("peer_pktlog", 0644, dir, sta,
866			    &fops_peer_pktlog);
867
868	debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
869	debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
870	debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
871	debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
872
873	if (test_bit(WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET,
874		     ar->ab->wmi_ab.svc_map))
875		debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta,
876				    &fops_htt_peer_stats_reset);
877
878	debugfs_create_file("peer_ps_state", 0400, dir, sta,
879			    &fops_peer_ps_state);
880
881	if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,
882		     ar->ab->wmi_ab.svc_map)) {
883		debugfs_create_file("current_ps_duration", 0440, dir, sta,
884				    &fops_current_ps_duration);
885		debugfs_create_file("total_ps_duration", 0440, dir, sta,
886				    &fops_total_ps_duration);
887	}
888}
889