xref: /linux/drivers/net/wireless/ath/ath10k/debugfs_sta.c (revision ee0e5ce2790c5be14ea3d422cac323e059a43792)
1 // SPDX-License-Identifier: ISC
2 /*
3  * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
4  * Copyright (c) 2018, The Linux Foundation. All rights reserved.
5  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
6  * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
7  */
8 
9 #include "core.h"
10 #include "wmi-ops.h"
11 #include "txrx.h"
12 #include "debug.h"
13 
14 static void ath10k_rx_stats_update_amsdu_subfrm(struct ath10k *ar,
15 						struct ath10k_sta_tid_stats *stats,
16 						u32 msdu_count)
17 {
18 	if (msdu_count == 1)
19 		stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_1]++;
20 	else if (msdu_count == 2)
21 		stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_2]++;
22 	else if (msdu_count == 3)
23 		stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_3]++;
24 	else if (msdu_count == 4)
25 		stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_4]++;
26 	else if (msdu_count > 4)
27 		stats->rx_pkt_amsdu[ATH10K_AMSDU_SUBFRM_NUM_MORE]++;
28 }
29 
30 static void ath10k_rx_stats_update_ampdu_subfrm(struct ath10k *ar,
31 						struct ath10k_sta_tid_stats *stats,
32 						u32 mpdu_count)
33 {
34 	if (mpdu_count <= 10)
35 		stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_10]++;
36 	else if (mpdu_count <= 20)
37 		stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_20]++;
38 	else if (mpdu_count <= 30)
39 		stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_30]++;
40 	else if (mpdu_count <= 40)
41 		stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_40]++;
42 	else if (mpdu_count <= 50)
43 		stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_50]++;
44 	else if (mpdu_count <= 60)
45 		stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_60]++;
46 	else if (mpdu_count > 60)
47 		stats->rx_pkt_ampdu[ATH10K_AMPDU_SUBFRM_NUM_MORE]++;
48 }
49 
50 void ath10k_sta_update_rx_tid_stats_ampdu(struct ath10k *ar, u16 peer_id, u8 tid,
51 					  struct htt_rx_indication_mpdu_range *ranges,
52 					  int num_ranges)
53 {
54 	struct ath10k_sta *arsta;
55 	struct ath10k_peer *peer;
56 	int i;
57 
58 	if (tid > IEEE80211_NUM_TIDS || !(ar->sta_tid_stats_mask & BIT(tid)))
59 		return;
60 
61 	rcu_read_lock();
62 	spin_lock_bh(&ar->data_lock);
63 
64 	peer = ath10k_peer_find_by_id(ar, peer_id);
65 	if (!peer || !peer->sta)
66 		goto out;
67 
68 	arsta = (struct ath10k_sta *)peer->sta->drv_priv;
69 
70 	for (i = 0; i < num_ranges; i++)
71 		ath10k_rx_stats_update_ampdu_subfrm(ar,
72 						    &arsta->tid_stats[tid],
73 						    ranges[i].mpdu_count);
74 
75 out:
76 	spin_unlock_bh(&ar->data_lock);
77 	rcu_read_unlock();
78 }
79 
80 void ath10k_sta_update_rx_tid_stats(struct ath10k *ar, u8 *first_hdr,
81 				    unsigned long num_msdus,
82 				    enum ath10k_pkt_rx_err err,
83 				    unsigned long unchain_cnt,
84 				    unsigned long drop_cnt,
85 				    unsigned long drop_cnt_filter,
86 				    unsigned long queued_msdus)
87 {
88 	struct ieee80211_sta *sta;
89 	struct ath10k_sta *arsta;
90 	struct ieee80211_hdr *hdr;
91 	struct ath10k_sta_tid_stats *stats;
92 	u8 tid = IEEE80211_NUM_TIDS;
93 	bool non_data_frm = false;
94 
95 	hdr = (struct ieee80211_hdr *)first_hdr;
96 	if (!ieee80211_is_data(hdr->frame_control))
97 		non_data_frm = true;
98 
99 	if (ieee80211_is_data_qos(hdr->frame_control))
100 		tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
101 
102 	if (!(ar->sta_tid_stats_mask & BIT(tid)) || non_data_frm)
103 		return;
104 
105 	rcu_read_lock();
106 
107 	sta = ieee80211_find_sta_by_ifaddr(ar->hw, hdr->addr2, NULL);
108 	if (!sta)
109 		goto exit;
110 
111 	arsta = (struct ath10k_sta *)sta->drv_priv;
112 
113 	spin_lock_bh(&ar->data_lock);
114 	stats = &arsta->tid_stats[tid];
115 	stats->rx_pkt_from_fw += num_msdus;
116 	stats->rx_pkt_unchained += unchain_cnt;
117 	stats->rx_pkt_drop_chained += drop_cnt;
118 	stats->rx_pkt_drop_filter += drop_cnt_filter;
119 	if (err != ATH10K_PKT_RX_ERR_MAX)
120 		stats->rx_pkt_err[err] += queued_msdus;
121 	stats->rx_pkt_queued_for_mac += queued_msdus;
122 	ath10k_rx_stats_update_amsdu_subfrm(ar, &arsta->tid_stats[tid],
123 					    num_msdus);
124 	spin_unlock_bh(&ar->data_lock);
125 
126 exit:
127 	rcu_read_unlock();
128 }
129 
130 static void ath10k_sta_update_extd_stats_rx_duration(struct ath10k *ar,
131 						     struct ath10k_fw_stats *stats)
132 {
133 	struct ath10k_fw_extd_stats_peer *peer;
134 	struct ieee80211_sta *sta;
135 	struct ath10k_sta *arsta;
136 
137 	rcu_read_lock();
138 	list_for_each_entry(peer, &stats->peers_extd, list) {
139 		sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
140 						   NULL);
141 		if (!sta)
142 			continue;
143 		arsta = (struct ath10k_sta *)sta->drv_priv;
144 		arsta->rx_duration += (u64)peer->rx_duration;
145 	}
146 	rcu_read_unlock();
147 }
148 
149 static void ath10k_sta_update_stats_rx_duration(struct ath10k *ar,
150 						struct ath10k_fw_stats *stats)
151 {
152 	struct ath10k_fw_stats_peer *peer;
153 	struct ieee80211_sta *sta;
154 	struct ath10k_sta *arsta;
155 
156 	rcu_read_lock();
157 	list_for_each_entry(peer, &stats->peers, list) {
158 		sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
159 						   NULL);
160 		if (!sta)
161 			continue;
162 		arsta = (struct ath10k_sta *)sta->drv_priv;
163 		arsta->rx_duration += (u64)peer->rx_duration;
164 	}
165 	rcu_read_unlock();
166 }
167 
168 void ath10k_sta_update_rx_duration(struct ath10k *ar,
169 				   struct ath10k_fw_stats *stats)
170 {
171 	if (stats->extended)
172 		ath10k_sta_update_extd_stats_rx_duration(ar, stats);
173 	else
174 		ath10k_sta_update_stats_rx_duration(ar, stats);
175 }
176 
177 static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
178 					     char __user *user_buf,
179 					     size_t count, loff_t *ppos)
180 {
181 	struct ieee80211_sta *sta = file->private_data;
182 	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
183 	struct ath10k *ar = arsta->arvif->ar;
184 	char buf[32];
185 	int len = 0;
186 
187 	mutex_lock(&ar->conf_mutex);
188 	len = scnprintf(buf, sizeof(buf) - len, "aggregation mode: %s\n",
189 			(arsta->aggr_mode == ATH10K_DBG_AGGR_MODE_AUTO) ?
190 			"auto" : "manual");
191 	mutex_unlock(&ar->conf_mutex);
192 
193 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
194 }
195 
196 static ssize_t ath10k_dbg_sta_write_aggr_mode(struct file *file,
197 					      const char __user *user_buf,
198 					      size_t count, loff_t *ppos)
199 {
200 	struct ieee80211_sta *sta = file->private_data;
201 	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
202 	struct ath10k *ar = arsta->arvif->ar;
203 	u32 aggr_mode;
204 	int ret;
205 
206 	if (kstrtouint_from_user(user_buf, count, 0, &aggr_mode))
207 		return -EINVAL;
208 
209 	if (aggr_mode >= ATH10K_DBG_AGGR_MODE_MAX)
210 		return -EINVAL;
211 
212 	mutex_lock(&ar->conf_mutex);
213 	if ((ar->state != ATH10K_STATE_ON) ||
214 	    (aggr_mode == arsta->aggr_mode)) {
215 		ret = count;
216 		goto out;
217 	}
218 
219 	ret = ath10k_wmi_addba_clear_resp(ar, arsta->arvif->vdev_id, sta->addr);
220 	if (ret) {
221 		ath10k_warn(ar, "failed to clear addba session ret: %d\n", ret);
222 		goto out;
223 	}
224 
225 	arsta->aggr_mode = aggr_mode;
226 out:
227 	mutex_unlock(&ar->conf_mutex);
228 	return ret;
229 }
230 
231 static const struct file_operations fops_aggr_mode = {
232 	.read = ath10k_dbg_sta_read_aggr_mode,
233 	.write = ath10k_dbg_sta_write_aggr_mode,
234 	.open = simple_open,
235 	.owner = THIS_MODULE,
236 	.llseek = default_llseek,
237 };
238 
239 static ssize_t ath10k_dbg_sta_write_addba(struct file *file,
240 					  const char __user *user_buf,
241 					  size_t count, loff_t *ppos)
242 {
243 	struct ieee80211_sta *sta = file->private_data;
244 	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
245 	struct ath10k *ar = arsta->arvif->ar;
246 	u32 tid, buf_size;
247 	int ret;
248 	char buf[64] = {};
249 
250 	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
251 				     user_buf, count);
252 	if (ret <= 0)
253 		return ret;
254 
255 	ret = sscanf(buf, "%u %u", &tid, &buf_size);
256 	if (ret != 2)
257 		return -EINVAL;
258 
259 	/* Valid TID values are 0 through 15 */
260 	if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
261 		return -EINVAL;
262 
263 	mutex_lock(&ar->conf_mutex);
264 	if ((ar->state != ATH10K_STATE_ON) ||
265 	    (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
266 		ret = count;
267 		goto out;
268 	}
269 
270 	ret = ath10k_wmi_addba_send(ar, arsta->arvif->vdev_id, sta->addr,
271 				    tid, buf_size);
272 	if (ret) {
273 		ath10k_warn(ar, "failed to send addba request: vdev_id %u peer %pM tid %u buf_size %u\n",
274 			    arsta->arvif->vdev_id, sta->addr, tid, buf_size);
275 	}
276 
277 	ret = count;
278 out:
279 	mutex_unlock(&ar->conf_mutex);
280 	return ret;
281 }
282 
283 static const struct file_operations fops_addba = {
284 	.write = ath10k_dbg_sta_write_addba,
285 	.open = simple_open,
286 	.owner = THIS_MODULE,
287 	.llseek = default_llseek,
288 };
289 
290 static ssize_t ath10k_dbg_sta_write_addba_resp(struct file *file,
291 					       const char __user *user_buf,
292 					       size_t count, loff_t *ppos)
293 {
294 	struct ieee80211_sta *sta = file->private_data;
295 	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
296 	struct ath10k *ar = arsta->arvif->ar;
297 	u32 tid, status;
298 	int ret;
299 	char buf[64] = {};
300 
301 	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
302 				     user_buf, count);
303 	if (ret <= 0)
304 		return ret;
305 
306 	ret = sscanf(buf, "%u %u", &tid, &status);
307 	if (ret != 2)
308 		return -EINVAL;
309 
310 	/* Valid TID values are 0 through 15 */
311 	if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
312 		return -EINVAL;
313 
314 	mutex_lock(&ar->conf_mutex);
315 	if ((ar->state != ATH10K_STATE_ON) ||
316 	    (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
317 		ret = count;
318 		goto out;
319 	}
320 
321 	ret = ath10k_wmi_addba_set_resp(ar, arsta->arvif->vdev_id, sta->addr,
322 					tid, status);
323 	if (ret) {
324 		ath10k_warn(ar, "failed to send addba response: vdev_id %u peer %pM tid %u status%u\n",
325 			    arsta->arvif->vdev_id, sta->addr, tid, status);
326 	}
327 	ret = count;
328 out:
329 	mutex_unlock(&ar->conf_mutex);
330 	return ret;
331 }
332 
333 static const struct file_operations fops_addba_resp = {
334 	.write = ath10k_dbg_sta_write_addba_resp,
335 	.open = simple_open,
336 	.owner = THIS_MODULE,
337 	.llseek = default_llseek,
338 };
339 
340 static ssize_t ath10k_dbg_sta_write_delba(struct file *file,
341 					  const char __user *user_buf,
342 					  size_t count, loff_t *ppos)
343 {
344 	struct ieee80211_sta *sta = file->private_data;
345 	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
346 	struct ath10k *ar = arsta->arvif->ar;
347 	u32 tid, initiator, reason;
348 	int ret;
349 	char buf[64] = {};
350 
351 	ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos,
352 				     user_buf, count);
353 	if (ret <= 0)
354 		return ret;
355 
356 	ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason);
357 	if (ret != 3)
358 		return -EINVAL;
359 
360 	/* Valid TID values are 0 through 15 */
361 	if (tid > HTT_DATA_TX_EXT_TID_MGMT - 2)
362 		return -EINVAL;
363 
364 	mutex_lock(&ar->conf_mutex);
365 	if ((ar->state != ATH10K_STATE_ON) ||
366 	    (arsta->aggr_mode != ATH10K_DBG_AGGR_MODE_MANUAL)) {
367 		ret = count;
368 		goto out;
369 	}
370 
371 	ret = ath10k_wmi_delba_send(ar, arsta->arvif->vdev_id, sta->addr,
372 				    tid, initiator, reason);
373 	if (ret) {
374 		ath10k_warn(ar, "failed to send delba: vdev_id %u peer %pM tid %u initiator %u reason %u\n",
375 			    arsta->arvif->vdev_id, sta->addr, tid, initiator,
376 			    reason);
377 	}
378 	ret = count;
379 out:
380 	mutex_unlock(&ar->conf_mutex);
381 	return ret;
382 }
383 
384 static const struct file_operations fops_delba = {
385 	.write = ath10k_dbg_sta_write_delba,
386 	.open = simple_open,
387 	.owner = THIS_MODULE,
388 	.llseek = default_llseek,
389 };
390 
391 static ssize_t ath10k_dbg_sta_read_peer_debug_trigger(struct file *file,
392 						      char __user *user_buf,
393 						      size_t count,
394 						      loff_t *ppos)
395 {
396 	struct ieee80211_sta *sta = file->private_data;
397 	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
398 	struct ath10k *ar = arsta->arvif->ar;
399 	char buf[8];
400 	int len = 0;
401 
402 	mutex_lock(&ar->conf_mutex);
403 	len = scnprintf(buf, sizeof(buf) - len,
404 			"Write 1 to once trigger the debug logs\n");
405 	mutex_unlock(&ar->conf_mutex);
406 
407 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
408 }
409 
410 static ssize_t
411 ath10k_dbg_sta_write_peer_debug_trigger(struct file *file,
412 					const char __user *user_buf,
413 					size_t count, loff_t *ppos)
414 {
415 	struct ieee80211_sta *sta = file->private_data;
416 	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
417 	struct ath10k *ar = arsta->arvif->ar;
418 	u8 peer_debug_trigger;
419 	int ret;
420 
421 	if (kstrtou8_from_user(user_buf, count, 0, &peer_debug_trigger))
422 		return -EINVAL;
423 
424 	if (peer_debug_trigger != 1)
425 		return -EINVAL;
426 
427 	mutex_lock(&ar->conf_mutex);
428 
429 	if (ar->state != ATH10K_STATE_ON) {
430 		ret = -ENETDOWN;
431 		goto out;
432 	}
433 
434 	ret = ath10k_wmi_peer_set_param(ar, arsta->arvif->vdev_id, sta->addr,
435 					ar->wmi.peer_param->debug, peer_debug_trigger);
436 	if (ret) {
437 		ath10k_warn(ar, "failed to set param to trigger peer tid logs for station ret: %d\n",
438 			    ret);
439 		goto out;
440 	}
441 out:
442 	mutex_unlock(&ar->conf_mutex);
443 	return ret ?: count;
444 }
445 
446 static const struct file_operations fops_peer_debug_trigger = {
447 	.open = simple_open,
448 	.read = ath10k_dbg_sta_read_peer_debug_trigger,
449 	.write = ath10k_dbg_sta_write_peer_debug_trigger,
450 	.owner = THIS_MODULE,
451 	.llseek = default_llseek,
452 };
453 
454 static ssize_t ath10k_dbg_sta_read_peer_ps_state(struct file *file,
455 						 char __user *user_buf,
456 						 size_t count, loff_t *ppos)
457 {
458 	struct ieee80211_sta *sta = file->private_data;
459 	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
460 	struct ath10k *ar = arsta->arvif->ar;
461 	char buf[20];
462 	int len = 0;
463 
464 	spin_lock_bh(&ar->data_lock);
465 
466 	len = scnprintf(buf, sizeof(buf) - len, "%d\n",
467 			arsta->peer_ps_state);
468 
469 	spin_unlock_bh(&ar->data_lock);
470 
471 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
472 }
473 
474 static const struct file_operations fops_peer_ps_state = {
475 	.open = simple_open,
476 	.read = ath10k_dbg_sta_read_peer_ps_state,
477 	.owner = THIS_MODULE,
478 	.llseek = default_llseek,
479 };
480 
481 static char *get_err_str(enum ath10k_pkt_rx_err i)
482 {
483 	switch (i) {
484 	case ATH10K_PKT_RX_ERR_FCS:
485 		return "fcs_err";
486 	case ATH10K_PKT_RX_ERR_TKIP:
487 		return "tkip_err";
488 	case ATH10K_PKT_RX_ERR_CRYPT:
489 		return "crypt_err";
490 	case ATH10K_PKT_RX_ERR_PEER_IDX_INVAL:
491 		return "peer_idx_inval";
492 	case ATH10K_PKT_RX_ERR_MAX:
493 		return "unknown";
494 	}
495 
496 	return "unknown";
497 }
498 
499 static char *get_num_ampdu_subfrm_str(enum ath10k_ampdu_subfrm_num i)
500 {
501 	switch (i) {
502 	case ATH10K_AMPDU_SUBFRM_NUM_10:
503 		return "up to 10";
504 	case ATH10K_AMPDU_SUBFRM_NUM_20:
505 		return "11-20";
506 	case ATH10K_AMPDU_SUBFRM_NUM_30:
507 		return "21-30";
508 	case ATH10K_AMPDU_SUBFRM_NUM_40:
509 		return "31-40";
510 	case ATH10K_AMPDU_SUBFRM_NUM_50:
511 		return "41-50";
512 	case ATH10K_AMPDU_SUBFRM_NUM_60:
513 		return "51-60";
514 	case ATH10K_AMPDU_SUBFRM_NUM_MORE:
515 		return ">60";
516 	case ATH10K_AMPDU_SUBFRM_NUM_MAX:
517 		return "0";
518 	}
519 
520 	return "0";
521 }
522 
523 static char *get_num_amsdu_subfrm_str(enum ath10k_amsdu_subfrm_num i)
524 {
525 	switch (i) {
526 	case ATH10K_AMSDU_SUBFRM_NUM_1:
527 		return "1";
528 	case ATH10K_AMSDU_SUBFRM_NUM_2:
529 		return "2";
530 	case ATH10K_AMSDU_SUBFRM_NUM_3:
531 		return "3";
532 	case ATH10K_AMSDU_SUBFRM_NUM_4:
533 		return "4";
534 	case ATH10K_AMSDU_SUBFRM_NUM_MORE:
535 		return ">4";
536 	case ATH10K_AMSDU_SUBFRM_NUM_MAX:
537 		return "0";
538 	}
539 
540 	return "0";
541 }
542 
543 #define PRINT_TID_STATS(_field, _tabs) \
544 	do { \
545 		int k = 0; \
546 		for (j = 0; j <= IEEE80211_NUM_TIDS; j++) { \
547 			if (ar->sta_tid_stats_mask & BIT(j))  { \
548 				len += scnprintf(buf + len, buf_len - len, \
549 						 "[%02d] %-10lu  ", \
550 						 j, stats[j]._field); \
551 				k++; \
552 				if (k % 8 == 0)  { \
553 					len += scnprintf(buf + len, \
554 							 buf_len - len, "\n"); \
555 					len += scnprintf(buf + len, \
556 							 buf_len - len, \
557 							 _tabs); \
558 				} \
559 			} \
560 		} \
561 		len += scnprintf(buf + len, buf_len - len, "\n"); \
562 	} while (0)
563 
564 static ssize_t ath10k_dbg_sta_read_tid_stats(struct file *file,
565 					     char __user *user_buf,
566 					     size_t count, loff_t *ppos)
567 {
568 	struct ieee80211_sta *sta = file->private_data;
569 	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
570 	struct ath10k *ar = arsta->arvif->ar;
571 	struct ath10k_sta_tid_stats *stats = arsta->tid_stats;
572 	size_t len = 0, buf_len = 1048 * IEEE80211_NUM_TIDS;
573 	char *buf;
574 	int i, j;
575 	ssize_t ret;
576 
577 	buf = kzalloc(buf_len, GFP_KERNEL);
578 	if (!buf)
579 		return -ENOMEM;
580 
581 	mutex_lock(&ar->conf_mutex);
582 
583 	spin_lock_bh(&ar->data_lock);
584 
585 	len += scnprintf(buf + len, buf_len - len,
586 			 "\n\t\tDriver Rx pkt stats per tid, ([tid] count)\n");
587 	len += scnprintf(buf + len, buf_len - len,
588 			 "\t\t------------------------------------------\n");
589 	len += scnprintf(buf + len, buf_len - len, "MSDUs from FW\t\t\t");
590 	PRINT_TID_STATS(rx_pkt_from_fw, "\t\t\t\t");
591 
592 	len += scnprintf(buf + len, buf_len - len, "MSDUs unchained\t\t\t");
593 	PRINT_TID_STATS(rx_pkt_unchained, "\t\t\t\t");
594 
595 	len += scnprintf(buf + len, buf_len - len,
596 			 "MSDUs locally dropped:chained\t");
597 	PRINT_TID_STATS(rx_pkt_drop_chained, "\t\t\t\t");
598 
599 	len += scnprintf(buf + len, buf_len - len,
600 			 "MSDUs locally dropped:filtered\t");
601 	PRINT_TID_STATS(rx_pkt_drop_filter, "\t\t\t\t");
602 
603 	len += scnprintf(buf + len, buf_len - len,
604 			 "MSDUs queued for mac80211\t");
605 	PRINT_TID_STATS(rx_pkt_queued_for_mac, "\t\t\t\t");
606 
607 	for (i = 0; i < ATH10K_PKT_RX_ERR_MAX; i++) {
608 		len += scnprintf(buf + len, buf_len - len,
609 				 "MSDUs with error:%s\t", get_err_str(i));
610 		PRINT_TID_STATS(rx_pkt_err[i], "\t\t\t\t");
611 	}
612 
613 	len += scnprintf(buf + len, buf_len - len, "\n");
614 	for (i = 0; i < ATH10K_AMPDU_SUBFRM_NUM_MAX; i++) {
615 		len += scnprintf(buf + len, buf_len - len,
616 				 "A-MPDU num subframes %s\t",
617 				 get_num_ampdu_subfrm_str(i));
618 		PRINT_TID_STATS(rx_pkt_ampdu[i], "\t\t\t\t");
619 	}
620 
621 	len += scnprintf(buf + len, buf_len - len, "\n");
622 	for (i = 0; i < ATH10K_AMSDU_SUBFRM_NUM_MAX; i++) {
623 		len += scnprintf(buf + len, buf_len - len,
624 				 "A-MSDU num subframes %s\t\t",
625 				 get_num_amsdu_subfrm_str(i));
626 		PRINT_TID_STATS(rx_pkt_amsdu[i], "\t\t\t\t");
627 	}
628 
629 	spin_unlock_bh(&ar->data_lock);
630 
631 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
632 
633 	kfree(buf);
634 
635 	mutex_unlock(&ar->conf_mutex);
636 
637 	return ret;
638 }
639 
640 static const struct file_operations fops_tid_stats_dump = {
641 	.open = simple_open,
642 	.read = ath10k_dbg_sta_read_tid_stats,
643 	.owner = THIS_MODULE,
644 	.llseek = default_llseek,
645 };
646 
647 static ssize_t ath10k_dbg_sta_dump_tx_stats(struct file *file,
648 					    char __user *user_buf,
649 					    size_t count, loff_t *ppos)
650 {
651 	struct ieee80211_sta *sta = file->private_data;
652 	struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
653 	struct ath10k *ar = arsta->arvif->ar;
654 	struct ath10k_htt_data_stats *stats;
655 	const char *str_name[ATH10K_STATS_TYPE_MAX] = {"succ", "fail",
656 						       "retry", "ampdu"};
657 	const char *str[ATH10K_COUNTER_TYPE_MAX] = {"bytes", "packets"};
658 	int len = 0, i, j, k, retval = 0;
659 	const int size = 16 * 4096;
660 	char *buf;
661 
662 	buf = kzalloc(size, GFP_KERNEL);
663 	if (!buf)
664 		return -ENOMEM;
665 
666 	mutex_lock(&ar->conf_mutex);
667 
668 	if (!arsta->tx_stats) {
669 		ath10k_warn(ar, "failed to get tx stats");
670 		mutex_unlock(&ar->conf_mutex);
671 		kfree(buf);
672 		return 0;
673 	}
674 
675 	spin_lock_bh(&ar->data_lock);
676 	for (k = 0; k < ATH10K_STATS_TYPE_MAX; k++) {
677 		for (j = 0; j < ATH10K_COUNTER_TYPE_MAX; j++) {
678 			stats = &arsta->tx_stats->stats[k];
679 			len += scnprintf(buf + len, size - len, "%s_%s\n",
680 					 str_name[k],
681 					 str[j]);
682 			len += scnprintf(buf + len, size - len,
683 					 " VHT MCS %s\n",
684 					 str[j]);
685 			for (i = 0; i < ATH10K_VHT_MCS_NUM; i++)
686 				len += scnprintf(buf + len, size - len,
687 						 "  %llu ",
688 						 stats->vht[j][i]);
689 			len += scnprintf(buf + len, size - len, "\n");
690 			len += scnprintf(buf + len, size - len, " HT MCS %s\n",
691 					 str[j]);
692 			for (i = 0; i < ATH10K_HT_MCS_NUM; i++)
693 				len += scnprintf(buf + len, size - len,
694 						 "  %llu ", stats->ht[j][i]);
695 			len += scnprintf(buf + len, size - len, "\n");
696 			len += scnprintf(buf + len, size - len,
697 					" BW %s (20,5,10,40,80,160 MHz)\n", str[j]);
698 			len += scnprintf(buf + len, size - len,
699 					 "  %llu %llu %llu %llu %llu %llu\n",
700 					 stats->bw[j][0], stats->bw[j][1],
701 					 stats->bw[j][2], stats->bw[j][3],
702 					 stats->bw[j][4], stats->bw[j][5]);
703 			len += scnprintf(buf + len, size - len,
704 					 " NSS %s (1x1,2x2,3x3,4x4)\n", str[j]);
705 			len += scnprintf(buf + len, size - len,
706 					 "  %llu %llu %llu %llu\n",
707 					 stats->nss[j][0], stats->nss[j][1],
708 					 stats->nss[j][2], stats->nss[j][3]);
709 			len += scnprintf(buf + len, size - len,
710 					 " GI %s (LGI,SGI)\n",
711 					 str[j]);
712 			len += scnprintf(buf + len, size - len, "  %llu %llu\n",
713 					 stats->gi[j][0], stats->gi[j][1]);
714 			len += scnprintf(buf + len, size - len,
715 					 " legacy rate %s (1,2 ... Mbps)\n  ",
716 					 str[j]);
717 			for (i = 0; i < ATH10K_LEGACY_NUM; i++)
718 				len += scnprintf(buf + len, size - len, "%llu ",
719 						 stats->legacy[j][i]);
720 			len += scnprintf(buf + len, size - len, "\n");
721 			len += scnprintf(buf + len, size - len,
722 					 " Rate table %s (1,2 ... Mbps)\n  ",
723 					 str[j]);
724 			for (i = 0; i < ATH10K_RATE_TABLE_NUM; i++) {
725 				len += scnprintf(buf + len, size - len, "%llu ",
726 						 stats->rate_table[j][i]);
727 				if (!((i + 1) % 8))
728 					len +=
729 					scnprintf(buf + len, size - len, "\n  ");
730 			}
731 		}
732 	}
733 
734 	len += scnprintf(buf + len, size - len,
735 			 "\nTX duration\n %llu usecs\n",
736 			 arsta->tx_stats->tx_duration);
737 	len += scnprintf(buf + len, size - len,
738 			"BA fails\n %llu\n", arsta->tx_stats->ba_fails);
739 	len += scnprintf(buf + len, size - len,
740 			"ack fails\n %llu\n", arsta->tx_stats->ack_fails);
741 	spin_unlock_bh(&ar->data_lock);
742 
743 	if (len > size)
744 		len = size;
745 	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
746 	kfree(buf);
747 
748 	mutex_unlock(&ar->conf_mutex);
749 	return retval;
750 }
751 
752 static const struct file_operations fops_tx_stats = {
753 	.read = ath10k_dbg_sta_dump_tx_stats,
754 	.open = simple_open,
755 	.owner = THIS_MODULE,
756 	.llseek = default_llseek,
757 };
758 
759 void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
760 			    struct ieee80211_sta *sta, struct dentry *dir)
761 {
762 	struct ath10k *ar = hw->priv;
763 
764 	debugfs_create_file("aggr_mode", 0644, dir, sta, &fops_aggr_mode);
765 	debugfs_create_file("addba", 0200, dir, sta, &fops_addba);
766 	debugfs_create_file("addba_resp", 0200, dir, sta, &fops_addba_resp);
767 	debugfs_create_file("delba", 0200, dir, sta, &fops_delba);
768 	debugfs_create_file("peer_debug_trigger", 0600, dir, sta,
769 			    &fops_peer_debug_trigger);
770 	debugfs_create_file("dump_tid_stats", 0400, dir, sta,
771 			    &fops_tid_stats_dump);
772 
773 	if (ath10k_peer_stats_enabled(ar) &&
774 	    ath10k_debug_is_extd_tx_stats_enabled(ar))
775 		debugfs_create_file("tx_stats", 0400, dir, sta,
776 				    &fops_tx_stats);
777 	debugfs_create_file("peer_ps_state", 0400, dir, sta,
778 			    &fops_peer_ps_state);
779 }
780