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