1d5c65159SKalle Valo // SPDX-License-Identifier: BSD-3-Clause-Clear
2d5c65159SKalle Valo /*
3d5c65159SKalle Valo  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4d5c65159SKalle Valo  */
5d5c65159SKalle Valo 
6d5c65159SKalle Valo #include <linux/vmalloc.h>
7d5c65159SKalle Valo 
8568f0603SKalle Valo #include "debugfs_sta.h"
9d5c65159SKalle Valo #include "core.h"
10d5c65159SKalle Valo #include "peer.h"
11d5c65159SKalle Valo #include "debug.h"
12559ef68fSAshok Raj Nagarajan #include "dp_tx.h"
1356292162SKalle Valo #include "debugfs_htt_stats.h"
14d5c65159SKalle Valo 
ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta * arsta,struct ath11k_per_peer_tx_stats * peer_stats,u8 legacy_rate_idx)15568f0603SKalle Valo void ath11k_debugfs_sta_add_tx_stats(struct ath11k_sta *arsta,
16d5c65159SKalle Valo 				     struct ath11k_per_peer_tx_stats *peer_stats,
17d5c65159SKalle Valo 				     u8 legacy_rate_idx)
18d5c65159SKalle Valo {
19d5c65159SKalle Valo 	struct rate_info *txrate = &arsta->txrate;
20d5c65159SKalle Valo 	struct ath11k_htt_tx_stats *tx_stats;
21d5c65159SKalle Valo 	int gi, mcs, bw, nss;
22d5c65159SKalle Valo 
23d5c65159SKalle Valo 	if (!arsta->tx_stats)
24d5c65159SKalle Valo 		return;
25d5c65159SKalle Valo 
26d5c65159SKalle Valo 	tx_stats = arsta->tx_stats;
27d5c65159SKalle Valo 	gi = FIELD_GET(RATE_INFO_FLAGS_SHORT_GI, arsta->txrate.flags);
28d5c65159SKalle Valo 	mcs = txrate->mcs;
2992bacd1cSVenkateswara Naralasetty 	bw = ath11k_mac_mac80211_bw_to_ath11k_bw(txrate->bw);
30d5c65159SKalle Valo 	nss = txrate->nss - 1;
31d5c65159SKalle Valo 
32d5c65159SKalle Valo #define STATS_OP_FMT(name) tx_stats->stats[ATH11K_STATS_TYPE_##name]
33d5c65159SKalle Valo 
34d5c65159SKalle Valo 	if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) {
35d5c65159SKalle Valo 		STATS_OP_FMT(SUCC).he[0][mcs] += peer_stats->succ_bytes;
36d5c65159SKalle Valo 		STATS_OP_FMT(SUCC).he[1][mcs] += peer_stats->succ_pkts;
37d5c65159SKalle Valo 		STATS_OP_FMT(FAIL).he[0][mcs] += peer_stats->failed_bytes;
38d5c65159SKalle Valo 		STATS_OP_FMT(FAIL).he[1][mcs] += peer_stats->failed_pkts;
39d5c65159SKalle Valo 		STATS_OP_FMT(RETRY).he[0][mcs] += peer_stats->retry_bytes;
40d5c65159SKalle Valo 		STATS_OP_FMT(RETRY).he[1][mcs] += peer_stats->retry_pkts;
41d5c65159SKalle Valo 	} else if (txrate->flags & RATE_INFO_FLAGS_VHT_MCS) {
42d5c65159SKalle Valo 		STATS_OP_FMT(SUCC).vht[0][mcs] += peer_stats->succ_bytes;
43d5c65159SKalle Valo 		STATS_OP_FMT(SUCC).vht[1][mcs] += peer_stats->succ_pkts;
44d5c65159SKalle Valo 		STATS_OP_FMT(FAIL).vht[0][mcs] += peer_stats->failed_bytes;
45d5c65159SKalle Valo 		STATS_OP_FMT(FAIL).vht[1][mcs] += peer_stats->failed_pkts;
46d5c65159SKalle Valo 		STATS_OP_FMT(RETRY).vht[0][mcs] += peer_stats->retry_bytes;
47d5c65159SKalle Valo 		STATS_OP_FMT(RETRY).vht[1][mcs] += peer_stats->retry_pkts;
48d5c65159SKalle Valo 	} else if (txrate->flags & RATE_INFO_FLAGS_MCS) {
49d5c65159SKalle Valo 		STATS_OP_FMT(SUCC).ht[0][mcs] += peer_stats->succ_bytes;
50d5c65159SKalle Valo 		STATS_OP_FMT(SUCC).ht[1][mcs] += peer_stats->succ_pkts;
51d5c65159SKalle Valo 		STATS_OP_FMT(FAIL).ht[0][mcs] += peer_stats->failed_bytes;
52d5c65159SKalle Valo 		STATS_OP_FMT(FAIL).ht[1][mcs] += peer_stats->failed_pkts;
53d5c65159SKalle Valo 		STATS_OP_FMT(RETRY).ht[0][mcs] += peer_stats->retry_bytes;
54d5c65159SKalle Valo 		STATS_OP_FMT(RETRY).ht[1][mcs] += peer_stats->retry_pkts;
55d5c65159SKalle Valo 	} else {
56d5c65159SKalle Valo 		mcs = legacy_rate_idx;
57d5c65159SKalle Valo 
58d5c65159SKalle Valo 		STATS_OP_FMT(SUCC).legacy[0][mcs] += peer_stats->succ_bytes;
59d5c65159SKalle Valo 		STATS_OP_FMT(SUCC).legacy[1][mcs] += peer_stats->succ_pkts;
60d5c65159SKalle Valo 		STATS_OP_FMT(FAIL).legacy[0][mcs] += peer_stats->failed_bytes;
61d5c65159SKalle Valo 		STATS_OP_FMT(FAIL).legacy[1][mcs] += peer_stats->failed_pkts;
62d5c65159SKalle Valo 		STATS_OP_FMT(RETRY).legacy[0][mcs] += peer_stats->retry_bytes;
63d5c65159SKalle Valo 		STATS_OP_FMT(RETRY).legacy[1][mcs] += peer_stats->retry_pkts;
64d5c65159SKalle Valo 	}
65d5c65159SKalle Valo 
66d5c65159SKalle Valo 	if (peer_stats->is_ampdu) {
67d5c65159SKalle Valo 		tx_stats->ba_fails += peer_stats->ba_fails;
68d5c65159SKalle Valo 
69d5c65159SKalle Valo 		if (txrate->flags & RATE_INFO_FLAGS_HE_MCS) {
70d5c65159SKalle Valo 			STATS_OP_FMT(AMPDU).he[0][mcs] +=
71d5c65159SKalle Valo 			peer_stats->succ_bytes + peer_stats->retry_bytes;
72d5c65159SKalle Valo 			STATS_OP_FMT(AMPDU).he[1][mcs] +=
73d5c65159SKalle Valo 			peer_stats->succ_pkts + peer_stats->retry_pkts;
74d5c65159SKalle Valo 		} else if (txrate->flags & RATE_INFO_FLAGS_MCS) {
75d5c65159SKalle Valo 			STATS_OP_FMT(AMPDU).ht[0][mcs] +=
76d5c65159SKalle Valo 			peer_stats->succ_bytes + peer_stats->retry_bytes;
77d5c65159SKalle Valo 			STATS_OP_FMT(AMPDU).ht[1][mcs] +=
78d5c65159SKalle Valo 			peer_stats->succ_pkts + peer_stats->retry_pkts;
79d5c65159SKalle Valo 		} else {
80d5c65159SKalle Valo 			STATS_OP_FMT(AMPDU).vht[0][mcs] +=
81d5c65159SKalle Valo 			peer_stats->succ_bytes + peer_stats->retry_bytes;
82d5c65159SKalle Valo 			STATS_OP_FMT(AMPDU).vht[1][mcs] +=
83d5c65159SKalle Valo 			peer_stats->succ_pkts + peer_stats->retry_pkts;
84d5c65159SKalle Valo 		}
85d5c65159SKalle Valo 		STATS_OP_FMT(AMPDU).bw[0][bw] +=
86d5c65159SKalle Valo 			peer_stats->succ_bytes + peer_stats->retry_bytes;
87d5c65159SKalle Valo 		STATS_OP_FMT(AMPDU).nss[0][nss] +=
88d5c65159SKalle Valo 			peer_stats->succ_bytes + peer_stats->retry_bytes;
89d5c65159SKalle Valo 		STATS_OP_FMT(AMPDU).gi[0][gi] +=
90d5c65159SKalle Valo 			peer_stats->succ_bytes + peer_stats->retry_bytes;
91d5c65159SKalle Valo 		STATS_OP_FMT(AMPDU).bw[1][bw] +=
92d5c65159SKalle Valo 			peer_stats->succ_pkts + peer_stats->retry_pkts;
93d5c65159SKalle Valo 		STATS_OP_FMT(AMPDU).nss[1][nss] +=
94d5c65159SKalle Valo 			peer_stats->succ_pkts + peer_stats->retry_pkts;
95d5c65159SKalle Valo 		STATS_OP_FMT(AMPDU).gi[1][gi] +=
96d5c65159SKalle Valo 			peer_stats->succ_pkts + peer_stats->retry_pkts;
97d5c65159SKalle Valo 	} else {
98d5c65159SKalle Valo 		tx_stats->ack_fails += peer_stats->ba_fails;
99d5c65159SKalle Valo 	}
100d5c65159SKalle Valo 
101d5c65159SKalle Valo 	STATS_OP_FMT(SUCC).bw[0][bw] += peer_stats->succ_bytes;
102d5c65159SKalle Valo 	STATS_OP_FMT(SUCC).nss[0][nss] += peer_stats->succ_bytes;
103d5c65159SKalle Valo 	STATS_OP_FMT(SUCC).gi[0][gi] += peer_stats->succ_bytes;
104d5c65159SKalle Valo 
105d5c65159SKalle Valo 	STATS_OP_FMT(SUCC).bw[1][bw] += peer_stats->succ_pkts;
106d5c65159SKalle Valo 	STATS_OP_FMT(SUCC).nss[1][nss] += peer_stats->succ_pkts;
107d5c65159SKalle Valo 	STATS_OP_FMT(SUCC).gi[1][gi] += peer_stats->succ_pkts;
108d5c65159SKalle Valo 
109d5c65159SKalle Valo 	STATS_OP_FMT(FAIL).bw[0][bw] += peer_stats->failed_bytes;
110d5c65159SKalle Valo 	STATS_OP_FMT(FAIL).nss[0][nss] += peer_stats->failed_bytes;
111d5c65159SKalle Valo 	STATS_OP_FMT(FAIL).gi[0][gi] += peer_stats->failed_bytes;
112d5c65159SKalle Valo 
113d5c65159SKalle Valo 	STATS_OP_FMT(FAIL).bw[1][bw] += peer_stats->failed_pkts;
114d5c65159SKalle Valo 	STATS_OP_FMT(FAIL).nss[1][nss] += peer_stats->failed_pkts;
115d5c65159SKalle Valo 	STATS_OP_FMT(FAIL).gi[1][gi] += peer_stats->failed_pkts;
116d5c65159SKalle Valo 
117d5c65159SKalle Valo 	STATS_OP_FMT(RETRY).bw[0][bw] += peer_stats->retry_bytes;
118d5c65159SKalle Valo 	STATS_OP_FMT(RETRY).nss[0][nss] += peer_stats->retry_bytes;
119d5c65159SKalle Valo 	STATS_OP_FMT(RETRY).gi[0][gi] += peer_stats->retry_bytes;
120d5c65159SKalle Valo 
121d5c65159SKalle Valo 	STATS_OP_FMT(RETRY).bw[1][bw] += peer_stats->retry_pkts;
122d5c65159SKalle Valo 	STATS_OP_FMT(RETRY).nss[1][nss] += peer_stats->retry_pkts;
123d5c65159SKalle Valo 	STATS_OP_FMT(RETRY).gi[1][gi] += peer_stats->retry_pkts;
124d5c65159SKalle Valo 
125d5c65159SKalle Valo 	tx_stats->tx_duration += peer_stats->duration;
126d5c65159SKalle Valo }
127d5c65159SKalle Valo 
ath11k_debugfs_sta_update_txcompl(struct ath11k * ar,struct hal_tx_status * ts)128568f0603SKalle Valo void ath11k_debugfs_sta_update_txcompl(struct ath11k *ar,
129d5c65159SKalle Valo 				       struct hal_tx_status *ts)
130d5c65159SKalle Valo {
1311b8bb94cSWen Gong 	ath11k_dp_tx_update_txcompl(ar, ts);
132d5c65159SKalle Valo }
133d5c65159SKalle Valo 
ath11k_dbg_sta_dump_tx_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)134d5c65159SKalle Valo static ssize_t ath11k_dbg_sta_dump_tx_stats(struct file *file,
135d5c65159SKalle Valo 					    char __user *user_buf,
136d5c65159SKalle Valo 					    size_t count, loff_t *ppos)
137d5c65159SKalle Valo {
138d5c65159SKalle Valo 	struct ieee80211_sta *sta = file->private_data;
139d5c65159SKalle Valo 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
140d5c65159SKalle Valo 	struct ath11k *ar = arsta->arvif->ar;
141d5c65159SKalle Valo 	struct ath11k_htt_data_stats *stats;
142d5c65159SKalle Valo 	static const char *str_name[ATH11K_STATS_TYPE_MAX] = {"succ", "fail",
143d5c65159SKalle Valo 							      "retry", "ampdu"};
144d5c65159SKalle Valo 	static const char *str[ATH11K_COUNTER_TYPE_MAX] = {"bytes", "packets"};
145d5c65159SKalle Valo 	int len = 0, i, j, k, retval = 0;
146d5c65159SKalle Valo 	const int size = 2 * 4096;
147d5c65159SKalle Valo 	char *buf;
148d5c65159SKalle Valo 
149fe0ebb51SPravas Kumar Panda 	if (!arsta->tx_stats)
150fe0ebb51SPravas Kumar Panda 		return -ENOENT;
151fe0ebb51SPravas Kumar Panda 
152d5c65159SKalle Valo 	buf = kzalloc(size, GFP_KERNEL);
153d5c65159SKalle Valo 	if (!buf)
154d5c65159SKalle Valo 		return -ENOMEM;
155d5c65159SKalle Valo 
156d5c65159SKalle Valo 	mutex_lock(&ar->conf_mutex);
157d5c65159SKalle Valo 
158d5c65159SKalle Valo 	spin_lock_bh(&ar->data_lock);
159d5c65159SKalle Valo 	for (k = 0; k < ATH11K_STATS_TYPE_MAX; k++) {
160d5c65159SKalle Valo 		for (j = 0; j < ATH11K_COUNTER_TYPE_MAX; j++) {
161d5c65159SKalle Valo 			stats = &arsta->tx_stats->stats[k];
162d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len, "%s_%s\n",
163d5c65159SKalle Valo 					 str_name[k],
164d5c65159SKalle Valo 					 str[j]);
165d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len,
166d5c65159SKalle Valo 					 " HE MCS %s\n",
167d5c65159SKalle Valo 					 str[j]);
168d5c65159SKalle Valo 			for (i = 0; i < ATH11K_HE_MCS_NUM; i++)
169d5c65159SKalle Valo 				len += scnprintf(buf + len, size - len,
170d5c65159SKalle Valo 						 "  %llu ",
171d5c65159SKalle Valo 						 stats->he[j][i]);
172d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len, "\n");
173d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len,
174d5c65159SKalle Valo 					 " VHT MCS %s\n",
175d5c65159SKalle Valo 					 str[j]);
176d5c65159SKalle Valo 			for (i = 0; i < ATH11K_VHT_MCS_NUM; i++)
177d5c65159SKalle Valo 				len += scnprintf(buf + len, size - len,
178d5c65159SKalle Valo 						 "  %llu ",
179d5c65159SKalle Valo 						 stats->vht[j][i]);
180d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len, "\n");
181d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len, " HT MCS %s\n",
182d5c65159SKalle Valo 					 str[j]);
183d5c65159SKalle Valo 			for (i = 0; i < ATH11K_HT_MCS_NUM; i++)
184d5c65159SKalle Valo 				len += scnprintf(buf + len, size - len,
185d5c65159SKalle Valo 						 "  %llu ", stats->ht[j][i]);
186d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len, "\n");
187d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len,
188d5c65159SKalle Valo 					" BW %s (20,40,80,160 MHz)\n", str[j]);
189d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len,
190d5c65159SKalle Valo 					 "  %llu %llu %llu %llu\n",
191d5c65159SKalle Valo 					 stats->bw[j][0], stats->bw[j][1],
192d5c65159SKalle Valo 					 stats->bw[j][2], stats->bw[j][3]);
193d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len,
194d5c65159SKalle Valo 					 " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
195d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len,
196d5c65159SKalle Valo 					 "  %llu %llu %llu %llu\n",
197d5c65159SKalle Valo 					 stats->nss[j][0], stats->nss[j][1],
198d5c65159SKalle Valo 					 stats->nss[j][2], stats->nss[j][3]);
199d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len,
200d5c65159SKalle Valo 					 " GI %s (0.4us,0.8us,1.6us,3.2us)\n",
201d5c65159SKalle Valo 					 str[j]);
202d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len,
203d5c65159SKalle Valo 					 "  %llu %llu %llu %llu\n",
204d5c65159SKalle Valo 					 stats->gi[j][0], stats->gi[j][1],
205d5c65159SKalle Valo 					 stats->gi[j][2], stats->gi[j][3]);
206d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len,
207d5c65159SKalle Valo 					 " legacy rate %s (1,2 ... Mbps)\n  ",
208d5c65159SKalle Valo 					 str[j]);
209d5c65159SKalle Valo 			for (i = 0; i < ATH11K_LEGACY_NUM; i++)
210d5c65159SKalle Valo 				len += scnprintf(buf + len, size - len, "%llu ",
211d5c65159SKalle Valo 						 stats->legacy[j][i]);
212d5c65159SKalle Valo 			len += scnprintf(buf + len, size - len, "\n");
213d5c65159SKalle Valo 		}
214d5c65159SKalle Valo 	}
215d5c65159SKalle Valo 
216d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len,
217d5c65159SKalle Valo 			 "\nTX duration\n %llu usecs\n",
218d5c65159SKalle Valo 			 arsta->tx_stats->tx_duration);
219d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len,
220d5c65159SKalle Valo 			"BA fails\n %llu\n", arsta->tx_stats->ba_fails);
221d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len,
222d5c65159SKalle Valo 			"ack fails\n %llu\n", arsta->tx_stats->ack_fails);
223d5c65159SKalle Valo 	spin_unlock_bh(&ar->data_lock);
224d5c65159SKalle Valo 
225d5c65159SKalle Valo 	if (len > size)
226d5c65159SKalle Valo 		len = size;
227d5c65159SKalle Valo 	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
228d5c65159SKalle Valo 	kfree(buf);
229d5c65159SKalle Valo 
230d5c65159SKalle Valo 	mutex_unlock(&ar->conf_mutex);
231d5c65159SKalle Valo 	return retval;
232d5c65159SKalle Valo }
233d5c65159SKalle Valo 
234d5c65159SKalle Valo static const struct file_operations fops_tx_stats = {
235d5c65159SKalle Valo 	.read = ath11k_dbg_sta_dump_tx_stats,
236d5c65159SKalle Valo 	.open = simple_open,
237d5c65159SKalle Valo 	.owner = THIS_MODULE,
238d5c65159SKalle Valo 	.llseek = default_llseek,
239d5c65159SKalle Valo };
240d5c65159SKalle Valo 
ath11k_dbg_sta_dump_rx_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)241d5c65159SKalle Valo static ssize_t ath11k_dbg_sta_dump_rx_stats(struct file *file,
242d5c65159SKalle Valo 					    char __user *user_buf,
243d5c65159SKalle Valo 					    size_t count, loff_t *ppos)
244d5c65159SKalle Valo {
245d5c65159SKalle Valo 	struct ieee80211_sta *sta = file->private_data;
246d5c65159SKalle Valo 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
247d5c65159SKalle Valo 	struct ath11k *ar = arsta->arvif->ar;
248d5c65159SKalle Valo 	struct ath11k_rx_peer_stats *rx_stats = arsta->rx_stats;
249d5c65159SKalle Valo 	int len = 0, i, retval = 0;
250d5c65159SKalle Valo 	const int size = 4096;
251d5c65159SKalle Valo 	char *buf;
252d5c65159SKalle Valo 
253d5c65159SKalle Valo 	if (!rx_stats)
254d5c65159SKalle Valo 		return -ENOENT;
255d5c65159SKalle Valo 
256d5c65159SKalle Valo 	buf = kzalloc(size, GFP_KERNEL);
257d5c65159SKalle Valo 	if (!buf)
258d5c65159SKalle Valo 		return -ENOMEM;
259d5c65159SKalle Valo 
260d5c65159SKalle Valo 	mutex_lock(&ar->conf_mutex);
261d5c65159SKalle Valo 	spin_lock_bh(&ar->ab->base_lock);
262d5c65159SKalle Valo 
263d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "RX peer stats:\n");
264d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "Num of MSDUs: %llu\n",
265d5c65159SKalle Valo 			 rx_stats->num_msdu);
266d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "Num of MSDUs with TCP L4: %llu\n",
267d5c65159SKalle Valo 			 rx_stats->tcp_msdu_count);
268d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "Num of MSDUs with UDP L4: %llu\n",
269d5c65159SKalle Valo 			 rx_stats->udp_msdu_count);
270d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "Num of MSDUs part of AMPDU: %llu\n",
271d5c65159SKalle Valo 			 rx_stats->ampdu_msdu_count);
272d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "Num of MSDUs not part of AMPDU: %llu\n",
273d5c65159SKalle Valo 			 rx_stats->non_ampdu_msdu_count);
274d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "Num of MSDUs using STBC: %llu\n",
275d5c65159SKalle Valo 			 rx_stats->stbc_count);
276d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "Num of MSDUs beamformed: %llu\n",
277d5c65159SKalle Valo 			 rx_stats->beamformed_count);
278d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS ok: %llu\n",
279d5c65159SKalle Valo 			 rx_stats->num_mpdu_fcs_ok);
280d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "Num of MPDUs with FCS error: %llu\n",
281d5c65159SKalle Valo 			 rx_stats->num_mpdu_fcs_err);
282d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len,
283d5c65159SKalle Valo 			 "GI: 0.8us %llu 0.4us %llu 1.6us %llu 3.2us %llu\n",
284d5c65159SKalle Valo 			 rx_stats->gi_count[0], rx_stats->gi_count[1],
285d5c65159SKalle Valo 			 rx_stats->gi_count[2], rx_stats->gi_count[3]);
286d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len,
287d5c65159SKalle Valo 			 "BW: 20Mhz %llu 40Mhz %llu 80Mhz %llu 160Mhz %llu\n",
288d5c65159SKalle Valo 			 rx_stats->bw_count[0], rx_stats->bw_count[1],
289d5c65159SKalle Valo 			 rx_stats->bw_count[2], rx_stats->bw_count[3]);
290d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "BCC %llu LDPC %llu\n",
291d5c65159SKalle Valo 			 rx_stats->coding_count[0], rx_stats->coding_count[1]);
292d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len,
293d5c65159SKalle Valo 			 "preamble: 11A %llu 11B %llu 11N %llu 11AC %llu 11AX %llu\n",
294d5c65159SKalle Valo 			 rx_stats->pream_cnt[0], rx_stats->pream_cnt[1],
295d5c65159SKalle Valo 			 rx_stats->pream_cnt[2], rx_stats->pream_cnt[3],
296d5c65159SKalle Valo 			 rx_stats->pream_cnt[4]);
297d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len,
298d5c65159SKalle Valo 			 "reception type: SU %llu MU_MIMO %llu MU_OFDMA %llu MU_OFDMA_MIMO %llu\n",
299d5c65159SKalle Valo 			 rx_stats->reception_type[0], rx_stats->reception_type[1],
300d5c65159SKalle Valo 			 rx_stats->reception_type[2], rx_stats->reception_type[3]);
301d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "TID(0-15) Legacy TID(16):");
302d5c65159SKalle Valo 	for (i = 0; i <= IEEE80211_NUM_TIDS; i++)
303d5c65159SKalle Valo 		len += scnprintf(buf + len, size - len, "%llu ", rx_stats->tid_count[i]);
304d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "\nMCS(0-11) Legacy MCS(12):");
305d5c65159SKalle Valo 	for (i = 0; i < HAL_RX_MAX_MCS + 1; i++)
306d5c65159SKalle Valo 		len += scnprintf(buf + len, size - len, "%llu ", rx_stats->mcs_count[i]);
307d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "\nNSS(1-8):");
308d5c65159SKalle Valo 	for (i = 0; i < HAL_RX_MAX_NSS; i++)
309d5c65159SKalle Valo 		len += scnprintf(buf + len, size - len, "%llu ", rx_stats->nss_count[i]);
310d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "\nRX Duration:%llu ",
311d5c65159SKalle Valo 			 rx_stats->rx_duration);
3126a0c3702SJohn Crispin 	len += scnprintf(buf + len, size - len,
3136a0c3702SJohn Crispin 			 "\nDCM: %llu\nRU: 26 %llu 52: %llu 106: %llu 242: %llu 484: %llu 996: %llu\n",
3146a0c3702SJohn Crispin 			 rx_stats->dcm_count, rx_stats->ru_alloc_cnt[0],
3156a0c3702SJohn Crispin 			 rx_stats->ru_alloc_cnt[1], rx_stats->ru_alloc_cnt[2],
3166a0c3702SJohn Crispin 			 rx_stats->ru_alloc_cnt[3], rx_stats->ru_alloc_cnt[4],
3176a0c3702SJohn Crispin 			 rx_stats->ru_alloc_cnt[5]);
3186a0c3702SJohn Crispin 
319d5c65159SKalle Valo 	len += scnprintf(buf + len, size - len, "\n");
320d5c65159SKalle Valo 
321d5c65159SKalle Valo 	spin_unlock_bh(&ar->ab->base_lock);
322d5c65159SKalle Valo 
323d5c65159SKalle Valo 	if (len > size)
324d5c65159SKalle Valo 		len = size;
325d5c65159SKalle Valo 	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
326d5c65159SKalle Valo 	kfree(buf);
327d5c65159SKalle Valo 
328d5c65159SKalle Valo 	mutex_unlock(&ar->conf_mutex);
329d5c65159SKalle Valo 	return retval;
330d5c65159SKalle Valo }
331d5c65159SKalle Valo 
332d5c65159SKalle Valo static const struct file_operations fops_rx_stats = {
333d5c65159SKalle Valo 	.read = ath11k_dbg_sta_dump_rx_stats,
334d5c65159SKalle Valo 	.open = simple_open,
335d5c65159SKalle Valo 	.owner = THIS_MODULE,
336d5c65159SKalle Valo 	.llseek = default_llseek,
337d5c65159SKalle Valo };
338d5c65159SKalle Valo 
339d5c65159SKalle Valo static int
ath11k_dbg_sta_open_htt_peer_stats(struct inode * inode,struct file * file)340d5c65159SKalle Valo ath11k_dbg_sta_open_htt_peer_stats(struct inode *inode, struct file *file)
341d5c65159SKalle Valo {
342d5c65159SKalle Valo 	struct ieee80211_sta *sta = inode->i_private;
343d5c65159SKalle Valo 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
344d5c65159SKalle Valo 	struct ath11k *ar = arsta->arvif->ar;
345d5c65159SKalle Valo 	struct debug_htt_stats_req *stats_req;
346ac83b603SVenkateswara Naralasetty 	int type = ar->debug.htt_stats.type;
347d5c65159SKalle Valo 	int ret;
348d5c65159SKalle Valo 
349ac83b603SVenkateswara Naralasetty 	if ((type != ATH11K_DBG_HTT_EXT_STATS_PEER_INFO &&
350ac83b603SVenkateswara Naralasetty 	     type != ATH11K_DBG_HTT_EXT_STATS_PEER_CTRL_PATH_TXRX_STATS) ||
351ac83b603SVenkateswara Naralasetty 	    type == ATH11K_DBG_HTT_EXT_STATS_RESET)
352ac83b603SVenkateswara Naralasetty 		return -EPERM;
353ac83b603SVenkateswara Naralasetty 
354d5c65159SKalle Valo 	stats_req = vzalloc(sizeof(*stats_req) + ATH11K_HTT_STATS_BUF_SIZE);
355d5c65159SKalle Valo 	if (!stats_req)
356d5c65159SKalle Valo 		return -ENOMEM;
357d5c65159SKalle Valo 
358d5c65159SKalle Valo 	mutex_lock(&ar->conf_mutex);
359d5c65159SKalle Valo 	ar->debug.htt_stats.stats_req = stats_req;
360ac83b603SVenkateswara Naralasetty 	stats_req->type = type;
361d5c65159SKalle Valo 	memcpy(stats_req->peer_addr, sta->addr, ETH_ALEN);
362568f0603SKalle Valo 	ret = ath11k_debugfs_htt_stats_req(ar);
363d5c65159SKalle Valo 	mutex_unlock(&ar->conf_mutex);
364d5c65159SKalle Valo 	if (ret < 0)
365d5c65159SKalle Valo 		goto out;
366d5c65159SKalle Valo 
367d5c65159SKalle Valo 	file->private_data = stats_req;
368d5c65159SKalle Valo 	return 0;
369d5c65159SKalle Valo out:
370d5c65159SKalle Valo 	vfree(stats_req);
37152f274b5SSowmiya Sree Elavalagan 	ar->debug.htt_stats.stats_req = NULL;
372d5c65159SKalle Valo 	return ret;
373d5c65159SKalle Valo }
374d5c65159SKalle Valo 
375d5c65159SKalle Valo static int
ath11k_dbg_sta_release_htt_peer_stats(struct inode * inode,struct file * file)376d5c65159SKalle Valo ath11k_dbg_sta_release_htt_peer_stats(struct inode *inode, struct file *file)
377d5c65159SKalle Valo {
37852f274b5SSowmiya Sree Elavalagan 	struct ieee80211_sta *sta = inode->i_private;
37952f274b5SSowmiya Sree Elavalagan 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
38052f274b5SSowmiya Sree Elavalagan 	struct ath11k *ar = arsta->arvif->ar;
38152f274b5SSowmiya Sree Elavalagan 
38252f274b5SSowmiya Sree Elavalagan 	mutex_lock(&ar->conf_mutex);
383d5c65159SKalle Valo 	vfree(file->private_data);
38452f274b5SSowmiya Sree Elavalagan 	ar->debug.htt_stats.stats_req = NULL;
38552f274b5SSowmiya Sree Elavalagan 	mutex_unlock(&ar->conf_mutex);
38652f274b5SSowmiya Sree Elavalagan 
387d5c65159SKalle Valo 	return 0;
388d5c65159SKalle Valo }
389d5c65159SKalle Valo 
ath11k_dbg_sta_read_htt_peer_stats(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)390d5c65159SKalle Valo static ssize_t ath11k_dbg_sta_read_htt_peer_stats(struct file *file,
391d5c65159SKalle Valo 						  char __user *user_buf,
392d5c65159SKalle Valo 						  size_t count, loff_t *ppos)
393d5c65159SKalle Valo {
394d5c65159SKalle Valo 	struct debug_htt_stats_req *stats_req = file->private_data;
395d5c65159SKalle Valo 	char *buf;
396d5c65159SKalle Valo 	u32 length = 0;
397d5c65159SKalle Valo 
398d5c65159SKalle Valo 	buf = stats_req->buf;
399d5c65159SKalle Valo 	length = min_t(u32, stats_req->buf_len, ATH11K_HTT_STATS_BUF_SIZE);
400d5c65159SKalle Valo 	return simple_read_from_buffer(user_buf, count, ppos, buf, length);
401d5c65159SKalle Valo }
402d5c65159SKalle Valo 
403d5c65159SKalle Valo static const struct file_operations fops_htt_peer_stats = {
404d5c65159SKalle Valo 	.open = ath11k_dbg_sta_open_htt_peer_stats,
405d5c65159SKalle Valo 	.release = ath11k_dbg_sta_release_htt_peer_stats,
406d5c65159SKalle Valo 	.read = ath11k_dbg_sta_read_htt_peer_stats,
407d5c65159SKalle Valo 	.owner = THIS_MODULE,
408d5c65159SKalle Valo 	.llseek = default_llseek,
409d5c65159SKalle Valo };
410d5c65159SKalle Valo 
ath11k_dbg_sta_write_peer_pktlog(struct file * file,const char __user * buf,size_t count,loff_t * ppos)411d5c65159SKalle Valo static ssize_t ath11k_dbg_sta_write_peer_pktlog(struct file *file,
412d5c65159SKalle Valo 						const char __user *buf,
413d5c65159SKalle Valo 						size_t count, loff_t *ppos)
414d5c65159SKalle Valo {
415d5c65159SKalle Valo 	struct ieee80211_sta *sta = file->private_data;
416d5c65159SKalle Valo 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
417d5c65159SKalle Valo 	struct ath11k *ar = arsta->arvif->ar;
418d5c65159SKalle Valo 	int ret, enable;
419d5c65159SKalle Valo 
420d5c65159SKalle Valo 	mutex_lock(&ar->conf_mutex);
421d5c65159SKalle Valo 
422d5c65159SKalle Valo 	if (ar->state != ATH11K_STATE_ON) {
423d5c65159SKalle Valo 		ret = -ENETDOWN;
424d5c65159SKalle Valo 		goto out;
425d5c65159SKalle Valo 	}
426d5c65159SKalle Valo 
427d5c65159SKalle Valo 	ret = kstrtoint_from_user(buf, count, 0, &enable);
428d5c65159SKalle Valo 	if (ret)
429d5c65159SKalle Valo 		goto out;
430d5c65159SKalle Valo 
431d5c65159SKalle Valo 	ar->debug.pktlog_peer_valid = enable;
432d5c65159SKalle Valo 	memcpy(ar->debug.pktlog_peer_addr, sta->addr, ETH_ALEN);
433d5c65159SKalle Valo 
434d5c65159SKalle Valo 	/* Send peer based pktlog enable/disable */
435d5c65159SKalle Valo 	ret = ath11k_wmi_pdev_peer_pktlog_filter(ar, sta->addr, enable);
436d5c65159SKalle Valo 	if (ret) {
437d5c65159SKalle Valo 		ath11k_warn(ar->ab, "failed to set peer pktlog filter %pM: %d\n",
438d5c65159SKalle Valo 			    sta->addr, ret);
439d5c65159SKalle Valo 		goto out;
440d5c65159SKalle Valo 	}
441d5c65159SKalle Valo 
442d5c65159SKalle Valo 	ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "peer pktlog filter set to %d\n",
443d5c65159SKalle Valo 		   enable);
444d5c65159SKalle Valo 	ret = count;
445d5c65159SKalle Valo 
446d5c65159SKalle Valo out:
447d5c65159SKalle Valo 	mutex_unlock(&ar->conf_mutex);
448d5c65159SKalle Valo 	return ret;
449d5c65159SKalle Valo }
450d5c65159SKalle Valo 
ath11k_dbg_sta_read_peer_pktlog(struct file * file,char __user * ubuf,size_t count,loff_t * ppos)451d5c65159SKalle Valo static ssize_t ath11k_dbg_sta_read_peer_pktlog(struct file *file,
452d5c65159SKalle Valo 					       char __user *ubuf,
453d5c65159SKalle Valo 					       size_t count, loff_t *ppos)
454d5c65159SKalle Valo {
455d5c65159SKalle Valo 	struct ieee80211_sta *sta = file->private_data;
456d5c65159SKalle Valo 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
457d5c65159SKalle Valo 	struct ath11k *ar = arsta->arvif->ar;
458d5c65159SKalle Valo 	char buf[32] = {0};
459d5c65159SKalle Valo 	int len;
460d5c65159SKalle Valo 
461d5c65159SKalle Valo 	mutex_lock(&ar->conf_mutex);
462d5c65159SKalle Valo 	len = scnprintf(buf, sizeof(buf), "%08x %pM\n",
463d5c65159SKalle Valo 			ar->debug.pktlog_peer_valid,
464d5c65159SKalle Valo 			ar->debug.pktlog_peer_addr);
465d5c65159SKalle Valo 	mutex_unlock(&ar->conf_mutex);
466d5c65159SKalle Valo 
467d5c65159SKalle Valo 	return simple_read_from_buffer(ubuf, count, ppos, buf, len);
468d5c65159SKalle Valo }
469d5c65159SKalle Valo 
470d5c65159SKalle Valo static const struct file_operations fops_peer_pktlog = {
471d5c65159SKalle Valo 	.write = ath11k_dbg_sta_write_peer_pktlog,
472d5c65159SKalle Valo 	.read = ath11k_dbg_sta_read_peer_pktlog,
473d5c65159SKalle Valo 	.open = simple_open,
474d5c65159SKalle Valo 	.owner = THIS_MODULE,
475d5c65159SKalle Valo 	.llseek = default_llseek,
476d5c65159SKalle Valo };
477d5c65159SKalle Valo 
ath11k_dbg_sta_write_delba(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)4789556dfa2SMaharaja Kennadyrajan static ssize_t ath11k_dbg_sta_write_delba(struct file *file,
4799556dfa2SMaharaja Kennadyrajan 					  const char __user *user_buf,
4809556dfa2SMaharaja Kennadyrajan 					  size_t count, loff_t *ppos)
4819556dfa2SMaharaja Kennadyrajan {
4829556dfa2SMaharaja Kennadyrajan 	struct ieee80211_sta *sta = file->private_data;
4839556dfa2SMaharaja Kennadyrajan 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
4849556dfa2SMaharaja Kennadyrajan 	struct ath11k *ar = arsta->arvif->ar;
4859556dfa2SMaharaja Kennadyrajan 	u32 tid, initiator, reason;
4869556dfa2SMaharaja Kennadyrajan 	int ret;
4879556dfa2SMaharaja Kennadyrajan 	char buf[64] = {0};
4889556dfa2SMaharaja Kennadyrajan 
4899556dfa2SMaharaja Kennadyrajan 	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
4909556dfa2SMaharaja Kennadyrajan 				     user_buf, count);
4919556dfa2SMaharaja Kennadyrajan 	if (ret <= 0)
4929556dfa2SMaharaja Kennadyrajan 		return ret;
4939556dfa2SMaharaja Kennadyrajan 
4949556dfa2SMaharaja Kennadyrajan 	ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
4959556dfa2SMaharaja Kennadyrajan 	if (ret != 3)
4969556dfa2SMaharaja Kennadyrajan 		return -EINVAL;
4979556dfa2SMaharaja Kennadyrajan 
4989556dfa2SMaharaja Kennadyrajan 	/* Valid TID values are 0 through 15 */
4999556dfa2SMaharaja Kennadyrajan 	if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
5009556dfa2SMaharaja Kennadyrajan 		return -EINVAL;
5019556dfa2SMaharaja Kennadyrajan 
5029556dfa2SMaharaja Kennadyrajan 	mutex_lock(&ar->conf_mutex);
5039556dfa2SMaharaja Kennadyrajan 	if (ar->state != ATH11K_STATE_ON ||
5049556dfa2SMaharaja Kennadyrajan 	    arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
5059556dfa2SMaharaja Kennadyrajan 		ret = count;
5069556dfa2SMaharaja Kennadyrajan 		goto out;
5079556dfa2SMaharaja Kennadyrajan 	}
5089556dfa2SMaharaja Kennadyrajan 
5099556dfa2SMaharaja Kennadyrajan 	ret = ath11k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
5109556dfa2SMaharaja Kennadyrajan 				    tid, initiator, reason);
5119556dfa2SMaharaja Kennadyrajan 	if (ret) {
5129556dfa2SMaharaja Kennadyrajan 		ath11k_warn(ar->ab, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
5139556dfa2SMaharaja Kennadyrajan 			    arsta->arvif->vdev_id, sta->addr, tid, initiator,
5149556dfa2SMaharaja Kennadyrajan 			    reason);
5159556dfa2SMaharaja Kennadyrajan 	}
5169556dfa2SMaharaja Kennadyrajan 	ret = count;
5179556dfa2SMaharaja Kennadyrajan out:
5189556dfa2SMaharaja Kennadyrajan 	mutex_unlock(&ar->conf_mutex);
5199556dfa2SMaharaja Kennadyrajan 	return ret;
5209556dfa2SMaharaja Kennadyrajan }
5219556dfa2SMaharaja Kennadyrajan 
5229556dfa2SMaharaja Kennadyrajan static const struct file_operations fops_delba = {
5239556dfa2SMaharaja Kennadyrajan 	.write = ath11k_dbg_sta_write_delba,
5249556dfa2SMaharaja Kennadyrajan 	.open = simple_open,
5259556dfa2SMaharaja Kennadyrajan 	.owner = THIS_MODULE,
5269556dfa2SMaharaja Kennadyrajan 	.llseek = default_llseek,
5279556dfa2SMaharaja Kennadyrajan };
5289556dfa2SMaharaja Kennadyrajan 
ath11k_dbg_sta_write_addba_resp(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)5299556dfa2SMaharaja Kennadyrajan static ssize_t ath11k_dbg_sta_write_addba_resp(struct file *file,
5309556dfa2SMaharaja Kennadyrajan 					       const char __user *user_buf,
5319556dfa2SMaharaja Kennadyrajan 					       size_t count, loff_t *ppos)
5329556dfa2SMaharaja Kennadyrajan {
5339556dfa2SMaharaja Kennadyrajan 	struct ieee80211_sta *sta = file->private_data;
5349556dfa2SMaharaja Kennadyrajan 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
5359556dfa2SMaharaja Kennadyrajan 	struct ath11k *ar = arsta->arvif->ar;
5369556dfa2SMaharaja Kennadyrajan 	u32 tid, status;
5379556dfa2SMaharaja Kennadyrajan 	int ret;
5389556dfa2SMaharaja Kennadyrajan 	char buf[64] = {0};
5399556dfa2SMaharaja Kennadyrajan 
5409556dfa2SMaharaja Kennadyrajan 	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
5419556dfa2SMaharaja Kennadyrajan 				     user_buf, count);
5429556dfa2SMaharaja Kennadyrajan 	if (ret <= 0)
5439556dfa2SMaharaja Kennadyrajan 		return ret;
5449556dfa2SMaharaja Kennadyrajan 
5459556dfa2SMaharaja Kennadyrajan 	ret = sscanf(buf, "%u %u", &tid, &status);
5469556dfa2SMaharaja Kennadyrajan 	if (ret != 2)
5479556dfa2SMaharaja Kennadyrajan 		return -EINVAL;
5489556dfa2SMaharaja Kennadyrajan 
5499556dfa2SMaharaja Kennadyrajan 	/* Valid TID values are 0 through 15 */
5509556dfa2SMaharaja Kennadyrajan 	if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
5519556dfa2SMaharaja Kennadyrajan 		return -EINVAL;
5529556dfa2SMaharaja Kennadyrajan 
5539556dfa2SMaharaja Kennadyrajan 	mutex_lock(&ar->conf_mutex);
5549556dfa2SMaharaja Kennadyrajan 	if (ar->state != ATH11K_STATE_ON ||
5559556dfa2SMaharaja Kennadyrajan 	    arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
5569556dfa2SMaharaja Kennadyrajan 		ret = count;
5579556dfa2SMaharaja Kennadyrajan 		goto out;
5589556dfa2SMaharaja Kennadyrajan 	}
5599556dfa2SMaharaja Kennadyrajan 
5609556dfa2SMaharaja Kennadyrajan 	ret = ath11k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
5619556dfa2SMaharaja Kennadyrajan 					tid, status);
5629556dfa2SMaharaja Kennadyrajan 	if (ret) {
5639556dfa2SMaharaja Kennadyrajan 		ath11k_warn(ar->ab, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
5649556dfa2SMaharaja Kennadyrajan 			    arsta->arvif->vdev_id, sta->addr, tid, status);
5659556dfa2SMaharaja Kennadyrajan 	}
5669556dfa2SMaharaja Kennadyrajan 	ret = count;
5679556dfa2SMaharaja Kennadyrajan out:
5689556dfa2SMaharaja Kennadyrajan 	mutex_unlock(&ar->conf_mutex);
5699556dfa2SMaharaja Kennadyrajan 	return ret;
5709556dfa2SMaharaja Kennadyrajan }
5719556dfa2SMaharaja Kennadyrajan 
5729556dfa2SMaharaja Kennadyrajan static const struct file_operations fops_addba_resp = {
5739556dfa2SMaharaja Kennadyrajan 	.write = ath11k_dbg_sta_write_addba_resp,
5749556dfa2SMaharaja Kennadyrajan 	.open = simple_open,
5759556dfa2SMaharaja Kennadyrajan 	.owner = THIS_MODULE,
5769556dfa2SMaharaja Kennadyrajan 	.llseek = default_llseek,
5779556dfa2SMaharaja Kennadyrajan };
5789556dfa2SMaharaja Kennadyrajan 
ath11k_dbg_sta_write_addba(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)5799556dfa2SMaharaja Kennadyrajan static ssize_t ath11k_dbg_sta_write_addba(struct file *file,
5809556dfa2SMaharaja Kennadyrajan 					  const char __user *user_buf,
5819556dfa2SMaharaja Kennadyrajan 					  size_t count, loff_t *ppos)
5829556dfa2SMaharaja Kennadyrajan {
5839556dfa2SMaharaja Kennadyrajan 	struct ieee80211_sta *sta = file->private_data;
5849556dfa2SMaharaja Kennadyrajan 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
5859556dfa2SMaharaja Kennadyrajan 	struct ath11k *ar = arsta->arvif->ar;
5869556dfa2SMaharaja Kennadyrajan 	u32 tid, buf_size;
5879556dfa2SMaharaja Kennadyrajan 	int ret;
5889556dfa2SMaharaja Kennadyrajan 	char buf[64] = {0};
5899556dfa2SMaharaja Kennadyrajan 
5909556dfa2SMaharaja Kennadyrajan 	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
5919556dfa2SMaharaja Kennadyrajan 				     user_buf, count);
5929556dfa2SMaharaja Kennadyrajan 	if (ret <= 0)
5939556dfa2SMaharaja Kennadyrajan 		return ret;
5949556dfa2SMaharaja Kennadyrajan 
5959556dfa2SMaharaja Kennadyrajan 	ret = sscanf(buf, "%u %u", &tid, &buf_size);
5969556dfa2SMaharaja Kennadyrajan 	if (ret != 2)
5979556dfa2SMaharaja Kennadyrajan 		return -EINVAL;
5989556dfa2SMaharaja Kennadyrajan 
5999556dfa2SMaharaja Kennadyrajan 	/* Valid TID values are 0 through 15 */
6009556dfa2SMaharaja Kennadyrajan 	if (tid > HAL_DESC_REO_NON_QOS_TID - 1)
6019556dfa2SMaharaja Kennadyrajan 		return -EINVAL;
6029556dfa2SMaharaja Kennadyrajan 
6039556dfa2SMaharaja Kennadyrajan 	mutex_lock(&ar->conf_mutex);
6049556dfa2SMaharaja Kennadyrajan 	if (ar->state != ATH11K_STATE_ON ||
6059556dfa2SMaharaja Kennadyrajan 	    arsta->aggr_mode != ATH11K_DBG_AGGR_MODE_MANUAL) {
6069556dfa2SMaharaja Kennadyrajan 		ret = count;
6079556dfa2SMaharaja Kennadyrajan 		goto out;
6089556dfa2SMaharaja Kennadyrajan 	}
6099556dfa2SMaharaja Kennadyrajan 
6109556dfa2SMaharaja Kennadyrajan 	ret = ath11k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
6119556dfa2SMaharaja Kennadyrajan 				    tid, buf_size);
6129556dfa2SMaharaja Kennadyrajan 	if (ret) {
6139556dfa2SMaharaja Kennadyrajan 		ath11k_warn(ar->ab, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
6149556dfa2SMaharaja Kennadyrajan 			    arsta->arvif->vdev_id, sta->addr, tid, buf_size);
6159556dfa2SMaharaja Kennadyrajan 	}
6169556dfa2SMaharaja Kennadyrajan 
6179556dfa2SMaharaja Kennadyrajan 	ret = count;
6189556dfa2SMaharaja Kennadyrajan out:
6199556dfa2SMaharaja Kennadyrajan 	mutex_unlock(&ar->conf_mutex);
6209556dfa2SMaharaja Kennadyrajan 	return ret;
6219556dfa2SMaharaja Kennadyrajan }
6229556dfa2SMaharaja Kennadyrajan 
6239556dfa2SMaharaja Kennadyrajan static const struct file_operations fops_addba = {
6249556dfa2SMaharaja Kennadyrajan 	.write = ath11k_dbg_sta_write_addba,
6259556dfa2SMaharaja Kennadyrajan 	.open = simple_open,
6269556dfa2SMaharaja Kennadyrajan 	.owner = THIS_MODULE,
6279556dfa2SMaharaja Kennadyrajan 	.llseek = default_llseek,
6289556dfa2SMaharaja Kennadyrajan };
6299556dfa2SMaharaja Kennadyrajan 
ath11k_dbg_sta_read_aggr_mode(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)6309556dfa2SMaharaja Kennadyrajan static ssize_t ath11k_dbg_sta_read_aggr_mode(struct file *file,
6319556dfa2SMaharaja Kennadyrajan 					     char __user *user_buf,
6329556dfa2SMaharaja Kennadyrajan 					     size_t count, loff_t *ppos)
6339556dfa2SMaharaja Kennadyrajan {
6349556dfa2SMaharaja Kennadyrajan 	struct ieee80211_sta *sta = file->private_data;
6359556dfa2SMaharaja Kennadyrajan 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
6369556dfa2SMaharaja Kennadyrajan 	struct ath11k *ar = arsta->arvif->ar;
6379556dfa2SMaharaja Kennadyrajan 	char buf[64];
6389556dfa2SMaharaja Kennadyrajan 	int len = 0;
6399556dfa2SMaharaja Kennadyrajan 
6409556dfa2SMaharaja Kennadyrajan 	mutex_lock(&ar->conf_mutex);
6419556dfa2SMaharaja Kennadyrajan 	len = scnprintf(buf, sizeof(buf) - len,
6429556dfa2SMaharaja Kennadyrajan 			"aggregation mode: %s\n\n%s\n%s\n",
6439556dfa2SMaharaja Kennadyrajan 			(arsta->aggr_mode == ATH11K_DBG_AGGR_MODE_AUTO) ?
6449556dfa2SMaharaja Kennadyrajan 			"auto" : "manual", "auto = 0", "manual = 1");
6459556dfa2SMaharaja Kennadyrajan 	mutex_unlock(&ar->conf_mutex);
6469556dfa2SMaharaja Kennadyrajan 
6479556dfa2SMaharaja Kennadyrajan 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
6489556dfa2SMaharaja Kennadyrajan }
6499556dfa2SMaharaja Kennadyrajan 
ath11k_dbg_sta_write_aggr_mode(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)6509556dfa2SMaharaja Kennadyrajan static ssize_t ath11k_dbg_sta_write_aggr_mode(struct file *file,
6519556dfa2SMaharaja Kennadyrajan 					      const char __user *user_buf,
6529556dfa2SMaharaja Kennadyrajan 					      size_t count, loff_t *ppos)
6539556dfa2SMaharaja Kennadyrajan {
6549556dfa2SMaharaja Kennadyrajan 	struct ieee80211_sta *sta = file->private_data;
6559556dfa2SMaharaja Kennadyrajan 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
6569556dfa2SMaharaja Kennadyrajan 	struct ath11k *ar = arsta->arvif->ar;
6579556dfa2SMaharaja Kennadyrajan 	u32 aggr_mode;
6589556dfa2SMaharaja Kennadyrajan 	int ret;
6599556dfa2SMaharaja Kennadyrajan 
6609556dfa2SMaharaja Kennadyrajan 	if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode))
6619556dfa2SMaharaja Kennadyrajan 		return -EINVAL;
6629556dfa2SMaharaja Kennadyrajan 
6639556dfa2SMaharaja Kennadyrajan 	if (aggr_mode >= ATH11K_DBG_AGGR_MODE_MAX)
6649556dfa2SMaharaja Kennadyrajan 		return -EINVAL;
6659556dfa2SMaharaja Kennadyrajan 
6669556dfa2SMaharaja Kennadyrajan 	mutex_lock(&ar->conf_mutex);
6679556dfa2SMaharaja Kennadyrajan 	if (ar->state != ATH11K_STATE_ON ||
6689556dfa2SMaharaja Kennadyrajan 	    aggr_mode == arsta->aggr_mode) {
6699556dfa2SMaharaja Kennadyrajan 		ret = count;
6709556dfa2SMaharaja Kennadyrajan 		goto out;
6719556dfa2SMaharaja Kennadyrajan 	}
6729556dfa2SMaharaja Kennadyrajan 
6739556dfa2SMaharaja Kennadyrajan 	ret = ath11k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr);
6749556dfa2SMaharaja Kennadyrajan 	if (ret) {
6759556dfa2SMaharaja Kennadyrajan 		ath11k_warn(ar->ab, "failed to clear addba session ret: %d\n",
6769556dfa2SMaharaja Kennadyrajan 			    ret);
6779556dfa2SMaharaja Kennadyrajan 		goto out;
6789556dfa2SMaharaja Kennadyrajan 	}
6799556dfa2SMaharaja Kennadyrajan 
6809556dfa2SMaharaja Kennadyrajan 	arsta->aggr_mode = aggr_mode;
6819556dfa2SMaharaja Kennadyrajan out:
6829556dfa2SMaharaja Kennadyrajan 	mutex_unlock(&ar->conf_mutex);
6839556dfa2SMaharaja Kennadyrajan 	return ret;
6849556dfa2SMaharaja Kennadyrajan }
6859556dfa2SMaharaja Kennadyrajan 
6869556dfa2SMaharaja Kennadyrajan static const struct file_operations fops_aggr_mode = {
6879556dfa2SMaharaja Kennadyrajan 	.read = ath11k_dbg_sta_read_aggr_mode,
6889556dfa2SMaharaja Kennadyrajan 	.write = ath11k_dbg_sta_write_aggr_mode,
6899556dfa2SMaharaja Kennadyrajan 	.open = simple_open,
6909556dfa2SMaharaja Kennadyrajan 	.owner = THIS_MODULE,
6919556dfa2SMaharaja Kennadyrajan 	.llseek = default_llseek,
6929556dfa2SMaharaja Kennadyrajan };
6939556dfa2SMaharaja Kennadyrajan 
694559ef68fSAshok Raj Nagarajan static ssize_t
ath11k_write_htt_peer_stats_reset(struct file * file,const char __user * user_buf,size_t count,loff_t * ppos)695559ef68fSAshok Raj Nagarajan ath11k_write_htt_peer_stats_reset(struct file *file,
696559ef68fSAshok Raj Nagarajan 				  const char __user *user_buf,
697559ef68fSAshok Raj Nagarajan 				  size_t count, loff_t *ppos)
698559ef68fSAshok Raj Nagarajan {
699559ef68fSAshok Raj Nagarajan 	struct ieee80211_sta *sta = file->private_data;
700559ef68fSAshok Raj Nagarajan 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
701559ef68fSAshok Raj Nagarajan 	struct ath11k *ar = arsta->arvif->ar;
702559ef68fSAshok Raj Nagarajan 	struct htt_ext_stats_cfg_params cfg_params = { 0 };
703559ef68fSAshok Raj Nagarajan 	int ret;
704559ef68fSAshok Raj Nagarajan 	u8 type;
705559ef68fSAshok Raj Nagarajan 
706559ef68fSAshok Raj Nagarajan 	ret = kstrtou8_from_user(user_buf, count, 0, &type);
707559ef68fSAshok Raj Nagarajan 	if (ret)
708559ef68fSAshok Raj Nagarajan 		return ret;
709559ef68fSAshok Raj Nagarajan 
710559ef68fSAshok Raj Nagarajan 	if (!type)
711559ef68fSAshok Raj Nagarajan 		return ret;
712559ef68fSAshok Raj Nagarajan 
713559ef68fSAshok Raj Nagarajan 	mutex_lock(&ar->conf_mutex);
714559ef68fSAshok Raj Nagarajan 	cfg_params.cfg0 = HTT_STAT_PEER_INFO_MAC_ADDR;
715559ef68fSAshok Raj Nagarajan 	cfg_params.cfg0 |= FIELD_PREP(GENMASK(15, 1),
716559ef68fSAshok Raj Nagarajan 				HTT_PEER_STATS_REQ_MODE_FLUSH_TQM);
717559ef68fSAshok Raj Nagarajan 
718559ef68fSAshok Raj Nagarajan 	cfg_params.cfg1 = HTT_STAT_DEFAULT_PEER_REQ_TYPE;
719559ef68fSAshok Raj Nagarajan 
720559ef68fSAshok Raj Nagarajan 	cfg_params.cfg2 |= FIELD_PREP(GENMASK(7, 0), sta->addr[0]);
721559ef68fSAshok Raj Nagarajan 	cfg_params.cfg2 |= FIELD_PREP(GENMASK(15, 8), sta->addr[1]);
722559ef68fSAshok Raj Nagarajan 	cfg_params.cfg2 |= FIELD_PREP(GENMASK(23, 16), sta->addr[2]);
723559ef68fSAshok Raj Nagarajan 	cfg_params.cfg2 |= FIELD_PREP(GENMASK(31, 24), sta->addr[3]);
724559ef68fSAshok Raj Nagarajan 
725559ef68fSAshok Raj Nagarajan 	cfg_params.cfg3 |= FIELD_PREP(GENMASK(7, 0), sta->addr[4]);
726559ef68fSAshok Raj Nagarajan 	cfg_params.cfg3 |= FIELD_PREP(GENMASK(15, 8), sta->addr[5]);
727559ef68fSAshok Raj Nagarajan 
728559ef68fSAshok Raj Nagarajan 	cfg_params.cfg3 |= ATH11K_HTT_PEER_STATS_RESET;
729559ef68fSAshok Raj Nagarajan 
730559ef68fSAshok Raj Nagarajan 	ret = ath11k_dp_tx_htt_h2t_ext_stats_req(ar,
731559ef68fSAshok Raj Nagarajan 						 ATH11K_DBG_HTT_EXT_STATS_PEER_INFO,
732559ef68fSAshok Raj Nagarajan 						 &cfg_params,
733559ef68fSAshok Raj Nagarajan 						 0ULL);
734559ef68fSAshok Raj Nagarajan 	if (ret) {
735559ef68fSAshok Raj Nagarajan 		ath11k_warn(ar->ab, "failed to send htt peer stats request: %d\n", ret);
736559ef68fSAshok Raj Nagarajan 		mutex_unlock(&ar->conf_mutex);
737559ef68fSAshok Raj Nagarajan 		return ret;
738559ef68fSAshok Raj Nagarajan 	}
739559ef68fSAshok Raj Nagarajan 
740559ef68fSAshok Raj Nagarajan 	mutex_unlock(&ar->conf_mutex);
741559ef68fSAshok Raj Nagarajan 
742559ef68fSAshok Raj Nagarajan 	ret = count;
743559ef68fSAshok Raj Nagarajan 
744559ef68fSAshok Raj Nagarajan 	return ret;
745559ef68fSAshok Raj Nagarajan }
746559ef68fSAshok Raj Nagarajan 
747559ef68fSAshok Raj Nagarajan static const struct file_operations fops_htt_peer_stats_reset = {
748559ef68fSAshok Raj Nagarajan 	.write = ath11k_write_htt_peer_stats_reset,
749559ef68fSAshok Raj Nagarajan 	.open = simple_open,
750559ef68fSAshok Raj Nagarajan 	.owner = THIS_MODULE,
751559ef68fSAshok Raj Nagarajan 	.llseek = default_llseek,
752559ef68fSAshok Raj Nagarajan };
753559ef68fSAshok Raj Nagarajan 
ath11k_dbg_sta_read_peer_ps_state(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)754*710a95f9SVenkateswara Naralasetty static ssize_t ath11k_dbg_sta_read_peer_ps_state(struct file *file,
755*710a95f9SVenkateswara Naralasetty 						 char __user *user_buf,
756*710a95f9SVenkateswara Naralasetty 						 size_t count, loff_t *ppos)
757*710a95f9SVenkateswara Naralasetty {
758*710a95f9SVenkateswara Naralasetty 	struct ieee80211_sta *sta = file->private_data;
759*710a95f9SVenkateswara Naralasetty 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
760*710a95f9SVenkateswara Naralasetty 	struct ath11k *ar = arsta->arvif->ar;
761*710a95f9SVenkateswara Naralasetty 	char buf[20];
762*710a95f9SVenkateswara Naralasetty 	int len;
763*710a95f9SVenkateswara Naralasetty 
764*710a95f9SVenkateswara Naralasetty 	spin_lock_bh(&ar->data_lock);
765*710a95f9SVenkateswara Naralasetty 
766*710a95f9SVenkateswara Naralasetty 	len = scnprintf(buf, sizeof(buf), "%d\n", arsta->peer_ps_state);
767*710a95f9SVenkateswara Naralasetty 
768*710a95f9SVenkateswara Naralasetty 	spin_unlock_bh(&ar->data_lock);
769*710a95f9SVenkateswara Naralasetty 
770*710a95f9SVenkateswara Naralasetty 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
771*710a95f9SVenkateswara Naralasetty }
772*710a95f9SVenkateswara Naralasetty 
773*710a95f9SVenkateswara Naralasetty static const struct file_operations fops_peer_ps_state = {
774*710a95f9SVenkateswara Naralasetty 	.open = simple_open,
775*710a95f9SVenkateswara Naralasetty 	.read = ath11k_dbg_sta_read_peer_ps_state,
776*710a95f9SVenkateswara Naralasetty 	.owner = THIS_MODULE,
777*710a95f9SVenkateswara Naralasetty 	.llseek = default_llseek,
778*710a95f9SVenkateswara Naralasetty };
779*710a95f9SVenkateswara Naralasetty 
ath11k_dbg_sta_read_current_ps_duration(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)780*710a95f9SVenkateswara Naralasetty static ssize_t ath11k_dbg_sta_read_current_ps_duration(struct file *file,
781*710a95f9SVenkateswara Naralasetty 						       char __user *user_buf,
782*710a95f9SVenkateswara Naralasetty 						       size_t count,
783*710a95f9SVenkateswara Naralasetty 						       loff_t *ppos)
784*710a95f9SVenkateswara Naralasetty {
785*710a95f9SVenkateswara Naralasetty 	struct ieee80211_sta *sta = file->private_data;
786*710a95f9SVenkateswara Naralasetty 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
787*710a95f9SVenkateswara Naralasetty 	struct ath11k *ar = arsta->arvif->ar;
788*710a95f9SVenkateswara Naralasetty 	u64 time_since_station_in_power_save;
789*710a95f9SVenkateswara Naralasetty 	char buf[20];
790*710a95f9SVenkateswara Naralasetty 	int len;
791*710a95f9SVenkateswara Naralasetty 
792*710a95f9SVenkateswara Naralasetty 	spin_lock_bh(&ar->data_lock);
793*710a95f9SVenkateswara Naralasetty 
794*710a95f9SVenkateswara Naralasetty 	if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON &&
795*710a95f9SVenkateswara Naralasetty 	    arsta->peer_current_ps_valid)
796*710a95f9SVenkateswara Naralasetty 		time_since_station_in_power_save = jiffies_to_msecs(jiffies
797*710a95f9SVenkateswara Naralasetty 						- arsta->ps_start_jiffies);
798*710a95f9SVenkateswara Naralasetty 	else
799*710a95f9SVenkateswara Naralasetty 		time_since_station_in_power_save = 0;
800*710a95f9SVenkateswara Naralasetty 
801*710a95f9SVenkateswara Naralasetty 	len = scnprintf(buf, sizeof(buf), "%llu\n",
802*710a95f9SVenkateswara Naralasetty 			time_since_station_in_power_save);
803*710a95f9SVenkateswara Naralasetty 	spin_unlock_bh(&ar->data_lock);
804*710a95f9SVenkateswara Naralasetty 
805*710a95f9SVenkateswara Naralasetty 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
806*710a95f9SVenkateswara Naralasetty }
807*710a95f9SVenkateswara Naralasetty 
808*710a95f9SVenkateswara Naralasetty static const struct file_operations fops_current_ps_duration = {
809*710a95f9SVenkateswara Naralasetty 	.open = simple_open,
810*710a95f9SVenkateswara Naralasetty 	.read = ath11k_dbg_sta_read_current_ps_duration,
811*710a95f9SVenkateswara Naralasetty 	.owner = THIS_MODULE,
812*710a95f9SVenkateswara Naralasetty 	.llseek = default_llseek,
813*710a95f9SVenkateswara Naralasetty };
814*710a95f9SVenkateswara Naralasetty 
ath11k_dbg_sta_read_total_ps_duration(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)815*710a95f9SVenkateswara Naralasetty static ssize_t ath11k_dbg_sta_read_total_ps_duration(struct file *file,
816*710a95f9SVenkateswara Naralasetty 						     char __user *user_buf,
817*710a95f9SVenkateswara Naralasetty 						     size_t count, loff_t *ppos)
818*710a95f9SVenkateswara Naralasetty {
819*710a95f9SVenkateswara Naralasetty 	struct ieee80211_sta *sta = file->private_data;
820*710a95f9SVenkateswara Naralasetty 	struct ath11k_sta *arsta = (struct ath11k_sta *)sta->drv_priv;
821*710a95f9SVenkateswara Naralasetty 	struct ath11k *ar = arsta->arvif->ar;
822*710a95f9SVenkateswara Naralasetty 	char buf[20];
823*710a95f9SVenkateswara Naralasetty 	u64 power_save_duration;
824*710a95f9SVenkateswara Naralasetty 	int len;
825*710a95f9SVenkateswara Naralasetty 
826*710a95f9SVenkateswara Naralasetty 	spin_lock_bh(&ar->data_lock);
827*710a95f9SVenkateswara Naralasetty 
828*710a95f9SVenkateswara Naralasetty 	if (arsta->peer_ps_state == WMI_PEER_PS_STATE_ON &&
829*710a95f9SVenkateswara Naralasetty 	    arsta->peer_current_ps_valid)
830*710a95f9SVenkateswara Naralasetty 		power_save_duration = jiffies_to_msecs(jiffies
831*710a95f9SVenkateswara Naralasetty 						- arsta->ps_start_jiffies)
832*710a95f9SVenkateswara Naralasetty 						+ arsta->ps_total_duration;
833*710a95f9SVenkateswara Naralasetty 	else
834*710a95f9SVenkateswara Naralasetty 		power_save_duration = arsta->ps_total_duration;
835*710a95f9SVenkateswara Naralasetty 
836*710a95f9SVenkateswara Naralasetty 	len = scnprintf(buf, sizeof(buf), "%llu\n", power_save_duration);
837*710a95f9SVenkateswara Naralasetty 
838*710a95f9SVenkateswara Naralasetty 	spin_unlock_bh(&ar->data_lock);
839*710a95f9SVenkateswara Naralasetty 
840*710a95f9SVenkateswara Naralasetty 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
841*710a95f9SVenkateswara Naralasetty }
842*710a95f9SVenkateswara Naralasetty 
843*710a95f9SVenkateswara Naralasetty static const struct file_operations fops_total_ps_duration = {
844*710a95f9SVenkateswara Naralasetty 	.open = simple_open,
845*710a95f9SVenkateswara Naralasetty 	.read = ath11k_dbg_sta_read_total_ps_duration,
846*710a95f9SVenkateswara Naralasetty 	.owner = THIS_MODULE,
847*710a95f9SVenkateswara Naralasetty 	.llseek = default_llseek,
848*710a95f9SVenkateswara Naralasetty };
849*710a95f9SVenkateswara Naralasetty 
ath11k_debugfs_sta_op_add(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct dentry * dir)850568f0603SKalle Valo void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
851d5c65159SKalle Valo 			       struct ieee80211_sta *sta, struct dentry *dir)
852d5c65159SKalle Valo {
853d5c65159SKalle Valo 	struct ath11k *ar = hw->priv;
854d5c65159SKalle Valo 
855cb4e57dbSKalle Valo 	if (ath11k_debugfs_is_extd_tx_stats_enabled(ar))
856d5c65159SKalle Valo 		debugfs_create_file("tx_stats", 0400, dir, sta,
857d5c65159SKalle Valo 				    &fops_tx_stats);
858cb4e57dbSKalle Valo 	if (ath11k_debugfs_is_extd_rx_stats_enabled(ar))
859d5c65159SKalle Valo 		debugfs_create_file("rx_stats", 0400, dir, sta,
860d5c65159SKalle Valo 				    &fops_rx_stats);
861d5c65159SKalle Valo 
862d5c65159SKalle Valo 	debugfs_create_file("htt_peer_stats", 0400, dir, sta,
863d5c65159SKalle Valo 			    &fops_htt_peer_stats);
864d5c65159SKalle Valo 
865d5c65159SKalle Valo 	debugfs_create_file("peer_pktlog", 0644, dir, sta,
866d5c65159SKalle Valo 			    &fops_peer_pktlog);
8679556dfa2SMaharaja Kennadyrajan 
8689556dfa2SMaharaja Kennadyrajan 	debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
8699556dfa2SMaharaja Kennadyrajan 	debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
8709556dfa2SMaharaja Kennadyrajan 	debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
8719556dfa2SMaharaja Kennadyrajan 	debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
872559ef68fSAshok Raj Nagarajan 
873559ef68fSAshok Raj Nagarajan 	if (test_bit(WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET,
874559ef68fSAshok Raj Nagarajan 		     ar->ab->wmi_ab.svc_map))
875559ef68fSAshok Raj Nagarajan 		debugfs_create_file("htt_peer_stats_reset", 0600, dir, sta,
876559ef68fSAshok Raj Nagarajan 				    &fops_htt_peer_stats_reset);
877*710a95f9SVenkateswara Naralasetty 
878*710a95f9SVenkateswara Naralasetty 	debugfs_create_file("peer_ps_state", 0400, dir, sta,
879*710a95f9SVenkateswara Naralasetty 			    &fops_peer_ps_state);
880*710a95f9SVenkateswara Naralasetty 
881*710a95f9SVenkateswara Naralasetty 	if (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,
882*710a95f9SVenkateswara Naralasetty 		     ar->ab->wmi_ab.svc_map)) {
883*710a95f9SVenkateswara Naralasetty 		debugfs_create_file("current_ps_duration", 0440, dir, sta,
884*710a95f9SVenkateswara Naralasetty 				    &fops_current_ps_duration);
885*710a95f9SVenkateswara Naralasetty 		debugfs_create_file("total_ps_duration", 0440, dir, sta,
886*710a95f9SVenkateswara Naralasetty 				    &fops_total_ps_duration);
887*710a95f9SVenkateswara Naralasetty 	}
888d5c65159SKalle Valo }
889