xref: /linux/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4  * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
5  */
6 
7 #include <linux/vmalloc.h>
8 #include "core.h"
9 #include "debug.h"
10 #include "debugfs_htt_stats.h"
11 #include "dp_tx.h"
12 #include "dp_rx.h"
13 
14 static u32
15 print_array_to_buf(u8 *buf, u32 offset, const char *header,
16 		   const __le32 *array, u32 array_len, const char *footer)
17 {
18 	int index = 0;
19 	u8 i;
20 
21 	if (header) {
22 		index += scnprintf(buf + offset,
23 				   ATH12K_HTT_STATS_BUF_SIZE - offset,
24 				   "%s = ", header);
25 	}
26 	for (i = 0; i < array_len; i++) {
27 		index += scnprintf(buf + offset + index,
28 				   (ATH12K_HTT_STATS_BUF_SIZE - offset) - index,
29 				   " %u:%u,", i, le32_to_cpu(array[i]));
30 	}
31 	/* To overwrite the last trailing comma */
32 	index--;
33 	*(buf + offset + index) = '\0';
34 
35 	if (footer) {
36 		index += scnprintf(buf + offset + index,
37 				   (ATH12K_HTT_STATS_BUF_SIZE - offset) - index,
38 				   "%s", footer);
39 	}
40 	return index;
41 }
42 
43 static void
44 htt_print_tx_pdev_stats_cmn_tlv(const void *tag_buf, u16 tag_len,
45 				struct debug_htt_stats_req *stats_req)
46 {
47 	const struct ath12k_htt_tx_pdev_stats_cmn_tlv *htt_stats_buf = tag_buf;
48 	u8 *buf = stats_req->buf;
49 	u32 len = stats_req->buf_len;
50 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
51 	u32 mac_id_word;
52 
53 	if (tag_len < sizeof(*htt_stats_buf))
54 		return;
55 
56 	mac_id_word = le32_to_cpu(htt_stats_buf->mac_id__word);
57 
58 	len += scnprintf(buf + len, buf_len - len, "HTT_TX_PDEV_STATS_CMN_TLV:\n");
59 	len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
60 			 u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
61 	len += scnprintf(buf + len, buf_len - len, "comp_delivered = %u\n",
62 			 le32_to_cpu(htt_stats_buf->comp_delivered));
63 	len += scnprintf(buf + len, buf_len - len, "self_triggers = %u\n",
64 			 le32_to_cpu(htt_stats_buf->self_triggers));
65 	len += scnprintf(buf + len, buf_len - len, "hw_queued = %u\n",
66 			 le32_to_cpu(htt_stats_buf->hw_queued));
67 	len += scnprintf(buf + len, buf_len - len, "hw_reaped = %u\n",
68 			 le32_to_cpu(htt_stats_buf->hw_reaped));
69 	len += scnprintf(buf + len, buf_len - len, "underrun = %u\n",
70 			 le32_to_cpu(htt_stats_buf->underrun));
71 	len += scnprintf(buf + len, buf_len - len, "hw_paused = %u\n",
72 			 le32_to_cpu(htt_stats_buf->hw_paused));
73 	len += scnprintf(buf + len, buf_len - len, "hw_flush = %u\n",
74 			 le32_to_cpu(htt_stats_buf->hw_flush));
75 	len += scnprintf(buf + len, buf_len - len, "hw_filt = %u\n",
76 			 le32_to_cpu(htt_stats_buf->hw_filt));
77 	len += scnprintf(buf + len, buf_len - len, "tx_abort = %u\n",
78 			 le32_to_cpu(htt_stats_buf->tx_abort));
79 	len += scnprintf(buf + len, buf_len - len, "ppdu_ok = %u\n",
80 			 le32_to_cpu(htt_stats_buf->ppdu_ok));
81 	len += scnprintf(buf + len, buf_len - len, "mpdu_requeued = %u\n",
82 			 le32_to_cpu(htt_stats_buf->mpdu_requed));
83 	len += scnprintf(buf + len, buf_len - len, "tx_xretry = %u\n",
84 			 le32_to_cpu(htt_stats_buf->tx_xretry));
85 	len += scnprintf(buf + len, buf_len - len, "data_rc = %u\n",
86 			 le32_to_cpu(htt_stats_buf->data_rc));
87 	len += scnprintf(buf + len, buf_len - len, "mpdu_dropped_xretry = %u\n",
88 			 le32_to_cpu(htt_stats_buf->mpdu_dropped_xretry));
89 	len += scnprintf(buf + len, buf_len - len, "illegal_rate_phy_err = %u\n",
90 			 le32_to_cpu(htt_stats_buf->illgl_rate_phy_err));
91 	len += scnprintf(buf + len, buf_len - len, "cont_xretry = %u\n",
92 			 le32_to_cpu(htt_stats_buf->cont_xretry));
93 	len += scnprintf(buf + len, buf_len - len, "tx_timeout = %u\n",
94 			 le32_to_cpu(htt_stats_buf->tx_timeout));
95 	len += scnprintf(buf + len, buf_len - len, "tx_time_dur_data = %u\n",
96 			 le32_to_cpu(htt_stats_buf->tx_time_dur_data));
97 	len += scnprintf(buf + len, buf_len - len, "pdev_resets = %u\n",
98 			 le32_to_cpu(htt_stats_buf->pdev_resets));
99 	len += scnprintf(buf + len, buf_len - len, "phy_underrun = %u\n",
100 			 le32_to_cpu(htt_stats_buf->phy_underrun));
101 	len += scnprintf(buf + len, buf_len - len, "txop_ovf = %u\n",
102 			 le32_to_cpu(htt_stats_buf->txop_ovf));
103 	len += scnprintf(buf + len, buf_len - len, "seq_posted = %u\n",
104 			 le32_to_cpu(htt_stats_buf->seq_posted));
105 	len += scnprintf(buf + len, buf_len - len, "seq_failed_queueing = %u\n",
106 			 le32_to_cpu(htt_stats_buf->seq_failed_queueing));
107 	len += scnprintf(buf + len, buf_len - len, "seq_completed = %u\n",
108 			 le32_to_cpu(htt_stats_buf->seq_completed));
109 	len += scnprintf(buf + len, buf_len - len, "seq_restarted = %u\n",
110 			 le32_to_cpu(htt_stats_buf->seq_restarted));
111 	len += scnprintf(buf + len, buf_len - len, "seq_txop_repost_stop = %u\n",
112 			 le32_to_cpu(htt_stats_buf->seq_txop_repost_stop));
113 	len += scnprintf(buf + len, buf_len - len, "next_seq_cancel = %u\n",
114 			 le32_to_cpu(htt_stats_buf->next_seq_cancel));
115 	len += scnprintf(buf + len, buf_len - len, "dl_mu_mimo_seq_posted = %u\n",
116 			 le32_to_cpu(htt_stats_buf->mu_seq_posted));
117 	len += scnprintf(buf + len, buf_len - len, "dl_mu_ofdma_seq_posted = %u\n",
118 			 le32_to_cpu(htt_stats_buf->mu_ofdma_seq_posted));
119 	len += scnprintf(buf + len, buf_len - len, "ul_mu_mimo_seq_posted = %u\n",
120 			 le32_to_cpu(htt_stats_buf->ul_mumimo_seq_posted));
121 	len += scnprintf(buf + len, buf_len - len, "ul_mu_ofdma_seq_posted = %u\n",
122 			 le32_to_cpu(htt_stats_buf->ul_ofdma_seq_posted));
123 	len += scnprintf(buf + len, buf_len - len, "mu_mimo_peer_blacklisted = %u\n",
124 			 le32_to_cpu(htt_stats_buf->num_mu_peer_blacklisted));
125 	len += scnprintf(buf + len, buf_len - len, "seq_qdepth_repost_stop = %u\n",
126 			 le32_to_cpu(htt_stats_buf->seq_qdepth_repost_stop));
127 	len += scnprintf(buf + len, buf_len - len, "seq_min_msdu_repost_stop = %u\n",
128 			 le32_to_cpu(htt_stats_buf->seq_min_msdu_repost_stop));
129 	len += scnprintf(buf + len, buf_len - len, "mu_seq_min_msdu_repost_stop = %u\n",
130 			 le32_to_cpu(htt_stats_buf->mu_seq_min_msdu_repost_stop));
131 	len += scnprintf(buf + len, buf_len - len, "seq_switch_hw_paused = %u\n",
132 			 le32_to_cpu(htt_stats_buf->seq_switch_hw_paused));
133 	len += scnprintf(buf + len, buf_len - len, "next_seq_posted_dsr = %u\n",
134 			 le32_to_cpu(htt_stats_buf->next_seq_posted_dsr));
135 	len += scnprintf(buf + len, buf_len - len, "seq_posted_isr = %u\n",
136 			 le32_to_cpu(htt_stats_buf->seq_posted_isr));
137 	len += scnprintf(buf + len, buf_len - len, "seq_ctrl_cached = %u\n",
138 			 le32_to_cpu(htt_stats_buf->seq_ctrl_cached));
139 	len += scnprintf(buf + len, buf_len - len, "mpdu_count_tqm = %u\n",
140 			 le32_to_cpu(htt_stats_buf->mpdu_count_tqm));
141 	len += scnprintf(buf + len, buf_len - len, "msdu_count_tqm = %u\n",
142 			 le32_to_cpu(htt_stats_buf->msdu_count_tqm));
143 	len += scnprintf(buf + len, buf_len - len, "mpdu_removed_tqm = %u\n",
144 			 le32_to_cpu(htt_stats_buf->mpdu_removed_tqm));
145 	len += scnprintf(buf + len, buf_len - len, "msdu_removed_tqm = %u\n",
146 			 le32_to_cpu(htt_stats_buf->msdu_removed_tqm));
147 	len += scnprintf(buf + len, buf_len - len, "remove_mpdus_max_retries = %u\n",
148 			 le32_to_cpu(htt_stats_buf->remove_mpdus_max_retries));
149 	len += scnprintf(buf + len, buf_len - len, "mpdus_sw_flush = %u\n",
150 			 le32_to_cpu(htt_stats_buf->mpdus_sw_flush));
151 	len += scnprintf(buf + len, buf_len - len, "mpdus_hw_filter = %u\n",
152 			 le32_to_cpu(htt_stats_buf->mpdus_hw_filter));
153 	len += scnprintf(buf + len, buf_len - len, "mpdus_truncated = %u\n",
154 			 le32_to_cpu(htt_stats_buf->mpdus_truncated));
155 	len += scnprintf(buf + len, buf_len - len, "mpdus_ack_failed = %u\n",
156 			 le32_to_cpu(htt_stats_buf->mpdus_ack_failed));
157 	len += scnprintf(buf + len, buf_len - len, "mpdus_expired = %u\n",
158 			 le32_to_cpu(htt_stats_buf->mpdus_expired));
159 	len += scnprintf(buf + len, buf_len - len, "mpdus_seq_hw_retry = %u\n",
160 			 le32_to_cpu(htt_stats_buf->mpdus_seq_hw_retry));
161 	len += scnprintf(buf + len, buf_len - len, "ack_tlv_proc = %u\n",
162 			 le32_to_cpu(htt_stats_buf->ack_tlv_proc));
163 	len += scnprintf(buf + len, buf_len - len, "coex_abort_mpdu_cnt_valid = %u\n",
164 			 le32_to_cpu(htt_stats_buf->coex_abort_mpdu_cnt_valid));
165 	len += scnprintf(buf + len, buf_len - len, "coex_abort_mpdu_cnt = %u\n",
166 			 le32_to_cpu(htt_stats_buf->coex_abort_mpdu_cnt));
167 	len += scnprintf(buf + len, buf_len - len, "num_total_ppdus_tried_ota = %u\n",
168 			 le32_to_cpu(htt_stats_buf->num_total_ppdus_tried_ota));
169 	len += scnprintf(buf + len, buf_len - len, "num_data_ppdus_tried_ota = %u\n",
170 			 le32_to_cpu(htt_stats_buf->num_data_ppdus_tried_ota));
171 	len += scnprintf(buf + len, buf_len - len, "local_ctrl_mgmt_enqued = %u\n",
172 			 le32_to_cpu(htt_stats_buf->local_ctrl_mgmt_enqued));
173 	len += scnprintf(buf + len, buf_len - len, "local_ctrl_mgmt_freed = %u\n",
174 			 le32_to_cpu(htt_stats_buf->local_ctrl_mgmt_freed));
175 	len += scnprintf(buf + len, buf_len - len, "local_data_enqued = %u\n",
176 			 le32_to_cpu(htt_stats_buf->local_data_enqued));
177 	len += scnprintf(buf + len, buf_len - len, "local_data_freed = %u\n",
178 			 le32_to_cpu(htt_stats_buf->local_data_freed));
179 	len += scnprintf(buf + len, buf_len - len, "mpdu_tried = %u\n",
180 			 le32_to_cpu(htt_stats_buf->mpdu_tried));
181 	len += scnprintf(buf + len, buf_len - len, "isr_wait_seq_posted = %u\n",
182 			 le32_to_cpu(htt_stats_buf->isr_wait_seq_posted));
183 	len += scnprintf(buf + len, buf_len - len, "tx_active_dur_us_low = %u\n",
184 			 le32_to_cpu(htt_stats_buf->tx_active_dur_us_low));
185 	len += scnprintf(buf + len, buf_len - len, "tx_active_dur_us_high = %u\n",
186 			 le32_to_cpu(htt_stats_buf->tx_active_dur_us_high));
187 	len += scnprintf(buf + len, buf_len - len, "fes_offsets_err_cnt = %u\n\n",
188 			 le32_to_cpu(htt_stats_buf->fes_offsets_err_cnt));
189 
190 	stats_req->buf_len = len;
191 }
192 
193 static void
194 htt_print_tx_pdev_stats_urrn_tlv(const void *tag_buf,
195 				 u16 tag_len,
196 				 struct debug_htt_stats_req *stats_req)
197 {
198 	const struct ath12k_htt_tx_pdev_stats_urrn_tlv *htt_stats_buf = tag_buf;
199 	u8 *buf = stats_req->buf;
200 	u32 len = stats_req->buf_len;
201 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
202 	u16 num_elems = min_t(u16, (tag_len >> 2),
203 			      HTT_TX_PDEV_MAX_URRN_STATS);
204 
205 	len += scnprintf(buf + len, buf_len - len,
206 			"HTT_TX_PDEV_STATS_URRN_TLV:\n");
207 
208 	len += print_array_to_buf(buf, len, "urrn_stats", htt_stats_buf->urrn_stats,
209 				  num_elems, "\n\n");
210 
211 	stats_req->buf_len = len;
212 }
213 
214 static void
215 htt_print_tx_pdev_stats_flush_tlv(const void *tag_buf,
216 				  u16 tag_len,
217 				  struct debug_htt_stats_req *stats_req)
218 {
219 	const struct ath12k_htt_tx_pdev_stats_flush_tlv *htt_stats_buf = tag_buf;
220 	u8 *buf = stats_req->buf;
221 	u32 len = stats_req->buf_len;
222 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
223 	u16 num_elems = min_t(u16, (tag_len >> 2),
224 			      ATH12K_HTT_TX_PDEV_MAX_FLUSH_REASON_STATS);
225 
226 	len += scnprintf(buf + len, buf_len - len,
227 			 "HTT_TX_PDEV_STATS_FLUSH_TLV:\n");
228 
229 	len += print_array_to_buf(buf, len, "flush_errs", htt_stats_buf->flush_errs,
230 				  num_elems, "\n\n");
231 
232 	stats_req->buf_len = len;
233 }
234 
235 static void
236 htt_print_tx_pdev_stats_sifs_tlv(const void *tag_buf,
237 				 u16 tag_len,
238 				 struct debug_htt_stats_req *stats_req)
239 {
240 	const struct ath12k_htt_tx_pdev_stats_sifs_tlv *htt_stats_buf = tag_buf;
241 	u8 *buf = stats_req->buf;
242 	u32 len = stats_req->buf_len;
243 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
244 	u16 num_elems = min_t(u16, (tag_len >> 2),
245 			      ATH12K_HTT_TX_PDEV_MAX_SIFS_BURST_STATS);
246 
247 	len += scnprintf(buf + len, buf_len - len,
248 			 "HTT_TX_PDEV_STATS_SIFS_TLV:\n");
249 
250 	len += print_array_to_buf(buf, len, "sifs_status", htt_stats_buf->sifs_status,
251 				  num_elems, "\n\n");
252 
253 	stats_req->buf_len = len;
254 }
255 
256 static void
257 htt_print_tx_pdev_mu_ppdu_dist_stats_tlv(const void *tag_buf, u16 tag_len,
258 					 struct debug_htt_stats_req *stats_req)
259 {
260 	const struct ath12k_htt_tx_pdev_mu_ppdu_dist_stats_tlv *htt_stats_buf = tag_buf;
261 	char *mode;
262 	u8 j, hw_mode, i, str_buf_len;
263 	u8 *buf = stats_req->buf;
264 	u32 len = stats_req->buf_len;
265 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
266 	u32 stats_value;
267 	u8 max_ppdu = ATH12K_HTT_STATS_MAX_NUM_MU_PPDU_PER_BURST;
268 	u8 max_sched = ATH12K_HTT_STATS_MAX_NUM_SCHED_STATUS;
269 	char str_buf[ATH12K_HTT_MAX_STRING_LEN];
270 
271 	if (tag_len < sizeof(*htt_stats_buf))
272 		return;
273 
274 	hw_mode = le32_to_cpu(htt_stats_buf->hw_mode);
275 
276 	switch (hw_mode) {
277 	case ATH12K_HTT_STATS_HWMODE_AC:
278 		len += scnprintf(buf + len, buf_len - len,
279 				 "HTT_TX_PDEV_AC_MU_PPDU_DISTRIBUTION_STATS:\n");
280 		mode = "ac";
281 		break;
282 	case ATH12K_HTT_STATS_HWMODE_AX:
283 		len += scnprintf(buf + len, buf_len - len,
284 				 "HTT_TX_PDEV_AX_MU_PPDU_DISTRIBUTION_STATS:\n");
285 		mode = "ax";
286 		break;
287 	case ATH12K_HTT_STATS_HWMODE_BE:
288 		len += scnprintf(buf + len, buf_len - len,
289 				 "HTT_TX_PDEV_BE_MU_PPDU_DISTRIBUTION_STATS:\n");
290 		mode = "be";
291 		break;
292 	default:
293 		return;
294 	}
295 
296 	for (i = 0; i < ATH12K_HTT_STATS_NUM_NR_BINS ; i++) {
297 		len += scnprintf(buf + len, buf_len - len,
298 				 "%s_mu_mimo_num_seq_posted_nr%u = %u\n", mode,
299 				 ((i + 1) * 4), htt_stats_buf->num_seq_posted[i]);
300 		str_buf_len = 0;
301 		memset(str_buf, 0x0, sizeof(str_buf));
302 		for (j = 0; j < ATH12K_HTT_STATS_MAX_NUM_MU_PPDU_PER_BURST ; j++) {
303 			stats_value = le32_to_cpu(htt_stats_buf->num_ppdu_posted_per_burst
304 						  [i * max_ppdu + j]);
305 			str_buf_len += scnprintf(&str_buf[str_buf_len],
306 						ATH12K_HTT_MAX_STRING_LEN - str_buf_len,
307 						" %u:%u,", j, stats_value);
308 		}
309 		/* To overwrite the last trailing comma */
310 		str_buf[str_buf_len - 1] = '\0';
311 		len += scnprintf(buf + len, buf_len - len,
312 				 "%s_mu_mimo_num_ppdu_posted_per_burst_nr%u = %s\n",
313 				 mode, ((i + 1) * 4), str_buf);
314 		str_buf_len = 0;
315 		memset(str_buf, 0x0, sizeof(str_buf));
316 		for (j = 0; j < ATH12K_HTT_STATS_MAX_NUM_MU_PPDU_PER_BURST ; j++) {
317 			stats_value = le32_to_cpu(htt_stats_buf->num_ppdu_cmpl_per_burst
318 						  [i * max_ppdu + j]);
319 			str_buf_len += scnprintf(&str_buf[str_buf_len],
320 						ATH12K_HTT_MAX_STRING_LEN - str_buf_len,
321 						" %u:%u,", j, stats_value);
322 		}
323 		/* To overwrite the last trailing comma */
324 		str_buf[str_buf_len - 1] = '\0';
325 		len += scnprintf(buf + len, buf_len - len,
326 				 "%s_mu_mimo_num_ppdu_completed_per_burst_nr%u = %s\n",
327 				 mode, ((i + 1) * 4), str_buf);
328 		str_buf_len = 0;
329 		memset(str_buf, 0x0, sizeof(str_buf));
330 		for (j = 0; j < ATH12K_HTT_STATS_MAX_NUM_SCHED_STATUS ; j++) {
331 			stats_value = le32_to_cpu(htt_stats_buf->num_seq_term_status
332 						  [i * max_sched + j]);
333 			str_buf_len += scnprintf(&str_buf[str_buf_len],
334 						ATH12K_HTT_MAX_STRING_LEN - str_buf_len,
335 						" %u:%u,", j, stats_value);
336 		}
337 		/* To overwrite the last trailing comma */
338 		str_buf[str_buf_len - 1] = '\0';
339 		len += scnprintf(buf + len, buf_len - len,
340 				 "%s_mu_mimo_num_seq_term_status_nr%u = %s\n\n",
341 				 mode, ((i + 1) * 4), str_buf);
342 	}
343 
344 	stats_req->buf_len = len;
345 }
346 
347 static void
348 htt_print_tx_pdev_stats_sifs_hist_tlv(const void *tag_buf,
349 				      u16 tag_len,
350 				      struct debug_htt_stats_req *stats_req)
351 {
352 	const struct ath12k_htt_tx_pdev_stats_sifs_hist_tlv *htt_stats_buf = tag_buf;
353 	u8 *buf = stats_req->buf;
354 	u32 len = stats_req->buf_len;
355 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
356 	u16 num_elems = min_t(u16, (tag_len >> 2),
357 			      ATH12K_HTT_TX_PDEV_MAX_SIFS_BURST_HIST_STATS);
358 
359 	len += scnprintf(buf + len, buf_len - len,
360 			 "HTT_TX_PDEV_STATS_SIFS_HIST_TLV:\n");
361 
362 	len += print_array_to_buf(buf, len, "sifs_hist_status",
363 				  htt_stats_buf->sifs_hist_status, num_elems, "\n\n");
364 
365 	stats_req->buf_len = len;
366 }
367 
368 static void
369 htt_print_pdev_ctrl_path_tx_stats_tlv(const void *tag_buf, u16 tag_len,
370 				      struct debug_htt_stats_req *stats_req)
371 {
372 	const struct ath12k_htt_pdev_ctrl_path_tx_stats_tlv *htt_stats_buf = tag_buf;
373 	u8 *buf = stats_req->buf;
374 	u32 len = stats_req->buf_len;
375 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
376 
377 	if (len < sizeof(*htt_stats_buf))
378 		return;
379 
380 	len += scnprintf(buf + len, buf_len - len,
381 			 "HTT_TX_PDEV_STATS_CTRL_PATH_TX_STATS:\n");
382 	len += print_array_to_buf(buf, len, "fw_tx_mgmt_subtype",
383 				 htt_stats_buf->fw_tx_mgmt_subtype,
384 				 ATH12K_HTT_STATS_SUBTYPE_MAX, "\n\n");
385 
386 	stats_req->buf_len = len;
387 }
388 
389 static void
390 ath12k_htt_print_stats_tx_sched_cmn_tlv(const void *tag_buf,
391 					u16 tag_len,
392 					struct debug_htt_stats_req *stats_req)
393 {
394 	const struct ath12k_htt_stats_tx_sched_cmn_tlv *htt_stats_buf = tag_buf;
395 	u8 *buf = stats_req->buf;
396 	u32 len = stats_req->buf_len;
397 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
398 	u32 mac_id_word;
399 
400 	if (tag_len < sizeof(*htt_stats_buf))
401 		return;
402 
403 	mac_id_word = __le32_to_cpu(htt_stats_buf->mac_id__word);
404 
405 	len += scnprintf(buf + len, buf_len - len, "HTT_STATS_TX_SCHED_CMN_TLV:\n");
406 	len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
407 			 u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
408 	len += scnprintf(buf + len, buf_len - len, "current_timestamp = %u\n\n",
409 			 le32_to_cpu(htt_stats_buf->current_timestamp));
410 
411 	stats_req->buf_len = len;
412 }
413 
414 static void
415 ath12k_htt_print_tx_pdev_stats_sched_per_txq_tlv(const void *tag_buf,
416 						 u16 tag_len,
417 						 struct debug_htt_stats_req *stats_req)
418 {
419 	const struct ath12k_htt_tx_pdev_stats_sched_per_txq_tlv *htt_stats_buf = tag_buf;
420 	u8 *buf = stats_req->buf;
421 	u32 len = stats_req->buf_len;
422 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
423 	u32 mac_id_word;
424 
425 	if (tag_len < sizeof(*htt_stats_buf))
426 		return;
427 
428 	mac_id_word = __le32_to_cpu(htt_stats_buf->mac_id__word);
429 
430 	len += scnprintf(buf + len, buf_len - len,
431 			 "HTT_TX_PDEV_STATS_SCHED_PER_TXQ_TLV:\n");
432 	len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
433 			u32_get_bits(mac_id_word,
434 				     ATH12K_HTT_TX_PDEV_STATS_SCHED_PER_TXQ_MAC_ID));
435 	len += scnprintf(buf + len, buf_len - len, "txq_id = %u\n",
436 			 u32_get_bits(mac_id_word,
437 				      ATH12K_HTT_TX_PDEV_STATS_SCHED_PER_TXQ_ID));
438 	len += scnprintf(buf + len, buf_len - len, "sched_policy = %u\n",
439 			 le32_to_cpu(htt_stats_buf->sched_policy));
440 	len += scnprintf(buf + len, buf_len - len,
441 			 "last_sched_cmd_posted_timestamp = %u\n",
442 			 le32_to_cpu(htt_stats_buf->last_sched_cmd_posted_timestamp));
443 	len += scnprintf(buf + len, buf_len - len,
444 			 "last_sched_cmd_compl_timestamp = %u\n",
445 			 le32_to_cpu(htt_stats_buf->last_sched_cmd_compl_timestamp));
446 	len += scnprintf(buf + len, buf_len - len, "sched_2_tac_lwm_count = %u\n",
447 			 le32_to_cpu(htt_stats_buf->sched_2_tac_lwm_count));
448 	len += scnprintf(buf + len, buf_len - len, "sched_2_tac_ring_full = %u\n",
449 			 le32_to_cpu(htt_stats_buf->sched_2_tac_ring_full));
450 	len += scnprintf(buf + len, buf_len - len, "sched_cmd_post_failure = %u\n",
451 			 le32_to_cpu(htt_stats_buf->sched_cmd_post_failure));
452 	len += scnprintf(buf + len, buf_len - len, "num_active_tids = %u\n",
453 			 le32_to_cpu(htt_stats_buf->num_active_tids));
454 	len += scnprintf(buf + len, buf_len - len, "num_ps_schedules = %u\n",
455 			 le32_to_cpu(htt_stats_buf->num_ps_schedules));
456 	len += scnprintf(buf + len, buf_len - len, "sched_cmds_pending = %u\n",
457 			 le32_to_cpu(htt_stats_buf->sched_cmds_pending));
458 	len += scnprintf(buf + len, buf_len - len, "num_tid_register = %u\n",
459 			 le32_to_cpu(htt_stats_buf->num_tid_register));
460 	len += scnprintf(buf + len, buf_len - len, "num_tid_unregister = %u\n",
461 			 le32_to_cpu(htt_stats_buf->num_tid_unregister));
462 	len += scnprintf(buf + len, buf_len - len, "num_qstats_queried = %u\n",
463 			 le32_to_cpu(htt_stats_buf->num_qstats_queried));
464 	len += scnprintf(buf + len, buf_len - len, "qstats_update_pending = %u\n",
465 			 le32_to_cpu(htt_stats_buf->qstats_update_pending));
466 	len += scnprintf(buf + len, buf_len - len, "last_qstats_query_timestamp = %u\n",
467 			 le32_to_cpu(htt_stats_buf->last_qstats_query_timestamp));
468 	len += scnprintf(buf + len, buf_len - len, "num_tqm_cmdq_full = %u\n",
469 			 le32_to_cpu(htt_stats_buf->num_tqm_cmdq_full));
470 	len += scnprintf(buf + len, buf_len - len, "num_de_sched_algo_trigger = %u\n",
471 			 le32_to_cpu(htt_stats_buf->num_de_sched_algo_trigger));
472 	len += scnprintf(buf + len, buf_len - len, "num_rt_sched_algo_trigger = %u\n",
473 			 le32_to_cpu(htt_stats_buf->num_rt_sched_algo_trigger));
474 	len += scnprintf(buf + len, buf_len - len, "num_tqm_sched_algo_trigger = %u\n",
475 			 le32_to_cpu(htt_stats_buf->num_tqm_sched_algo_trigger));
476 	len += scnprintf(buf + len, buf_len - len, "notify_sched = %u\n",
477 			 le32_to_cpu(htt_stats_buf->notify_sched));
478 	len += scnprintf(buf + len, buf_len - len, "dur_based_sendn_term = %u\n",
479 			 le32_to_cpu(htt_stats_buf->dur_based_sendn_term));
480 	len += scnprintf(buf + len, buf_len - len, "su_notify2_sched = %u\n",
481 			 le32_to_cpu(htt_stats_buf->su_notify2_sched));
482 	len += scnprintf(buf + len, buf_len - len, "su_optimal_queued_msdus_sched = %u\n",
483 			 le32_to_cpu(htt_stats_buf->su_optimal_queued_msdus_sched));
484 	len += scnprintf(buf + len, buf_len - len, "su_delay_timeout_sched = %u\n",
485 			 le32_to_cpu(htt_stats_buf->su_delay_timeout_sched));
486 	len += scnprintf(buf + len, buf_len - len, "su_min_txtime_sched_delay = %u\n",
487 			 le32_to_cpu(htt_stats_buf->su_min_txtime_sched_delay));
488 	len += scnprintf(buf + len, buf_len - len, "su_no_delay = %u\n",
489 			 le32_to_cpu(htt_stats_buf->su_no_delay));
490 	len += scnprintf(buf + len, buf_len - len, "num_supercycles = %u\n",
491 			 le32_to_cpu(htt_stats_buf->num_supercycles));
492 	len += scnprintf(buf + len, buf_len - len, "num_subcycles_with_sort = %u\n",
493 			 le32_to_cpu(htt_stats_buf->num_subcycles_with_sort));
494 	len += scnprintf(buf + len, buf_len - len, "num_subcycles_no_sort = %u\n\n",
495 			 le32_to_cpu(htt_stats_buf->num_subcycles_no_sort));
496 
497 	stats_req->buf_len = len;
498 }
499 
500 static void
501 ath12k_htt_print_sched_txq_cmd_posted_tlv(const void *tag_buf,
502 					  u16 tag_len,
503 					  struct debug_htt_stats_req *stats_req)
504 {
505 	const struct ath12k_htt_sched_txq_cmd_posted_tlv *htt_stats_buf = tag_buf;
506 	u8 *buf = stats_req->buf;
507 	u32 len = stats_req->buf_len;
508 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
509 	u16 num_elements = tag_len >> 2;
510 
511 	len += scnprintf(buf + len, buf_len - len, "HTT_SCHED_TXQ_CMD_POSTED_TLV:\n");
512 	len += print_array_to_buf(buf, len, "sched_cmd_posted",
513 				  htt_stats_buf->sched_cmd_posted, num_elements, "\n\n");
514 
515 	stats_req->buf_len = len;
516 }
517 
518 static void
519 ath12k_htt_print_sched_txq_cmd_reaped_tlv(const void *tag_buf,
520 					  u16 tag_len,
521 					  struct debug_htt_stats_req *stats_req)
522 {
523 	const struct ath12k_htt_sched_txq_cmd_reaped_tlv *htt_stats_buf = tag_buf;
524 	u8 *buf = stats_req->buf;
525 	u32 len = stats_req->buf_len;
526 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
527 	u16 num_elements = tag_len >> 2;
528 
529 	len += scnprintf(buf + len, buf_len - len, "HTT_SCHED_TXQ_CMD_REAPED_TLV:\n");
530 	len += print_array_to_buf(buf, len, "sched_cmd_reaped",
531 				  htt_stats_buf->sched_cmd_reaped, num_elements, "\n\n");
532 
533 	stats_req->buf_len = len;
534 }
535 
536 static void
537 ath12k_htt_print_sched_txq_sched_order_su_tlv(const void *tag_buf,
538 					      u16 tag_len,
539 					      struct debug_htt_stats_req *stats_req)
540 {
541 	const struct ath12k_htt_sched_txq_sched_order_su_tlv *htt_stats_buf = tag_buf;
542 	u8 *buf = stats_req->buf;
543 	u32 len = stats_req->buf_len;
544 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
545 	u32 sched_order_su_num_entries = min_t(u32, (tag_len >> 2),
546 					       ATH12K_HTT_TX_PDEV_NUM_SCHED_ORDER_LOG);
547 
548 	len += scnprintf(buf + len, buf_len - len,
549 			 "HTT_SCHED_TXQ_SCHED_ORDER_SU_TLV:\n");
550 	len += print_array_to_buf(buf, len, "sched_order_su",
551 				  htt_stats_buf->sched_order_su,
552 				  sched_order_su_num_entries, "\n\n");
553 
554 	stats_req->buf_len = len;
555 }
556 
557 static void
558 ath12k_htt_print_sched_txq_sched_ineligibility_tlv(const void *tag_buf,
559 						   u16 tag_len,
560 						   struct debug_htt_stats_req *stats_req)
561 {
562 	const struct ath12k_htt_sched_txq_sched_ineligibility_tlv *htt_stats_buf =
563 		     tag_buf;
564 	u8 *buf = stats_req->buf;
565 	u32 len = stats_req->buf_len;
566 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
567 	u32 sched_ineligibility_num_entries = tag_len >> 2;
568 
569 	len += scnprintf(buf + len, buf_len - len,
570 			 "HTT_SCHED_TXQ_SCHED_INELIGIBILITY:\n");
571 	len += print_array_to_buf(buf, len, "sched_ineligibility",
572 				  htt_stats_buf->sched_ineligibility,
573 				  sched_ineligibility_num_entries, "\n\n");
574 
575 	stats_req->buf_len = len;
576 }
577 
578 static void
579 ath12k_htt_print_sched_txq_supercycle_trigger_tlv(const void *tag_buf,
580 						  u16 tag_len,
581 						  struct debug_htt_stats_req *stats_req)
582 {
583 	const struct ath12k_htt_sched_txq_supercycle_triggers_tlv *htt_stats_buf =
584 		     tag_buf;
585 	u8 *buf = stats_req->buf;
586 	u32 len = stats_req->buf_len;
587 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
588 	u16 num_elems = min_t(u16, (tag_len >> 2),
589 			      ATH12K_HTT_SCHED_SUPERCYCLE_TRIGGER_MAX);
590 
591 	len += scnprintf(buf + len, buf_len - len,
592 			 "HTT_SCHED_TXQ_SUPERCYCLE_TRIGGER:\n");
593 	len += print_array_to_buf(buf, len, "supercycle_triggers",
594 				  htt_stats_buf->supercycle_triggers, num_elems, "\n\n");
595 
596 	stats_req->buf_len = len;
597 }
598 
599 static void
600 ath12k_htt_print_hw_stats_pdev_errs_tlv(const void *tag_buf, u16 tag_len,
601 					struct debug_htt_stats_req *stats_req)
602 {
603 	const struct ath12k_htt_hw_stats_pdev_errs_tlv *htt_buf = tag_buf;
604 	u8 *buf = stats_req->buf;
605 	u32 len = stats_req->buf_len;
606 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
607 	u32 mac_id_word;
608 
609 	if (tag_len < sizeof(*htt_buf))
610 		return;
611 
612 	mac_id_word = le32_to_cpu(htt_buf->mac_id__word);
613 
614 	len += scnprintf(buf + len, buf_len - len, "HTT_HW_STATS_PDEV_ERRS_TLV:\n");
615 	len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
616 			 u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
617 	len += scnprintf(buf + len, buf_len - len, "tx_abort = %u\n",
618 			 le32_to_cpu(htt_buf->tx_abort));
619 	len += scnprintf(buf + len, buf_len - len, "tx_abort_fail_count = %u\n",
620 			 le32_to_cpu(htt_buf->tx_abort_fail_count));
621 	len += scnprintf(buf + len, buf_len - len, "rx_abort = %u\n",
622 			 le32_to_cpu(htt_buf->rx_abort));
623 	len += scnprintf(buf + len, buf_len - len, "rx_abort_fail_count = %u\n",
624 			 le32_to_cpu(htt_buf->rx_abort_fail_count));
625 	len += scnprintf(buf + len, buf_len - len, "rx_flush_cnt = %u\n",
626 			 le32_to_cpu(htt_buf->rx_flush_cnt));
627 	len += scnprintf(buf + len, buf_len - len, "warm_reset = %u\n",
628 			 le32_to_cpu(htt_buf->warm_reset));
629 	len += scnprintf(buf + len, buf_len - len, "cold_reset = %u\n",
630 			 le32_to_cpu(htt_buf->cold_reset));
631 	len += scnprintf(buf + len, buf_len - len, "mac_cold_reset_restore_cal = %u\n",
632 			 le32_to_cpu(htt_buf->mac_cold_reset_restore_cal));
633 	len += scnprintf(buf + len, buf_len - len, "mac_cold_reset = %u\n",
634 			 le32_to_cpu(htt_buf->mac_cold_reset));
635 	len += scnprintf(buf + len, buf_len - len, "mac_warm_reset = %u\n",
636 			 le32_to_cpu(htt_buf->mac_warm_reset));
637 	len += scnprintf(buf + len, buf_len - len, "mac_only_reset = %u\n",
638 			 le32_to_cpu(htt_buf->mac_only_reset));
639 	len += scnprintf(buf + len, buf_len - len, "phy_warm_reset = %u\n",
640 			 le32_to_cpu(htt_buf->phy_warm_reset));
641 	len += scnprintf(buf + len, buf_len - len, "phy_warm_reset_ucode_trig = %u\n",
642 			 le32_to_cpu(htt_buf->phy_warm_reset_ucode_trig));
643 	len += scnprintf(buf + len, buf_len - len, "mac_warm_reset_restore_cal = %u\n",
644 			 le32_to_cpu(htt_buf->mac_warm_reset_restore_cal));
645 	len += scnprintf(buf + len, buf_len - len, "mac_sfm_reset = %u\n",
646 			 le32_to_cpu(htt_buf->mac_sfm_reset));
647 	len += scnprintf(buf + len, buf_len - len, "phy_warm_reset_m3_ssr = %u\n",
648 			 le32_to_cpu(htt_buf->phy_warm_reset_m3_ssr));
649 	len += scnprintf(buf + len, buf_len - len, "fw_rx_rings_reset = %u\n",
650 			 le32_to_cpu(htt_buf->fw_rx_rings_reset));
651 	len += scnprintf(buf + len, buf_len - len, "tx_flush = %u\n",
652 			 le32_to_cpu(htt_buf->tx_flush));
653 	len += scnprintf(buf + len, buf_len - len, "tx_glb_reset = %u\n",
654 			 le32_to_cpu(htt_buf->tx_glb_reset));
655 	len += scnprintf(buf + len, buf_len - len, "tx_txq_reset = %u\n",
656 			 le32_to_cpu(htt_buf->tx_txq_reset));
657 	len += scnprintf(buf + len, buf_len - len, "rx_timeout_reset = %u\n\n",
658 			 le32_to_cpu(htt_buf->rx_timeout_reset));
659 
660 	len += scnprintf(buf + len, buf_len - len, "PDEV_PHY_WARM_RESET_REASONS:\n");
661 	len += scnprintf(buf + len, buf_len - len, "phy_warm_reset_reason_phy_m3 = %u\n",
662 			 le32_to_cpu(htt_buf->phy_warm_reset_reason_phy_m3));
663 	len += scnprintf(buf + len, buf_len - len,
664 			 "phy_warm_reset_reason_tx_hw_stuck = %u\n",
665 			 le32_to_cpu(htt_buf->phy_warm_reset_reason_tx_hw_stuck));
666 	len += scnprintf(buf + len, buf_len - len,
667 			 "phy_warm_reset_reason_num_cca_rx_frame_stuck = %u\n",
668 			 le32_to_cpu(htt_buf->phy_warm_reset_reason_num_rx_frame_stuck));
669 	len += scnprintf(buf + len, buf_len - len,
670 			 "phy_warm_reset_reason_wal_rx_recovery_rst_rx_busy = %u\n",
671 			 le32_to_cpu(htt_buf->phy_warm_reset_reason_wal_rx_rec_rx_busy));
672 	len += scnprintf(buf + len, buf_len - len,
673 			 "phy_warm_reset_reason_wal_rx_recovery_rst_mac_hang = %u\n",
674 			 le32_to_cpu(htt_buf->phy_warm_reset_reason_wal_rx_rec_mac_hng));
675 	len += scnprintf(buf + len, buf_len - len,
676 			 "phy_warm_reset_reason_mac_reset_converted_phy_reset = %u\n",
677 			 le32_to_cpu(htt_buf->phy_warm_reset_reason_mac_conv_phy_reset));
678 	len += scnprintf(buf + len, buf_len - len,
679 			 "phy_warm_reset_reason_tx_lifetime_expiry_cca_stuck = %u\n",
680 			 le32_to_cpu(htt_buf->phy_warm_reset_reason_tx_exp_cca_stuck));
681 	len += scnprintf(buf + len, buf_len - len,
682 			 "phy_warm_reset_reason_tx_consecutive_flush9_war = %u\n",
683 			 le32_to_cpu(htt_buf->phy_warm_reset_reason_tx_consec_flsh_war));
684 	len += scnprintf(buf + len, buf_len - len,
685 			 "phy_warm_reset_reason_tx_hwsch_reset_war = %u\n",
686 			 le32_to_cpu(htt_buf->phy_warm_reset_reason_tx_hwsch_reset_war));
687 	len += scnprintf(buf + len, buf_len - len,
688 			 "phy_warm_reset_reason_hwsch_wdog_or_cca_wdog_war = %u\n\n",
689 			 le32_to_cpu(htt_buf->phy_warm_reset_reason_hwsch_cca_wdog_war));
690 
691 	len += scnprintf(buf + len, buf_len - len, "WAL_RX_RECOVERY_STATS:\n");
692 	len += scnprintf(buf + len, buf_len - len,
693 			 "wal_rx_recovery_rst_mac_hang_count = %u\n",
694 			 le32_to_cpu(htt_buf->wal_rx_recovery_rst_mac_hang_cnt));
695 	len += scnprintf(buf + len, buf_len - len,
696 			 "wal_rx_recovery_rst_known_sig_count = %u\n",
697 			 le32_to_cpu(htt_buf->wal_rx_recovery_rst_known_sig_cnt));
698 	len += scnprintf(buf + len, buf_len - len,
699 			 "wal_rx_recovery_rst_no_rx_count = %u\n",
700 			 le32_to_cpu(htt_buf->wal_rx_recovery_rst_no_rx_cnt));
701 	len += scnprintf(buf + len, buf_len - len,
702 			 "wal_rx_recovery_rst_no_rx_consecutive_count = %u\n",
703 			 le32_to_cpu(htt_buf->wal_rx_recovery_rst_no_rx_consec_cnt));
704 	len += scnprintf(buf + len, buf_len - len,
705 			 "wal_rx_recovery_rst_rx_busy_count = %u\n",
706 			 le32_to_cpu(htt_buf->wal_rx_recovery_rst_rx_busy_cnt));
707 	len += scnprintf(buf + len, buf_len - len,
708 			 "wal_rx_recovery_rst_phy_mac_hang_count = %u\n\n",
709 			 le32_to_cpu(htt_buf->wal_rx_recovery_rst_phy_mac_hang_cnt));
710 
711 	len += scnprintf(buf + len, buf_len - len, "HTT_RX_DEST_DRAIN_STATS:\n");
712 	len += scnprintf(buf + len, buf_len - len,
713 			 "rx_dest_drain_rx_descs_leak_prevention_done = %u\n",
714 			 le32_to_cpu(htt_buf->rx_dest_drain_rx_descs_leak_prevented));
715 	len += scnprintf(buf + len, buf_len - len,
716 			 "rx_dest_drain_rx_descs_saved_cnt = %u\n",
717 			 le32_to_cpu(htt_buf->rx_dest_drain_rx_descs_saved_cnt));
718 	len += scnprintf(buf + len, buf_len - len,
719 			 "rx_dest_drain_rxdma2reo_leak_detected = %u\n",
720 			 le32_to_cpu(htt_buf->rx_dest_drain_rxdma2reo_leak_detected));
721 	len += scnprintf(buf + len, buf_len - len,
722 			 "rx_dest_drain_rxdma2fw_leak_detected = %u\n",
723 			 le32_to_cpu(htt_buf->rx_dest_drain_rxdma2fw_leak_detected));
724 	len += scnprintf(buf + len, buf_len - len,
725 			 "rx_dest_drain_rxdma2wbm_leak_detected = %u\n",
726 			 le32_to_cpu(htt_buf->rx_dest_drain_rxdma2wbm_leak_detected));
727 	len += scnprintf(buf + len, buf_len - len,
728 			 "rx_dest_drain_rxdma1_2sw_leak_detected = %u\n",
729 			 le32_to_cpu(htt_buf->rx_dest_drain_rxdma1_2sw_leak_detected));
730 	len += scnprintf(buf + len, buf_len - len,
731 			 "rx_dest_drain_rx_drain_ok_mac_idle = %u\n",
732 			 le32_to_cpu(htt_buf->rx_dest_drain_rx_drain_ok_mac_idle));
733 	len += scnprintf(buf + len, buf_len - len,
734 			 "rx_dest_drain_ok_mac_not_idle = %u\n",
735 			 le32_to_cpu(htt_buf->rx_dest_drain_ok_mac_not_idle));
736 	len += scnprintf(buf + len, buf_len - len,
737 			 "rx_dest_drain_prerequisite_invld = %u\n",
738 			 le32_to_cpu(htt_buf->rx_dest_drain_prerequisite_invld));
739 	len += scnprintf(buf + len, buf_len - len,
740 			 "rx_dest_drain_skip_for_non_lmac_reset = %u\n",
741 			 le32_to_cpu(htt_buf->rx_dest_drain_skip_non_lmac_reset));
742 	len += scnprintf(buf + len, buf_len - len,
743 			 "rx_dest_drain_hw_fifo_not_empty_post_drain_wait = %u\n\n",
744 			 le32_to_cpu(htt_buf->rx_dest_drain_hw_fifo_notempty_post_wait));
745 
746 	stats_req->buf_len = len;
747 }
748 
749 static void
750 ath12k_htt_print_hw_stats_intr_misc_tlv(const void *tag_buf, u16 tag_len,
751 					struct debug_htt_stats_req *stats_req)
752 {
753 	const struct ath12k_htt_hw_stats_intr_misc_tlv *htt_stats_buf = tag_buf;
754 	u8 *buf = stats_req->buf;
755 	u32 len = stats_req->buf_len;
756 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
757 
758 	if (tag_len < sizeof(*htt_stats_buf))
759 		return;
760 
761 	len += scnprintf(buf + len, buf_len - len, "HTT_HW_STATS_INTR_MISC_TLV:\n");
762 	len += scnprintf(buf + len, buf_len - len, "hw_intr_name = %s\n",
763 			 htt_stats_buf->hw_intr_name);
764 	len += scnprintf(buf + len, buf_len - len, "mask = %u\n",
765 			 le32_to_cpu(htt_stats_buf->mask));
766 	len += scnprintf(buf + len, buf_len - len, "count = %u\n\n",
767 			 le32_to_cpu(htt_stats_buf->count));
768 
769 	stats_req->buf_len = len;
770 }
771 
772 static void
773 ath12k_htt_print_hw_stats_whal_tx_tlv(const void *tag_buf, u16 tag_len,
774 				      struct debug_htt_stats_req *stats_req)
775 {
776 	const struct ath12k_htt_hw_stats_whal_tx_tlv *htt_stats_buf = tag_buf;
777 	u8 *buf = stats_req->buf;
778 	u32 len = stats_req->buf_len;
779 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
780 	u32 mac_id_word;
781 
782 	if (tag_len < sizeof(*htt_stats_buf))
783 		return;
784 
785 	mac_id_word = __le32_to_cpu(htt_stats_buf->mac_id__word);
786 
787 	len += scnprintf(buf + len, buf_len - len, "HTT_HW_STATS_WHAL_TX_TLV:\n");
788 	len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
789 			 u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
790 	len += scnprintf(buf + len, buf_len - len, "last_unpause_ppdu_id = %u\n",
791 			 le32_to_cpu(htt_stats_buf->last_unpause_ppdu_id));
792 	len += scnprintf(buf + len, buf_len - len, "hwsch_unpause_wait_tqm_write = %u\n",
793 			 le32_to_cpu(htt_stats_buf->hwsch_unpause_wait_tqm_write));
794 	len += scnprintf(buf + len, buf_len - len, "hwsch_dummy_tlv_skipped = %u\n",
795 			 le32_to_cpu(htt_stats_buf->hwsch_dummy_tlv_skipped));
796 	len += scnprintf(buf + len, buf_len - len,
797 			 "hwsch_misaligned_offset_received = %u\n",
798 			 le32_to_cpu(htt_stats_buf->hwsch_misaligned_offset_received));
799 	len += scnprintf(buf + len, buf_len - len, "hwsch_reset_count = %u\n",
800 			 le32_to_cpu(htt_stats_buf->hwsch_reset_count));
801 	len += scnprintf(buf + len, buf_len - len, "hwsch_dev_reset_war = %u\n",
802 			 le32_to_cpu(htt_stats_buf->hwsch_dev_reset_war));
803 	len += scnprintf(buf + len, buf_len - len, "hwsch_delayed_pause = %u\n",
804 			 le32_to_cpu(htt_stats_buf->hwsch_delayed_pause));
805 	len += scnprintf(buf + len, buf_len - len, "hwsch_long_delayed_pause = %u\n",
806 			 le32_to_cpu(htt_stats_buf->hwsch_long_delayed_pause));
807 	len += scnprintf(buf + len, buf_len - len, "sch_rx_ppdu_no_response = %u\n",
808 			 le32_to_cpu(htt_stats_buf->sch_rx_ppdu_no_response));
809 	len += scnprintf(buf + len, buf_len - len, "sch_selfgen_response = %u\n",
810 			 le32_to_cpu(htt_stats_buf->sch_selfgen_response));
811 	len += scnprintf(buf + len, buf_len - len, "sch_rx_sifs_resp_trigger= %u\n\n",
812 			 le32_to_cpu(htt_stats_buf->sch_rx_sifs_resp_trigger));
813 
814 	stats_req->buf_len = len;
815 }
816 
817 static void
818 ath12k_htt_print_hw_war_tlv(const void *tag_buf, u16 tag_len,
819 			    struct debug_htt_stats_req *stats_req)
820 {
821 	const struct ath12k_htt_hw_war_stats_tlv *htt_stats_buf = tag_buf;
822 	u8 *buf = stats_req->buf;
823 	u32 len = stats_req->buf_len;
824 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
825 	u16 fixed_len, array_len;
826 	u8 i, array_words;
827 	u32 mac_id;
828 
829 	if (tag_len < sizeof(*htt_stats_buf))
830 		return;
831 
832 	mac_id = __le32_to_cpu(htt_stats_buf->mac_id__word);
833 	fixed_len = sizeof(*htt_stats_buf);
834 	array_len = tag_len - fixed_len;
835 	array_words = array_len >> 2;
836 
837 	len += scnprintf(buf + len, buf_len - len, "HTT_HW_WAR_STATS_TLV:\n");
838 	len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
839 			 u32_get_bits(mac_id, ATH12K_HTT_STATS_MAC_ID));
840 
841 	for (i = 0; i < array_words; i++) {
842 		len += scnprintf(buf + len, buf_len - len, "hw_war %u = %u\n\n",
843 				 i, le32_to_cpu(htt_stats_buf->hw_wars[i]));
844 	}
845 
846 	stats_req->buf_len = len;
847 }
848 
849 static void
850 ath12k_htt_print_tx_tqm_cmn_stats_tlv(const void *tag_buf, u16 tag_len,
851 				      struct debug_htt_stats_req *stats_req)
852 {
853 	const struct ath12k_htt_tx_tqm_cmn_stats_tlv *htt_stats_buf = tag_buf;
854 	u8 *buf = stats_req->buf;
855 	u32 len = stats_req->buf_len;
856 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
857 	u32 mac_id_word;
858 
859 	if (tag_len < sizeof(*htt_stats_buf))
860 		return;
861 
862 	mac_id_word = __le32_to_cpu(htt_stats_buf->mac_id__word);
863 
864 	len += scnprintf(buf + len, buf_len - len, "HTT_TX_TQM_CMN_STATS_TLV:\n");
865 	len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
866 			u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
867 	len += scnprintf(buf + len, buf_len - len, "max_cmdq_id = %u\n",
868 			 le32_to_cpu(htt_stats_buf->max_cmdq_id));
869 	len += scnprintf(buf + len, buf_len - len, "list_mpdu_cnt_hist_intvl = %u\n",
870 			 le32_to_cpu(htt_stats_buf->list_mpdu_cnt_hist_intvl));
871 	len += scnprintf(buf + len, buf_len - len, "add_msdu = %u\n",
872 			 le32_to_cpu(htt_stats_buf->add_msdu));
873 	len += scnprintf(buf + len, buf_len - len, "q_empty = %u\n",
874 			 le32_to_cpu(htt_stats_buf->q_empty));
875 	len += scnprintf(buf + len, buf_len - len, "q_not_empty = %u\n",
876 			 le32_to_cpu(htt_stats_buf->q_not_empty));
877 	len += scnprintf(buf + len, buf_len - len, "drop_notification = %u\n",
878 			 le32_to_cpu(htt_stats_buf->drop_notification));
879 	len += scnprintf(buf + len, buf_len - len, "desc_threshold = %u\n",
880 			 le32_to_cpu(htt_stats_buf->desc_threshold));
881 	len += scnprintf(buf + len, buf_len - len, "hwsch_tqm_invalid_status = %u\n",
882 			 le32_to_cpu(htt_stats_buf->hwsch_tqm_invalid_status));
883 	len += scnprintf(buf + len, buf_len - len, "missed_tqm_gen_mpdus = %u\n",
884 			 le32_to_cpu(htt_stats_buf->missed_tqm_gen_mpdus));
885 	len += scnprintf(buf + len, buf_len - len,
886 			 "total_msduq_timestamp_updates = %u\n",
887 			 le32_to_cpu(htt_stats_buf->msduq_timestamp_updates));
888 	len += scnprintf(buf + len, buf_len - len,
889 			 "total_msduq_timestamp_updates_by_get_mpdu_head_info_cmd = %u\n",
890 			 le32_to_cpu(htt_stats_buf->msduq_updates_mpdu_head_info_cmd));
891 	len += scnprintf(buf + len, buf_len - len,
892 			 "total_msduq_timestamp_updates_by_emp_to_nonemp_status = %u\n",
893 			 le32_to_cpu(htt_stats_buf->msduq_updates_emp_to_nonemp_status));
894 	len += scnprintf(buf + len, buf_len - len,
895 			 "total_get_mpdu_head_info_cmds_by_sched_algo_la_query = %u\n",
896 			 le32_to_cpu(htt_stats_buf->get_mpdu_head_info_cmds_by_query));
897 	len += scnprintf(buf + len, buf_len - len,
898 			 "total_get_mpdu_head_info_cmds_by_tac = %u\n",
899 			 le32_to_cpu(htt_stats_buf->get_mpdu_head_info_cmds_by_tac));
900 	len += scnprintf(buf + len, buf_len - len,
901 			 "total_gen_mpdu_cmds_by_sched_algo_la_query = %u\n",
902 			 le32_to_cpu(htt_stats_buf->gen_mpdu_cmds_by_query));
903 	len += scnprintf(buf + len, buf_len - len, "active_tqm_tids = %u\n",
904 			 le32_to_cpu(htt_stats_buf->tqm_active_tids));
905 	len += scnprintf(buf + len, buf_len - len, "inactive_tqm_tids = %u\n",
906 			 le32_to_cpu(htt_stats_buf->tqm_inactive_tids));
907 	len += scnprintf(buf + len, buf_len - len, "tqm_active_msduq_flows = %u\n",
908 			 le32_to_cpu(htt_stats_buf->tqm_active_msduq_flows));
909 	len += scnprintf(buf + len, buf_len - len, "hi_prio_q_not_empty = %u\n\n",
910 			 le32_to_cpu(htt_stats_buf->high_prio_q_not_empty));
911 
912 	stats_req->buf_len = len;
913 }
914 
915 static void
916 ath12k_htt_print_tx_tqm_error_stats_tlv(const void *tag_buf, u16 tag_len,
917 					struct debug_htt_stats_req *stats_req)
918 {
919 	const struct ath12k_htt_tx_tqm_error_stats_tlv *htt_stats_buf = tag_buf;
920 	u8 *buf = stats_req->buf;
921 	u32 len = stats_req->buf_len;
922 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
923 
924 	if (tag_len < sizeof(*htt_stats_buf))
925 		return;
926 
927 	len += scnprintf(buf + len, buf_len - len, "HTT_TX_TQM_ERROR_STATS_TLV:\n");
928 	len += scnprintf(buf + len, buf_len - len, "q_empty_failure = %u\n",
929 			 le32_to_cpu(htt_stats_buf->q_empty_failure));
930 	len += scnprintf(buf + len, buf_len - len, "q_not_empty_failure = %u\n",
931 			 le32_to_cpu(htt_stats_buf->q_not_empty_failure));
932 	len += scnprintf(buf + len, buf_len - len, "add_msdu_failure = %u\n\n",
933 			 le32_to_cpu(htt_stats_buf->add_msdu_failure));
934 
935 	len += scnprintf(buf + len, buf_len - len, "TQM_ERROR_RESET_STATS:\n");
936 	len += scnprintf(buf + len, buf_len - len, "tqm_cache_ctl_err = %u\n",
937 			 le32_to_cpu(htt_stats_buf->tqm_cache_ctl_err));
938 	len += scnprintf(buf + len, buf_len - len, "tqm_soft_reset = %u\n",
939 			 le32_to_cpu(htt_stats_buf->tqm_soft_reset));
940 	len += scnprintf(buf + len, buf_len - len,
941 			 "tqm_reset_total_num_in_use_link_descs = %u\n",
942 			 le32_to_cpu(htt_stats_buf->tqm_reset_num_in_use_link_descs));
943 	len += scnprintf(buf + len, buf_len - len,
944 			 "tqm_reset_worst_case_num_lost_link_descs = %u\n",
945 			 le32_to_cpu(htt_stats_buf->tqm_reset_num_lost_link_descs));
946 	len += scnprintf(buf + len, buf_len - len,
947 			 "tqm_reset_worst_case_num_lost_host_tx_bufs_count = %u\n",
948 			 le32_to_cpu(htt_stats_buf->tqm_reset_num_lost_host_tx_buf_cnt));
949 	len += scnprintf(buf + len, buf_len - len,
950 			 "tqm_reset_num_in_use_link_descs_internal_tqm = %u\n",
951 			 le32_to_cpu(htt_stats_buf->tqm_reset_num_in_use_internal_tqm));
952 	len += scnprintf(buf + len, buf_len - len,
953 			 "tqm_reset_num_in_use_link_descs_wbm_idle_link_ring = %u\n",
954 			 le32_to_cpu(htt_stats_buf->tqm_reset_num_in_use_idle_link_rng));
955 	len += scnprintf(buf + len, buf_len - len,
956 			 "tqm_reset_time_to_tqm_hang_delta_ms = %u\n",
957 			 le32_to_cpu(htt_stats_buf->tqm_reset_time_to_tqm_hang_delta_ms));
958 	len += scnprintf(buf + len, buf_len - len, "tqm_reset_recovery_time_ms = %u\n",
959 			 le32_to_cpu(htt_stats_buf->tqm_reset_recovery_time_ms));
960 	len += scnprintf(buf + len, buf_len - len, "tqm_reset_num_peers_hdl = %u\n",
961 			 le32_to_cpu(htt_stats_buf->tqm_reset_num_peers_hdl));
962 	len += scnprintf(buf + len, buf_len - len,
963 			 "tqm_reset_cumm_dirty_hw_mpduq_proc_cnt = %u\n",
964 			 le32_to_cpu(htt_stats_buf->tqm_reset_cumm_dirty_hw_mpduq_cnt));
965 	len += scnprintf(buf + len, buf_len - len,
966 			 "tqm_reset_cumm_dirty_hw_msduq_proc = %u\n",
967 			 le32_to_cpu(htt_stats_buf->tqm_reset_cumm_dirty_hw_msduq_proc));
968 	len += scnprintf(buf + len, buf_len - len,
969 			 "tqm_reset_flush_cache_cmd_su_cnt = %u\n",
970 			 le32_to_cpu(htt_stats_buf->tqm_reset_flush_cache_cmd_su_cnt));
971 	len += scnprintf(buf + len, buf_len - len,
972 			 "tqm_reset_flush_cache_cmd_other_cnt = %u\n",
973 			 le32_to_cpu(htt_stats_buf->tqm_reset_flush_cache_cmd_other_cnt));
974 	len += scnprintf(buf + len, buf_len - len,
975 			 "tqm_reset_flush_cache_cmd_trig_type = %u\n",
976 			 le32_to_cpu(htt_stats_buf->tqm_reset_flush_cache_cmd_trig_type));
977 	len += scnprintf(buf + len, buf_len - len,
978 			 "tqm_reset_flush_cache_cmd_trig_cfg = %u\n",
979 			 le32_to_cpu(htt_stats_buf->tqm_reset_flush_cache_cmd_trig_cfg));
980 	len += scnprintf(buf + len, buf_len - len,
981 			 "tqm_reset_flush_cache_cmd_skip_cmd_status_null = %u\n\n",
982 			 le32_to_cpu(htt_stats_buf->tqm_reset_flush_cmd_skp_status_null));
983 
984 	stats_req->buf_len = len;
985 }
986 
987 static void
988 ath12k_htt_print_tx_tqm_gen_mpdu_stats_tlv(const void *tag_buf, u16 tag_len,
989 					   struct debug_htt_stats_req *stats_req)
990 {
991 	const struct ath12k_htt_tx_tqm_gen_mpdu_stats_tlv *htt_stats_buf = tag_buf;
992 	u8 *buf = stats_req->buf;
993 	u32 len = stats_req->buf_len;
994 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
995 	u16 num_elements = tag_len >> 2;
996 
997 	len += scnprintf(buf + len, buf_len - len, "HTT_TX_TQM_GEN_MPDU_STATS_TLV:\n");
998 	len += print_array_to_buf(buf, len, "gen_mpdu_end_reason",
999 				  htt_stats_buf->gen_mpdu_end_reason, num_elements,
1000 				  "\n\n");
1001 
1002 	stats_req->buf_len = len;
1003 }
1004 
1005 static void
1006 ath12k_htt_print_tx_tqm_list_mpdu_stats_tlv(const void *tag_buf, u16 tag_len,
1007 					    struct debug_htt_stats_req *stats_req)
1008 {
1009 	const struct ath12k_htt_tx_tqm_list_mpdu_stats_tlv *htt_stats_buf = tag_buf;
1010 	u8 *buf = stats_req->buf;
1011 	u32 len = stats_req->buf_len;
1012 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
1013 	u16 num_elems = min_t(u16, (tag_len >> 2),
1014 			      ATH12K_HTT_TX_TQM_MAX_LIST_MPDU_END_REASON);
1015 
1016 	len += scnprintf(buf + len, buf_len - len, "HTT_TX_TQM_LIST_MPDU_STATS_TLV:\n");
1017 	len += print_array_to_buf(buf, len, "list_mpdu_end_reason",
1018 				  htt_stats_buf->list_mpdu_end_reason, num_elems, "\n\n");
1019 
1020 	stats_req->buf_len = len;
1021 }
1022 
1023 static void
1024 ath12k_htt_print_tx_tqm_list_mpdu_cnt_tlv(const void *tag_buf, u16 tag_len,
1025 					  struct debug_htt_stats_req *stats_req)
1026 {
1027 	const struct ath12k_htt_tx_tqm_list_mpdu_cnt_tlv *htt_stats_buf = tag_buf;
1028 	u8 *buf = stats_req->buf;
1029 	u32 len = stats_req->buf_len;
1030 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
1031 	u16 num_elems = min_t(u16, (tag_len >> 2),
1032 			      ATH12K_HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS);
1033 
1034 	len += scnprintf(buf + len, buf_len - len, "HTT_TX_TQM_LIST_MPDU_CNT_TLV_V:\n");
1035 	len += print_array_to_buf(buf, len, "list_mpdu_cnt_hist",
1036 				  htt_stats_buf->list_mpdu_cnt_hist, num_elems, "\n\n");
1037 
1038 	stats_req->buf_len = len;
1039 }
1040 
1041 static void
1042 ath12k_htt_print_tx_tqm_pdev_stats_tlv(const void *tag_buf, u16 tag_len,
1043 				       struct debug_htt_stats_req *stats_req)
1044 {
1045 	const struct ath12k_htt_tx_tqm_pdev_stats_tlv *htt_stats_buf = tag_buf;
1046 	u8 *buf = stats_req->buf;
1047 	u32 len = stats_req->buf_len;
1048 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
1049 
1050 	if (tag_len < sizeof(*htt_stats_buf))
1051 		return;
1052 
1053 	len += scnprintf(buf + len, buf_len - len, "HTT_TX_TQM_PDEV_STATS_TLV_V:\n");
1054 	len += scnprintf(buf + len, buf_len - len, "msdu_count = %u\n",
1055 			 le32_to_cpu(htt_stats_buf->msdu_count));
1056 	len += scnprintf(buf + len, buf_len - len, "mpdu_count = %u\n",
1057 			 le32_to_cpu(htt_stats_buf->mpdu_count));
1058 	len += scnprintf(buf + len, buf_len - len, "remove_msdu = %u\n",
1059 			 le32_to_cpu(htt_stats_buf->remove_msdu));
1060 	len += scnprintf(buf + len, buf_len - len, "remove_mpdu = %u\n",
1061 			 le32_to_cpu(htt_stats_buf->remove_mpdu));
1062 	len += scnprintf(buf + len, buf_len - len, "remove_msdu_ttl = %u\n",
1063 			 le32_to_cpu(htt_stats_buf->remove_msdu_ttl));
1064 	len += scnprintf(buf + len, buf_len - len, "send_bar = %u\n",
1065 			 le32_to_cpu(htt_stats_buf->send_bar));
1066 	len += scnprintf(buf + len, buf_len - len, "bar_sync = %u\n",
1067 			 le32_to_cpu(htt_stats_buf->bar_sync));
1068 	len += scnprintf(buf + len, buf_len - len, "notify_mpdu = %u\n",
1069 			 le32_to_cpu(htt_stats_buf->notify_mpdu));
1070 	len += scnprintf(buf + len, buf_len - len, "sync_cmd = %u\n",
1071 			 le32_to_cpu(htt_stats_buf->sync_cmd));
1072 	len += scnprintf(buf + len, buf_len - len, "write_cmd = %u\n",
1073 			 le32_to_cpu(htt_stats_buf->write_cmd));
1074 	len += scnprintf(buf + len, buf_len - len, "hwsch_trigger = %u\n",
1075 			 le32_to_cpu(htt_stats_buf->hwsch_trigger));
1076 	len += scnprintf(buf + len, buf_len - len, "ack_tlv_proc = %u\n",
1077 			 le32_to_cpu(htt_stats_buf->ack_tlv_proc));
1078 	len += scnprintf(buf + len, buf_len - len, "gen_mpdu_cmd = %u\n",
1079 			 le32_to_cpu(htt_stats_buf->gen_mpdu_cmd));
1080 	len += scnprintf(buf + len, buf_len - len, "gen_list_cmd = %u\n",
1081 			 le32_to_cpu(htt_stats_buf->gen_list_cmd));
1082 	len += scnprintf(buf + len, buf_len - len, "remove_mpdu_cmd = %u\n",
1083 			 le32_to_cpu(htt_stats_buf->remove_mpdu_cmd));
1084 	len += scnprintf(buf + len, buf_len - len, "remove_mpdu_tried_cmd = %u\n",
1085 			 le32_to_cpu(htt_stats_buf->remove_mpdu_tried_cmd));
1086 	len += scnprintf(buf + len, buf_len - len, "mpdu_queue_stats_cmd = %u\n",
1087 			 le32_to_cpu(htt_stats_buf->mpdu_queue_stats_cmd));
1088 	len += scnprintf(buf + len, buf_len - len, "mpdu_head_info_cmd = %u\n",
1089 			 le32_to_cpu(htt_stats_buf->mpdu_head_info_cmd));
1090 	len += scnprintf(buf + len, buf_len - len, "msdu_flow_stats_cmd = %u\n",
1091 			 le32_to_cpu(htt_stats_buf->msdu_flow_stats_cmd));
1092 	len += scnprintf(buf + len, buf_len - len, "remove_msdu_cmd = %u\n",
1093 			 le32_to_cpu(htt_stats_buf->remove_msdu_cmd));
1094 	len += scnprintf(buf + len, buf_len - len, "remove_msdu_ttl_cmd = %u\n",
1095 			 le32_to_cpu(htt_stats_buf->remove_msdu_ttl_cmd));
1096 	len += scnprintf(buf + len, buf_len - len, "flush_cache_cmd = %u\n",
1097 			 le32_to_cpu(htt_stats_buf->flush_cache_cmd));
1098 	len += scnprintf(buf + len, buf_len - len, "update_mpduq_cmd = %u\n",
1099 			 le32_to_cpu(htt_stats_buf->update_mpduq_cmd));
1100 	len += scnprintf(buf + len, buf_len - len, "enqueue = %u\n",
1101 			 le32_to_cpu(htt_stats_buf->enqueue));
1102 	len += scnprintf(buf + len, buf_len - len, "enqueue_notify = %u\n",
1103 			 le32_to_cpu(htt_stats_buf->enqueue_notify));
1104 	len += scnprintf(buf + len, buf_len - len, "notify_mpdu_at_head = %u\n",
1105 			 le32_to_cpu(htt_stats_buf->notify_mpdu_at_head));
1106 	len += scnprintf(buf + len, buf_len - len, "notify_mpdu_state_valid = %u\n",
1107 			 le32_to_cpu(htt_stats_buf->notify_mpdu_state_valid));
1108 	len += scnprintf(buf + len, buf_len - len, "sched_udp_notify1 = %u\n",
1109 			 le32_to_cpu(htt_stats_buf->sched_udp_notify1));
1110 	len += scnprintf(buf + len, buf_len - len, "sched_udp_notify2 = %u\n",
1111 			 le32_to_cpu(htt_stats_buf->sched_udp_notify2));
1112 	len += scnprintf(buf + len, buf_len - len, "sched_nonudp_notify1 = %u\n",
1113 			 le32_to_cpu(htt_stats_buf->sched_nonudp_notify1));
1114 	len += scnprintf(buf + len, buf_len - len, "sched_nonudp_notify2 = %u\n\n",
1115 			 le32_to_cpu(htt_stats_buf->sched_nonudp_notify2));
1116 
1117 	stats_req->buf_len = len;
1118 }
1119 
1120 static void
1121 ath12k_htt_print_tx_de_cmn_stats_tlv(const void *tag_buf, u16 tag_len,
1122 				     struct debug_htt_stats_req *stats_req)
1123 {
1124 	const struct ath12k_htt_tx_de_cmn_stats_tlv *htt_stats_buf = tag_buf;
1125 	u8 *buf = stats_req->buf;
1126 	u32 len = stats_req->buf_len;
1127 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
1128 	u32 mac_id_word;
1129 
1130 	if (tag_len < sizeof(*htt_stats_buf))
1131 		return;
1132 
1133 	mac_id_word = __le32_to_cpu(htt_stats_buf->mac_id__word);
1134 
1135 	len += scnprintf(buf + len, buf_len - len, "HTT_TX_DE_CMN_STATS_TLV:\n");
1136 	len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
1137 			 u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
1138 	len += scnprintf(buf + len, buf_len - len, "tcl2fw_entry_count = %u\n",
1139 			 le32_to_cpu(htt_stats_buf->tcl2fw_entry_count));
1140 	len += scnprintf(buf + len, buf_len - len, "not_to_fw = %u\n",
1141 			 le32_to_cpu(htt_stats_buf->not_to_fw));
1142 	len += scnprintf(buf + len, buf_len - len, "invalid_pdev_vdev_peer = %u\n",
1143 			 le32_to_cpu(htt_stats_buf->invalid_pdev_vdev_peer));
1144 	len += scnprintf(buf + len, buf_len - len, "tcl_res_invalid_addrx = %u\n",
1145 			 le32_to_cpu(htt_stats_buf->tcl_res_invalid_addrx));
1146 	len += scnprintf(buf + len, buf_len - len, "wbm2fw_entry_count = %u\n",
1147 			 le32_to_cpu(htt_stats_buf->wbm2fw_entry_count));
1148 	len += scnprintf(buf + len, buf_len - len, "invalid_pdev = %u\n",
1149 			 le32_to_cpu(htt_stats_buf->invalid_pdev));
1150 	len += scnprintf(buf + len, buf_len - len, "tcl_res_addrx_timeout = %u\n",
1151 			 le32_to_cpu(htt_stats_buf->tcl_res_addrx_timeout));
1152 	len += scnprintf(buf + len, buf_len - len, "invalid_vdev = %u\n",
1153 			 le32_to_cpu(htt_stats_buf->invalid_vdev));
1154 	len += scnprintf(buf + len, buf_len - len, "invalid_tcl_exp_frame_desc = %u\n",
1155 			 le32_to_cpu(htt_stats_buf->invalid_tcl_exp_frame_desc));
1156 	len += scnprintf(buf + len, buf_len - len, "vdev_id_mismatch_count = %u\n\n",
1157 			 le32_to_cpu(htt_stats_buf->vdev_id_mismatch_cnt));
1158 
1159 	stats_req->buf_len = len;
1160 }
1161 
1162 static void
1163 ath12k_htt_print_tx_de_eapol_packets_stats_tlv(const void *tag_buf, u16 tag_len,
1164 					       struct debug_htt_stats_req *stats_req)
1165 {
1166 	const struct ath12k_htt_tx_de_eapol_packets_stats_tlv *htt_stats_buf = tag_buf;
1167 	u8 *buf = stats_req->buf;
1168 	u32 len = stats_req->buf_len;
1169 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
1170 
1171 	if (tag_len < sizeof(*htt_stats_buf))
1172 		return;
1173 
1174 	len += scnprintf(buf + len, buf_len - len,
1175 			 "HTT_TX_DE_EAPOL_PACKETS_STATS_TLV:\n");
1176 	len += scnprintf(buf + len, buf_len - len, "m1_packets = %u\n",
1177 			 le32_to_cpu(htt_stats_buf->m1_packets));
1178 	len += scnprintf(buf + len, buf_len - len, "m2_packets = %u\n",
1179 			 le32_to_cpu(htt_stats_buf->m2_packets));
1180 	len += scnprintf(buf + len, buf_len - len, "m3_packets = %u\n",
1181 			 le32_to_cpu(htt_stats_buf->m3_packets));
1182 	len += scnprintf(buf + len, buf_len - len, "m4_packets = %u\n",
1183 			 le32_to_cpu(htt_stats_buf->m4_packets));
1184 	len += scnprintf(buf + len, buf_len - len, "g1_packets = %u\n",
1185 			 le32_to_cpu(htt_stats_buf->g1_packets));
1186 	len += scnprintf(buf + len, buf_len - len, "g2_packets = %u\n",
1187 			 le32_to_cpu(htt_stats_buf->g2_packets));
1188 	len += scnprintf(buf + len, buf_len - len, "rc4_packets = %u\n",
1189 			 le32_to_cpu(htt_stats_buf->rc4_packets));
1190 	len += scnprintf(buf + len, buf_len - len, "eap_packets = %u\n",
1191 			 le32_to_cpu(htt_stats_buf->eap_packets));
1192 	len += scnprintf(buf + len, buf_len - len, "eapol_start_packets = %u\n",
1193 			 le32_to_cpu(htt_stats_buf->eapol_start_packets));
1194 	len += scnprintf(buf + len, buf_len - len, "eapol_logoff_packets = %u\n",
1195 			 le32_to_cpu(htt_stats_buf->eapol_logoff_packets));
1196 	len += scnprintf(buf + len, buf_len - len, "eapol_encap_asf_packets = %u\n\n",
1197 			 le32_to_cpu(htt_stats_buf->eapol_encap_asf_packets));
1198 
1199 	stats_req->buf_len = len;
1200 }
1201 
1202 static void
1203 ath12k_htt_print_tx_de_classify_stats_tlv(const void *tag_buf, u16 tag_len,
1204 					  struct debug_htt_stats_req *stats_req)
1205 {
1206 	const struct ath12k_htt_tx_de_classify_stats_tlv *htt_stats_buf = tag_buf;
1207 	u8 *buf = stats_req->buf;
1208 	u32 len = stats_req->buf_len;
1209 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
1210 
1211 	if (tag_len < sizeof(*htt_stats_buf))
1212 		return;
1213 
1214 	len += scnprintf(buf + len, buf_len - len, "HTT_TX_DE_CLASSIFY_STATS_TLV:\n");
1215 	len += scnprintf(buf + len, buf_len - len, "arp_packets = %u\n",
1216 			 le32_to_cpu(htt_stats_buf->arp_packets));
1217 	len += scnprintf(buf + len, buf_len - len, "igmp_packets = %u\n",
1218 			 le32_to_cpu(htt_stats_buf->igmp_packets));
1219 	len += scnprintf(buf + len, buf_len - len, "dhcp_packets = %u\n",
1220 			 le32_to_cpu(htt_stats_buf->dhcp_packets));
1221 	len += scnprintf(buf + len, buf_len - len, "host_inspected = %u\n",
1222 			 le32_to_cpu(htt_stats_buf->host_inspected));
1223 	len += scnprintf(buf + len, buf_len - len, "htt_included = %u\n",
1224 			 le32_to_cpu(htt_stats_buf->htt_included));
1225 	len += scnprintf(buf + len, buf_len - len, "htt_valid_mcs = %u\n",
1226 			 le32_to_cpu(htt_stats_buf->htt_valid_mcs));
1227 	len += scnprintf(buf + len, buf_len - len, "htt_valid_nss = %u\n",
1228 			 le32_to_cpu(htt_stats_buf->htt_valid_nss));
1229 	len += scnprintf(buf + len, buf_len - len, "htt_valid_preamble_type = %u\n",
1230 			 le32_to_cpu(htt_stats_buf->htt_valid_preamble_type));
1231 	len += scnprintf(buf + len, buf_len - len, "htt_valid_chainmask = %u\n",
1232 			 le32_to_cpu(htt_stats_buf->htt_valid_chainmask));
1233 	len += scnprintf(buf + len, buf_len - len, "htt_valid_guard_interval = %u\n",
1234 			 le32_to_cpu(htt_stats_buf->htt_valid_guard_interval));
1235 	len += scnprintf(buf + len, buf_len - len, "htt_valid_retries = %u\n",
1236 			 le32_to_cpu(htt_stats_buf->htt_valid_retries));
1237 	len += scnprintf(buf + len, buf_len - len, "htt_valid_bw_info = %u\n",
1238 			 le32_to_cpu(htt_stats_buf->htt_valid_bw_info));
1239 	len += scnprintf(buf + len, buf_len - len, "htt_valid_power = %u\n",
1240 			 le32_to_cpu(htt_stats_buf->htt_valid_power));
1241 	len += scnprintf(buf + len, buf_len - len, "htt_valid_key_flags = 0x%x\n",
1242 			 le32_to_cpu(htt_stats_buf->htt_valid_key_flags));
1243 	len += scnprintf(buf + len, buf_len - len, "htt_valid_no_encryption = %u\n",
1244 			 le32_to_cpu(htt_stats_buf->htt_valid_no_encryption));
1245 	len += scnprintf(buf + len, buf_len - len, "fse_entry_count = %u\n",
1246 			 le32_to_cpu(htt_stats_buf->fse_entry_count));
1247 	len += scnprintf(buf + len, buf_len - len, "fse_priority_be = %u\n",
1248 			 le32_to_cpu(htt_stats_buf->fse_priority_be));
1249 	len += scnprintf(buf + len, buf_len - len, "fse_priority_high = %u\n",
1250 			 le32_to_cpu(htt_stats_buf->fse_priority_high));
1251 	len += scnprintf(buf + len, buf_len - len, "fse_priority_low = %u\n",
1252 			 le32_to_cpu(htt_stats_buf->fse_priority_low));
1253 	len += scnprintf(buf + len, buf_len - len, "fse_traffic_ptrn_be = %u\n",
1254 			 le32_to_cpu(htt_stats_buf->fse_traffic_ptrn_be));
1255 	len += scnprintf(buf + len, buf_len - len, "fse_traffic_ptrn_over_sub = %u\n",
1256 			 le32_to_cpu(htt_stats_buf->fse_traffic_ptrn_over_sub));
1257 	len += scnprintf(buf + len, buf_len - len, "fse_traffic_ptrn_bursty = %u\n",
1258 			 le32_to_cpu(htt_stats_buf->fse_traffic_ptrn_bursty));
1259 	len += scnprintf(buf + len, buf_len - len, "fse_traffic_ptrn_interactive = %u\n",
1260 			 le32_to_cpu(htt_stats_buf->fse_traffic_ptrn_interactive));
1261 	len += scnprintf(buf + len, buf_len - len, "fse_traffic_ptrn_periodic = %u\n",
1262 			 le32_to_cpu(htt_stats_buf->fse_traffic_ptrn_periodic));
1263 	len += scnprintf(buf + len, buf_len - len, "fse_hwqueue_alloc = %u\n",
1264 			 le32_to_cpu(htt_stats_buf->fse_hwqueue_alloc));
1265 	len += scnprintf(buf + len, buf_len - len, "fse_hwqueue_created = %u\n",
1266 			 le32_to_cpu(htt_stats_buf->fse_hwqueue_created));
1267 	len += scnprintf(buf + len, buf_len - len, "fse_hwqueue_send_to_host = %u\n",
1268 			 le32_to_cpu(htt_stats_buf->fse_hwqueue_send_to_host));
1269 	len += scnprintf(buf + len, buf_len - len, "mcast_entry = %u\n",
1270 			 le32_to_cpu(htt_stats_buf->mcast_entry));
1271 	len += scnprintf(buf + len, buf_len - len, "bcast_entry = %u\n",
1272 			 le32_to_cpu(htt_stats_buf->bcast_entry));
1273 	len += scnprintf(buf + len, buf_len - len, "htt_update_peer_cache = %u\n",
1274 			 le32_to_cpu(htt_stats_buf->htt_update_peer_cache));
1275 	len += scnprintf(buf + len, buf_len - len, "htt_learning_frame = %u\n",
1276 			 le32_to_cpu(htt_stats_buf->htt_learning_frame));
1277 	len += scnprintf(buf + len, buf_len - len, "fse_invalid_peer = %u\n",
1278 			 le32_to_cpu(htt_stats_buf->fse_invalid_peer));
1279 	len += scnprintf(buf + len, buf_len - len, "mec_notify = %u\n\n",
1280 			 le32_to_cpu(htt_stats_buf->mec_notify));
1281 
1282 	stats_req->buf_len = len;
1283 }
1284 
1285 static void
1286 ath12k_htt_print_tx_de_classify_failed_stats_tlv(const void *tag_buf, u16 tag_len,
1287 						 struct debug_htt_stats_req *stats_req)
1288 {
1289 	const struct ath12k_htt_tx_de_classify_failed_stats_tlv *htt_stats_buf = tag_buf;
1290 	u8 *buf = stats_req->buf;
1291 	u32 len = stats_req->buf_len;
1292 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
1293 
1294 	if (tag_len < sizeof(*htt_stats_buf))
1295 		return;
1296 
1297 	len += scnprintf(buf + len, buf_len - len,
1298 			 "HTT_TX_DE_CLASSIFY_FAILED_STATS_TLV:\n");
1299 	len += scnprintf(buf + len, buf_len - len, "ap_bss_peer_not_found = %u\n",
1300 			 le32_to_cpu(htt_stats_buf->ap_bss_peer_not_found));
1301 	len += scnprintf(buf + len, buf_len - len, "ap_bcast_mcast_no_peer = %u\n",
1302 			 le32_to_cpu(htt_stats_buf->ap_bcast_mcast_no_peer));
1303 	len += scnprintf(buf + len, buf_len - len, "sta_delete_in_progress = %u\n",
1304 			 le32_to_cpu(htt_stats_buf->sta_delete_in_progress));
1305 	len += scnprintf(buf + len, buf_len - len, "ibss_no_bss_peer = %u\n",
1306 			 le32_to_cpu(htt_stats_buf->ibss_no_bss_peer));
1307 	len += scnprintf(buf + len, buf_len - len, "invalid_vdev_type = %u\n",
1308 			 le32_to_cpu(htt_stats_buf->invalid_vdev_type));
1309 	len += scnprintf(buf + len, buf_len - len, "invalid_ast_peer_entry = %u\n",
1310 			 le32_to_cpu(htt_stats_buf->invalid_ast_peer_entry));
1311 	len += scnprintf(buf + len, buf_len - len, "peer_entry_invalid = %u\n",
1312 			 le32_to_cpu(htt_stats_buf->peer_entry_invalid));
1313 	len += scnprintf(buf + len, buf_len - len, "ethertype_not_ip = %u\n",
1314 			 le32_to_cpu(htt_stats_buf->ethertype_not_ip));
1315 	len += scnprintf(buf + len, buf_len - len, "eapol_lookup_failed = %u\n",
1316 			 le32_to_cpu(htt_stats_buf->eapol_lookup_failed));
1317 	len += scnprintf(buf + len, buf_len - len, "qpeer_not_allow_data = %u\n",
1318 			 le32_to_cpu(htt_stats_buf->qpeer_not_allow_data));
1319 	len += scnprintf(buf + len, buf_len - len, "fse_tid_override = %u\n",
1320 			 le32_to_cpu(htt_stats_buf->fse_tid_override));
1321 	len += scnprintf(buf + len, buf_len - len, "ipv6_jumbogram_zero_length = %u\n",
1322 			 le32_to_cpu(htt_stats_buf->ipv6_jumbogram_zero_length));
1323 	len += scnprintf(buf + len, buf_len - len, "qos_to_non_qos_in_prog = %u\n",
1324 			 le32_to_cpu(htt_stats_buf->qos_to_non_qos_in_prog));
1325 	len += scnprintf(buf + len, buf_len - len, "ap_bcast_mcast_eapol = %u\n",
1326 			 le32_to_cpu(htt_stats_buf->ap_bcast_mcast_eapol));
1327 	len += scnprintf(buf + len, buf_len - len, "unicast_on_ap_bss_peer = %u\n",
1328 			 le32_to_cpu(htt_stats_buf->unicast_on_ap_bss_peer));
1329 	len += scnprintf(buf + len, buf_len - len, "ap_vdev_invalid = %u\n",
1330 			 le32_to_cpu(htt_stats_buf->ap_vdev_invalid));
1331 	len += scnprintf(buf + len, buf_len - len, "incomplete_llc = %u\n",
1332 			 le32_to_cpu(htt_stats_buf->incomplete_llc));
1333 	len += scnprintf(buf + len, buf_len - len, "eapol_duplicate_m3 = %u\n",
1334 			 le32_to_cpu(htt_stats_buf->eapol_duplicate_m3));
1335 	len += scnprintf(buf + len, buf_len - len, "eapol_duplicate_m4 = %u\n\n",
1336 			 le32_to_cpu(htt_stats_buf->eapol_duplicate_m4));
1337 
1338 	stats_req->buf_len = len;
1339 }
1340 
1341 static void
1342 ath12k_htt_print_tx_de_classify_status_stats_tlv(const void *tag_buf, u16 tag_len,
1343 						 struct debug_htt_stats_req *stats_req)
1344 {
1345 	const struct ath12k_htt_tx_de_classify_status_stats_tlv *htt_stats_buf = tag_buf;
1346 	u8 *buf = stats_req->buf;
1347 	u32 len = stats_req->buf_len;
1348 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
1349 
1350 	if (tag_len < sizeof(*htt_stats_buf))
1351 		return;
1352 
1353 	len += scnprintf(buf + len, buf_len - len,
1354 			 "HTT_TX_DE_CLASSIFY_STATUS_STATS_TLV:\n");
1355 	len += scnprintf(buf + len, buf_len - len, "eok = %u\n",
1356 			 le32_to_cpu(htt_stats_buf->eok));
1357 	len += scnprintf(buf + len, buf_len - len, "classify_done = %u\n",
1358 			 le32_to_cpu(htt_stats_buf->classify_done));
1359 	len += scnprintf(buf + len, buf_len - len, "lookup_failed = %u\n",
1360 			 le32_to_cpu(htt_stats_buf->lookup_failed));
1361 	len += scnprintf(buf + len, buf_len - len, "send_host_dhcp = %u\n",
1362 			 le32_to_cpu(htt_stats_buf->send_host_dhcp));
1363 	len += scnprintf(buf + len, buf_len - len, "send_host_mcast = %u\n",
1364 			 le32_to_cpu(htt_stats_buf->send_host_mcast));
1365 	len += scnprintf(buf + len, buf_len - len, "send_host_unknown_dest = %u\n",
1366 			 le32_to_cpu(htt_stats_buf->send_host_unknown_dest));
1367 	len += scnprintf(buf + len, buf_len - len, "send_host = %u\n",
1368 			 le32_to_cpu(htt_stats_buf->send_host));
1369 	len += scnprintf(buf + len, buf_len - len, "status_invalid = %u\n\n",
1370 			 le32_to_cpu(htt_stats_buf->status_invalid));
1371 
1372 	stats_req->buf_len = len;
1373 }
1374 
1375 static void
1376 ath12k_htt_print_tx_de_enqueue_packets_stats_tlv(const void *tag_buf, u16 tag_len,
1377 						 struct debug_htt_stats_req *stats_req)
1378 {
1379 	const struct ath12k_htt_tx_de_enqueue_packets_stats_tlv *htt_stats_buf = tag_buf;
1380 	u8 *buf = stats_req->buf;
1381 	u32 len = stats_req->buf_len;
1382 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
1383 
1384 	if (tag_len < sizeof(*htt_stats_buf))
1385 		return;
1386 
1387 	len += scnprintf(buf + len, buf_len - len,
1388 			 "HTT_TX_DE_ENQUEUE_PACKETS_STATS_TLV:\n");
1389 	len += scnprintf(buf + len, buf_len - len, "enqueued_pkts = %u\n",
1390 			 le32_to_cpu(htt_stats_buf->enqueued_pkts));
1391 	len += scnprintf(buf + len, buf_len - len, "to_tqm = %u\n",
1392 			 le32_to_cpu(htt_stats_buf->to_tqm));
1393 	len += scnprintf(buf + len, buf_len - len, "to_tqm_bypass = %u\n\n",
1394 			 le32_to_cpu(htt_stats_buf->to_tqm_bypass));
1395 
1396 	stats_req->buf_len = len;
1397 }
1398 
1399 static void
1400 ath12k_htt_print_tx_de_enqueue_discard_stats_tlv(const void *tag_buf, u16 tag_len,
1401 						 struct debug_htt_stats_req *stats_req)
1402 {
1403 	const struct ath12k_htt_tx_de_enqueue_discard_stats_tlv *htt_stats_buf = tag_buf;
1404 	u8 *buf = stats_req->buf;
1405 	u32 len = stats_req->buf_len;
1406 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
1407 
1408 	if (tag_len < sizeof(*htt_stats_buf))
1409 		return;
1410 
1411 	len += scnprintf(buf + len, buf_len - len,
1412 			 "HTT_TX_DE_ENQUEUE_DISCARD_STATS_TLV:\n");
1413 	len += scnprintf(buf + len, buf_len - len, "discarded_pkts = %u\n",
1414 			 le32_to_cpu(htt_stats_buf->discarded_pkts));
1415 	len += scnprintf(buf + len, buf_len - len, "local_frames = %u\n",
1416 			 le32_to_cpu(htt_stats_buf->local_frames));
1417 	len += scnprintf(buf + len, buf_len - len, "is_ext_msdu = %u\n\n",
1418 			 le32_to_cpu(htt_stats_buf->is_ext_msdu));
1419 
1420 	stats_req->buf_len = len;
1421 }
1422 
1423 static void
1424 ath12k_htt_print_tx_de_compl_stats_tlv(const void *tag_buf, u16 tag_len,
1425 				       struct debug_htt_stats_req *stats_req)
1426 {
1427 	const struct ath12k_htt_tx_de_compl_stats_tlv *htt_stats_buf = tag_buf;
1428 	u8 *buf = stats_req->buf;
1429 	u32 len = stats_req->buf_len;
1430 	u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
1431 
1432 	if (tag_len < sizeof(*htt_stats_buf))
1433 		return;
1434 
1435 	len += scnprintf(buf + len, buf_len - len, "HTT_TX_DE_COMPL_STATS_TLV:\n");
1436 	len += scnprintf(buf + len, buf_len - len, "tcl_dummy_frame = %u\n",
1437 			 le32_to_cpu(htt_stats_buf->tcl_dummy_frame));
1438 	len += scnprintf(buf + len, buf_len - len, "tqm_dummy_frame = %u\n",
1439 			 le32_to_cpu(htt_stats_buf->tqm_dummy_frame));
1440 	len += scnprintf(buf + len, buf_len - len, "tqm_notify_frame = %u\n",
1441 			 le32_to_cpu(htt_stats_buf->tqm_notify_frame));
1442 	len += scnprintf(buf + len, buf_len - len, "fw2wbm_enq = %u\n",
1443 			 le32_to_cpu(htt_stats_buf->fw2wbm_enq));
1444 	len += scnprintf(buf + len, buf_len - len, "tqm_bypass_frame = %u\n\n",
1445 			 le32_to_cpu(htt_stats_buf->tqm_bypass_frame));
1446 
1447 	stats_req->buf_len = len;
1448 }
1449 
1450 static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
1451 					  u16 tag, u16 len, const void *tag_buf,
1452 					  void *user_data)
1453 {
1454 	struct debug_htt_stats_req *stats_req = user_data;
1455 
1456 	switch (tag) {
1457 	case HTT_STATS_TX_PDEV_CMN_TAG:
1458 		htt_print_tx_pdev_stats_cmn_tlv(tag_buf, len, stats_req);
1459 		break;
1460 	case HTT_STATS_TX_PDEV_UNDERRUN_TAG:
1461 		htt_print_tx_pdev_stats_urrn_tlv(tag_buf, len, stats_req);
1462 		break;
1463 	case HTT_STATS_TX_PDEV_SIFS_TAG:
1464 		htt_print_tx_pdev_stats_sifs_tlv(tag_buf, len, stats_req);
1465 		break;
1466 	case HTT_STATS_TX_PDEV_FLUSH_TAG:
1467 		htt_print_tx_pdev_stats_flush_tlv(tag_buf, len, stats_req);
1468 		break;
1469 	case HTT_STATS_TX_PDEV_SIFS_HIST_TAG:
1470 		htt_print_tx_pdev_stats_sifs_hist_tlv(tag_buf, len, stats_req);
1471 		break;
1472 	case HTT_STATS_PDEV_CTRL_PATH_TX_STATS_TAG:
1473 		htt_print_pdev_ctrl_path_tx_stats_tlv(tag_buf, len, stats_req);
1474 		break;
1475 	case HTT_STATS_MU_PPDU_DIST_TAG:
1476 		htt_print_tx_pdev_mu_ppdu_dist_stats_tlv(tag_buf, len, stats_req);
1477 		break;
1478 	case HTT_STATS_TX_SCHED_CMN_TAG:
1479 		ath12k_htt_print_stats_tx_sched_cmn_tlv(tag_buf, len, stats_req);
1480 		break;
1481 	case HTT_STATS_TX_PDEV_SCHEDULER_TXQ_STATS_TAG:
1482 		ath12k_htt_print_tx_pdev_stats_sched_per_txq_tlv(tag_buf, len, stats_req);
1483 		break;
1484 	case HTT_STATS_SCHED_TXQ_CMD_POSTED_TAG:
1485 		ath12k_htt_print_sched_txq_cmd_posted_tlv(tag_buf, len, stats_req);
1486 		break;
1487 	case HTT_STATS_SCHED_TXQ_CMD_REAPED_TAG:
1488 		ath12k_htt_print_sched_txq_cmd_reaped_tlv(tag_buf, len, stats_req);
1489 		break;
1490 	case HTT_STATS_SCHED_TXQ_SCHED_ORDER_SU_TAG:
1491 		ath12k_htt_print_sched_txq_sched_order_su_tlv(tag_buf, len, stats_req);
1492 		break;
1493 	case HTT_STATS_SCHED_TXQ_SCHED_INELIGIBILITY_TAG:
1494 		ath12k_htt_print_sched_txq_sched_ineligibility_tlv(tag_buf, len,
1495 								   stats_req);
1496 		break;
1497 	case HTT_STATS_SCHED_TXQ_SUPERCYCLE_TRIGGER_TAG:
1498 		ath12k_htt_print_sched_txq_supercycle_trigger_tlv(tag_buf, len,
1499 								  stats_req);
1500 		break;
1501 	case HTT_STATS_HW_PDEV_ERRS_TAG:
1502 		ath12k_htt_print_hw_stats_pdev_errs_tlv(tag_buf, len, stats_req);
1503 		break;
1504 	case HTT_STATS_HW_INTR_MISC_TAG:
1505 		ath12k_htt_print_hw_stats_intr_misc_tlv(tag_buf, len, stats_req);
1506 		break;
1507 	case HTT_STATS_WHAL_TX_TAG:
1508 		ath12k_htt_print_hw_stats_whal_tx_tlv(tag_buf, len, stats_req);
1509 		break;
1510 	case HTT_STATS_HW_WAR_TAG:
1511 		ath12k_htt_print_hw_war_tlv(tag_buf, len, stats_req);
1512 		break;
1513 	case HTT_STATS_TX_TQM_CMN_TAG:
1514 		ath12k_htt_print_tx_tqm_cmn_stats_tlv(tag_buf, len, stats_req);
1515 		break;
1516 	case HTT_STATS_TX_TQM_ERROR_STATS_TAG:
1517 		ath12k_htt_print_tx_tqm_error_stats_tlv(tag_buf, len, stats_req);
1518 		break;
1519 	case HTT_STATS_TX_TQM_GEN_MPDU_TAG:
1520 		ath12k_htt_print_tx_tqm_gen_mpdu_stats_tlv(tag_buf, len, stats_req);
1521 		break;
1522 	case HTT_STATS_TX_TQM_LIST_MPDU_TAG:
1523 		ath12k_htt_print_tx_tqm_list_mpdu_stats_tlv(tag_buf, len, stats_req);
1524 		break;
1525 	case HTT_STATS_TX_TQM_LIST_MPDU_CNT_TAG:
1526 		ath12k_htt_print_tx_tqm_list_mpdu_cnt_tlv(tag_buf, len, stats_req);
1527 		break;
1528 	case HTT_STATS_TX_TQM_PDEV_TAG:
1529 		ath12k_htt_print_tx_tqm_pdev_stats_tlv(tag_buf, len, stats_req);
1530 		break;
1531 	case HTT_STATS_TX_DE_CMN_TAG:
1532 		ath12k_htt_print_tx_de_cmn_stats_tlv(tag_buf, len, stats_req);
1533 		break;
1534 	case HTT_STATS_TX_DE_EAPOL_PACKETS_TAG:
1535 		ath12k_htt_print_tx_de_eapol_packets_stats_tlv(tag_buf, len, stats_req);
1536 		break;
1537 	case HTT_STATS_TX_DE_CLASSIFY_STATS_TAG:
1538 		ath12k_htt_print_tx_de_classify_stats_tlv(tag_buf, len, stats_req);
1539 		break;
1540 	case HTT_STATS_TX_DE_CLASSIFY_FAILED_TAG:
1541 		ath12k_htt_print_tx_de_classify_failed_stats_tlv(tag_buf, len, stats_req);
1542 		break;
1543 	case HTT_STATS_TX_DE_CLASSIFY_STATUS_TAG:
1544 		ath12k_htt_print_tx_de_classify_status_stats_tlv(tag_buf, len, stats_req);
1545 		break;
1546 	case HTT_STATS_TX_DE_ENQUEUE_PACKETS_TAG:
1547 		ath12k_htt_print_tx_de_enqueue_packets_stats_tlv(tag_buf, len, stats_req);
1548 		break;
1549 	case HTT_STATS_TX_DE_ENQUEUE_DISCARD_TAG:
1550 		ath12k_htt_print_tx_de_enqueue_discard_stats_tlv(tag_buf, len, stats_req);
1551 		break;
1552 	case HTT_STATS_TX_DE_COMPL_STATS_TAG:
1553 		ath12k_htt_print_tx_de_compl_stats_tlv(tag_buf, len, stats_req);
1554 		break;
1555 	default:
1556 		break;
1557 	}
1558 
1559 	return 0;
1560 }
1561 
1562 void ath12k_debugfs_htt_ext_stats_handler(struct ath12k_base *ab,
1563 					  struct sk_buff *skb)
1564 {
1565 	struct ath12k_htt_extd_stats_msg *msg;
1566 	struct debug_htt_stats_req *stats_req;
1567 	struct ath12k *ar;
1568 	u32 len, pdev_id, stats_info;
1569 	u64 cookie;
1570 	int ret;
1571 	bool send_completion = false;
1572 
1573 	msg = (struct ath12k_htt_extd_stats_msg *)skb->data;
1574 	cookie = le64_to_cpu(msg->cookie);
1575 
1576 	if (u64_get_bits(cookie, ATH12K_HTT_STATS_COOKIE_MSB) !=
1577 			 ATH12K_HTT_STATS_MAGIC_VALUE) {
1578 		ath12k_warn(ab, "received invalid htt ext stats event\n");
1579 		return;
1580 	}
1581 
1582 	pdev_id = u64_get_bits(cookie, ATH12K_HTT_STATS_COOKIE_LSB);
1583 	rcu_read_lock();
1584 	ar = ath12k_mac_get_ar_by_pdev_id(ab, pdev_id);
1585 	if (!ar) {
1586 		ath12k_warn(ab, "failed to get ar for pdev_id %d\n", pdev_id);
1587 		goto exit;
1588 	}
1589 
1590 	stats_req = ar->debug.htt_stats.stats_req;
1591 	if (!stats_req)
1592 		goto exit;
1593 
1594 	spin_lock_bh(&ar->data_lock);
1595 
1596 	stats_info = le32_to_cpu(msg->info1);
1597 	stats_req->done = u32_get_bits(stats_info, ATH12K_HTT_T2H_EXT_STATS_INFO1_DONE);
1598 	if (stats_req->done)
1599 		send_completion = true;
1600 
1601 	spin_unlock_bh(&ar->data_lock);
1602 
1603 	len = u32_get_bits(stats_info, ATH12K_HTT_T2H_EXT_STATS_INFO1_LENGTH);
1604 	if (len > skb->len) {
1605 		ath12k_warn(ab, "invalid length %d for HTT stats", len);
1606 		goto exit;
1607 	}
1608 
1609 	ret = ath12k_dp_htt_tlv_iter(ab, msg->data, len,
1610 				     ath12k_dbg_htt_ext_stats_parse,
1611 				     stats_req);
1612 	if (ret)
1613 		ath12k_warn(ab, "Failed to parse tlv %d\n", ret);
1614 
1615 	if (send_completion)
1616 		complete(&stats_req->htt_stats_rcvd);
1617 exit:
1618 	rcu_read_unlock();
1619 }
1620 
1621 static ssize_t ath12k_read_htt_stats_type(struct file *file,
1622 					  char __user *user_buf,
1623 					  size_t count, loff_t *ppos)
1624 {
1625 	struct ath12k *ar = file->private_data;
1626 	enum ath12k_dbg_htt_ext_stats_type type;
1627 	char buf[32];
1628 	size_t len;
1629 
1630 	mutex_lock(&ar->conf_mutex);
1631 	type = ar->debug.htt_stats.type;
1632 	mutex_unlock(&ar->conf_mutex);
1633 
1634 	len = scnprintf(buf, sizeof(buf), "%u\n", type);
1635 
1636 	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
1637 }
1638 
1639 static ssize_t ath12k_write_htt_stats_type(struct file *file,
1640 					   const char __user *user_buf,
1641 					   size_t count, loff_t *ppos)
1642 {
1643 	struct ath12k *ar = file->private_data;
1644 	enum ath12k_dbg_htt_ext_stats_type type;
1645 	unsigned int cfg_param[4] = {0};
1646 	const int size = 32;
1647 	int num_args;
1648 
1649 	char *buf __free(kfree) = kzalloc(size, GFP_KERNEL);
1650 	if (!buf)
1651 		return -ENOMEM;
1652 
1653 	if (copy_from_user(buf, user_buf, count))
1654 		return -EFAULT;
1655 
1656 	num_args = sscanf(buf, "%u %u %u %u %u\n", &type, &cfg_param[0],
1657 			  &cfg_param[1], &cfg_param[2], &cfg_param[3]);
1658 	if (!num_args || num_args > 5)
1659 		return -EINVAL;
1660 
1661 	if (type == ATH12K_DBG_HTT_EXT_STATS_RESET ||
1662 	    type >= ATH12K_DBG_HTT_NUM_EXT_STATS)
1663 		return -EINVAL;
1664 
1665 	mutex_lock(&ar->conf_mutex);
1666 
1667 	ar->debug.htt_stats.type = type;
1668 	ar->debug.htt_stats.cfg_param[0] = cfg_param[0];
1669 	ar->debug.htt_stats.cfg_param[1] = cfg_param[1];
1670 	ar->debug.htt_stats.cfg_param[2] = cfg_param[2];
1671 	ar->debug.htt_stats.cfg_param[3] = cfg_param[3];
1672 
1673 	mutex_unlock(&ar->conf_mutex);
1674 
1675 	return count;
1676 }
1677 
1678 static const struct file_operations fops_htt_stats_type = {
1679 	.read = ath12k_read_htt_stats_type,
1680 	.write = ath12k_write_htt_stats_type,
1681 	.open = simple_open,
1682 	.owner = THIS_MODULE,
1683 	.llseek = default_llseek,
1684 };
1685 
1686 static int ath12k_debugfs_htt_stats_req(struct ath12k *ar)
1687 {
1688 	struct debug_htt_stats_req *stats_req = ar->debug.htt_stats.stats_req;
1689 	enum ath12k_dbg_htt_ext_stats_type type = stats_req->type;
1690 	u64 cookie;
1691 	int ret, pdev_id;
1692 	struct htt_ext_stats_cfg_params cfg_params = { 0 };
1693 
1694 	lockdep_assert_held(&ar->conf_mutex);
1695 
1696 	init_completion(&stats_req->htt_stats_rcvd);
1697 
1698 	pdev_id = ath12k_mac_get_target_pdev_id(ar);
1699 	stats_req->done = false;
1700 	stats_req->pdev_id = pdev_id;
1701 
1702 	cookie = u64_encode_bits(ATH12K_HTT_STATS_MAGIC_VALUE,
1703 				 ATH12K_HTT_STATS_COOKIE_MSB);
1704 	cookie |= u64_encode_bits(pdev_id, ATH12K_HTT_STATS_COOKIE_LSB);
1705 
1706 	if (stats_req->override_cfg_param) {
1707 		cfg_params.cfg0 = stats_req->cfg_param[0];
1708 		cfg_params.cfg1 = stats_req->cfg_param[1];
1709 		cfg_params.cfg2 = stats_req->cfg_param[2];
1710 		cfg_params.cfg3 = stats_req->cfg_param[3];
1711 	}
1712 
1713 	ret = ath12k_dp_tx_htt_h2t_ext_stats_req(ar, type, &cfg_params, cookie);
1714 	if (ret) {
1715 		ath12k_warn(ar->ab, "failed to send htt stats request: %d\n", ret);
1716 		return ret;
1717 	}
1718 	if (!wait_for_completion_timeout(&stats_req->htt_stats_rcvd, 3 * HZ)) {
1719 		spin_lock_bh(&ar->data_lock);
1720 		if (!stats_req->done) {
1721 			stats_req->done = true;
1722 			spin_unlock_bh(&ar->data_lock);
1723 			ath12k_warn(ar->ab, "stats request timed out\n");
1724 			return -ETIMEDOUT;
1725 		}
1726 		spin_unlock_bh(&ar->data_lock);
1727 	}
1728 
1729 	return 0;
1730 }
1731 
1732 static int ath12k_open_htt_stats(struct inode *inode,
1733 				 struct file *file)
1734 {
1735 	struct ath12k *ar = inode->i_private;
1736 	struct debug_htt_stats_req *stats_req;
1737 	enum ath12k_dbg_htt_ext_stats_type type = ar->debug.htt_stats.type;
1738 	struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
1739 	int ret;
1740 
1741 	if (type == ATH12K_DBG_HTT_EXT_STATS_RESET)
1742 		return -EPERM;
1743 
1744 	mutex_lock(&ar->conf_mutex);
1745 
1746 	if (ah->state != ATH12K_HW_STATE_ON) {
1747 		ret = -ENETDOWN;
1748 		goto err_unlock;
1749 	}
1750 
1751 	if (ar->debug.htt_stats.stats_req) {
1752 		ret = -EAGAIN;
1753 		goto err_unlock;
1754 	}
1755 
1756 	stats_req = kzalloc(sizeof(*stats_req) + ATH12K_HTT_STATS_BUF_SIZE, GFP_KERNEL);
1757 	if (!stats_req) {
1758 		ret = -ENOMEM;
1759 		goto err_unlock;
1760 	}
1761 
1762 	ar->debug.htt_stats.stats_req = stats_req;
1763 	stats_req->type = type;
1764 	stats_req->cfg_param[0] = ar->debug.htt_stats.cfg_param[0];
1765 	stats_req->cfg_param[1] = ar->debug.htt_stats.cfg_param[1];
1766 	stats_req->cfg_param[2] = ar->debug.htt_stats.cfg_param[2];
1767 	stats_req->cfg_param[3] = ar->debug.htt_stats.cfg_param[3];
1768 	stats_req->override_cfg_param = !!stats_req->cfg_param[0] ||
1769 					!!stats_req->cfg_param[1] ||
1770 					!!stats_req->cfg_param[2] ||
1771 					!!stats_req->cfg_param[3];
1772 
1773 	ret = ath12k_debugfs_htt_stats_req(ar);
1774 	if (ret < 0)
1775 		goto out;
1776 
1777 	file->private_data = stats_req;
1778 
1779 	mutex_unlock(&ar->conf_mutex);
1780 
1781 	return 0;
1782 out:
1783 	kfree(stats_req);
1784 	ar->debug.htt_stats.stats_req = NULL;
1785 err_unlock:
1786 	mutex_unlock(&ar->conf_mutex);
1787 
1788 	return ret;
1789 }
1790 
1791 static int ath12k_release_htt_stats(struct inode *inode,
1792 				    struct file *file)
1793 {
1794 	struct ath12k *ar = inode->i_private;
1795 
1796 	mutex_lock(&ar->conf_mutex);
1797 	kfree(file->private_data);
1798 	ar->debug.htt_stats.stats_req = NULL;
1799 	mutex_unlock(&ar->conf_mutex);
1800 
1801 	return 0;
1802 }
1803 
1804 static ssize_t ath12k_read_htt_stats(struct file *file,
1805 				     char __user *user_buf,
1806 				     size_t count, loff_t *ppos)
1807 {
1808 	struct debug_htt_stats_req *stats_req = file->private_data;
1809 	char *buf;
1810 	u32 length;
1811 
1812 	buf = stats_req->buf;
1813 	length = min_t(u32, stats_req->buf_len, ATH12K_HTT_STATS_BUF_SIZE);
1814 	return simple_read_from_buffer(user_buf, count, ppos, buf, length);
1815 }
1816 
1817 static const struct file_operations fops_dump_htt_stats = {
1818 	.open = ath12k_open_htt_stats,
1819 	.release = ath12k_release_htt_stats,
1820 	.read = ath12k_read_htt_stats,
1821 	.owner = THIS_MODULE,
1822 	.llseek = default_llseek,
1823 };
1824 
1825 static ssize_t ath12k_write_htt_stats_reset(struct file *file,
1826 					    const char __user *user_buf,
1827 					    size_t count, loff_t *ppos)
1828 {
1829 	struct ath12k *ar = file->private_data;
1830 	enum ath12k_dbg_htt_ext_stats_type type;
1831 	struct htt_ext_stats_cfg_params cfg_params = { 0 };
1832 	u8 param_pos;
1833 	int ret;
1834 
1835 	ret = kstrtou32_from_user(user_buf, count, 0, &type);
1836 	if (ret)
1837 		return ret;
1838 
1839 	if (type >= ATH12K_DBG_HTT_NUM_EXT_STATS ||
1840 	    type == ATH12K_DBG_HTT_EXT_STATS_RESET)
1841 		return -E2BIG;
1842 
1843 	mutex_lock(&ar->conf_mutex);
1844 	cfg_params.cfg0 = HTT_STAT_DEFAULT_RESET_START_OFFSET;
1845 	param_pos = (type >> 5) + 1;
1846 
1847 	switch (param_pos) {
1848 	case ATH12K_HTT_STATS_RESET_PARAM_CFG_32_BYTES:
1849 		cfg_params.cfg1 = 1 << (cfg_params.cfg0 + type);
1850 		break;
1851 	case ATH12K_HTT_STATS_RESET_PARAM_CFG_64_BYTES:
1852 		cfg_params.cfg2 = ATH12K_HTT_STATS_RESET_BITMAP32_BIT(cfg_params.cfg0 +
1853 								      type);
1854 		break;
1855 	case ATH12K_HTT_STATS_RESET_PARAM_CFG_128_BYTES:
1856 		cfg_params.cfg3 = ATH12K_HTT_STATS_RESET_BITMAP64_BIT(cfg_params.cfg0 +
1857 								      type);
1858 		break;
1859 	default:
1860 		break;
1861 	}
1862 
1863 	ret = ath12k_dp_tx_htt_h2t_ext_stats_req(ar,
1864 						 ATH12K_DBG_HTT_EXT_STATS_RESET,
1865 						 &cfg_params,
1866 						 0ULL);
1867 	if (ret) {
1868 		ath12k_warn(ar->ab, "failed to send htt stats request: %d\n", ret);
1869 		mutex_unlock(&ar->conf_mutex);
1870 		return ret;
1871 	}
1872 
1873 	ar->debug.htt_stats.reset = type;
1874 	mutex_unlock(&ar->conf_mutex);
1875 
1876 	return count;
1877 }
1878 
1879 static const struct file_operations fops_htt_stats_reset = {
1880 	.write = ath12k_write_htt_stats_reset,
1881 	.open = simple_open,
1882 	.owner = THIS_MODULE,
1883 	.llseek = default_llseek,
1884 };
1885 
1886 void ath12k_debugfs_htt_stats_register(struct ath12k *ar)
1887 {
1888 	debugfs_create_file("htt_stats_type", 0600, ar->debug.debugfs_pdev,
1889 			    ar, &fops_htt_stats_type);
1890 	debugfs_create_file("htt_stats", 0400, ar->debug.debugfs_pdev,
1891 			    ar, &fops_dump_htt_stats);
1892 	debugfs_create_file("htt_stats_reset", 0200, ar->debug.debugfs_pdev,
1893 			    ar, &fops_htt_stats_reset);
1894 }
1895