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