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