xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/qdf_trace.c (revision 10fe6982eb7194813d8d8335da336bbcd531b22e)
1 /*
2  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  *  DOC:  qdf_trace
22  *  QCA driver framework (QDF) trace APIs
23  *  Trace, logging, and debugging definitions and APIs
24  */
25 
26 /* Include Files */
27 #include "qdf_str.h"
28 #include <qdf_trace.h>
29 #include <qdf_parse.h>
30 #include <qdf_module.h>
31 #include <qdf_util.h>
32 #include <qdf_mem.h>
33 #include <qdf_list.h>
34 
35 /* macro to map qdf trace levels into the bitmask */
36 #define QDF_TRACE_LEVEL_TO_MODULE_BITMASK(_level) ((1 << (_level)))
37 
38 #include <wlan_logging_sock_svc.h>
39 #include <qdf_module.h>
40 static int qdf_pidx = -1;
41 static bool qdf_log_dump_at_kernel_enable = true;
42 qdf_declare_param(qdf_log_dump_at_kernel_enable, bool);
43 
44 /* This value of 0 will disable the timer by default. */
45 static uint32_t qdf_log_flush_timer_period;
46 qdf_declare_param(qdf_log_flush_timer_period, uint);
47 
48 #include "qdf_time.h"
49 #include "qdf_mc_timer.h"
50 #include <host_diag_core_log.h>
51 
52 #if defined(WLAN_FEATURE_CONNECTIVITY_LOGGING) || \
53 	defined(CONNECTIVITY_DIAG_EVENT)
54 #include <wlan_connectivity_logging.h>
55 #include "i_host_diag_core_event.h"
56 #endif
57 
58 /* Global qdf print id */
59 
60 /* Preprocessor definitions and constants */
61 
62 enum qdf_timestamp_unit qdf_log_timestamp_type = QDF_LOG_TIMESTAMP_UNIT;
63 
64 #define DP_TRACE_META_DATA_STRLEN 50
65 
66 #ifdef TRACE_RECORD
67 /* Static and Global variables */
68 static spinlock_t ltrace_lock;
69 /* global qdf trace data */
70 static t_qdf_trace_data g_qdf_trace_data;
71 /*
72  * all the call back functions for dumping MTRACE messages from ring buffer
73  * are stored in qdf_trace_cb_table,these callbacks are initialized during init
74  * only so, we will make a copy of these call back functions and maintain in to
75  * qdf_trace_restore_cb_table. Incase if we make modifications to
76  * qdf_trace_cb_table, we can certainly retrieve all the call back functions
77  * back from Restore Table
78  */
79 static tp_qdf_trace_cb qdf_trace_cb_table[QDF_MODULE_ID_MAX];
80 static tp_qdf_trace_cb qdf_trace_restore_cb_table[QDF_MODULE_ID_MAX];
81 
82 #ifdef WLAN_LOGGING_BUFFERS_DYNAMICALLY
83 static qdf_trace_record_t *g_qdf_trace_tbl;
84 #else
85 static qdf_trace_record_t g_qdf_trace_tbl[MAX_QDF_TRACE_RECORDS];
86 #endif
87 
88 #endif
89 
90 #ifdef WLAN_FEATURE_MEMDUMP_ENABLE
91 static tp_qdf_state_info_cb qdf_state_info_table[QDF_MODULE_ID_MAX];
92 #endif
93 
94 #ifdef CONFIG_DP_TRACE
95 /* Static and Global variables */
96 #ifdef WLAN_LOGGING_BUFFERS_DYNAMICALLY
97 static struct qdf_dp_trace_record_s *g_qdf_dp_trace_tbl;
98 #else
99 static struct qdf_dp_trace_record_s
100 			g_qdf_dp_trace_tbl[MAX_QDF_DP_TRACE_RECORDS];
101 #endif
102 static spinlock_t l_dp_trace_lock;
103 
104 /*
105  * all the options to configure/control DP trace are
106  * defined in this structure
107  */
108 static struct s_qdf_dp_trace_data g_qdf_dp_trace_data;
109 /*
110  * all the call back functions for dumping DPTRACE messages from ring buffer
111  * are stored in qdf_dp_trace_cb_table, callbacks are initialized during init
112  */
113 static tp_qdf_dp_trace_cb qdf_dp_trace_cb_table[QDF_DP_TRACE_MAX + 1];
114 #endif
115 
116 #ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI
117 #define QDF_PARAM_STR_LENGTH 40
118 
119 enum qdf_num_module_param {
120 	MEM_DEBUG_DISABLED,
121 	QDF_DBG_MASK,
122 	PREALLOC_DISABLED,
123 	QDF_LOG_DUMP_AT_KERNEL_ENABLE,
124 	QDF_DBG_ARR,
125 	QDF_LOG_FLUSH_TIMER_PERIOD,
126 	QDF_PARAM_MAX,
127 };
128 
129 static char qdf_module_param[QDF_PARAM_MAX][QDF_PARAM_STR_LENGTH] = {
130 	"mem_debug_disabled",
131 	"qdf_dbg_mask",
132 	"prealloc_disabled",
133 	"qdf_log_dump_at_kernel_enable",
134 	"qdf_dbg_arr",
135 	"qdf_log_flush_timer_period",
136 };
137 #endif
138 
139 int qdf_snprintf(char *str_buffer, unsigned int size, char *str_format, ...)
140 {
141 	va_list args;
142 	int i;
143 
144 	va_start(args, str_format);
145 	i = vsnprintf(str_buffer, size, str_format, args);
146 	va_end(args);
147 
148 	return i;
149 }
150 qdf_export_symbol(qdf_snprintf);
151 
152 #ifdef QDF_ENABLE_TRACING
153 
154 void qdf_trace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
155 		   const char *str_format, ...)
156 {
157 	va_list val;
158 
159 	va_start(val, str_format);
160 	qdf_trace_msg_cmn(qdf_pidx, module, level, str_format, val);
161 	va_end(val);
162 }
163 qdf_export_symbol(qdf_trace_msg);
164 
165 void qdf_vtrace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
166 		    const char *str_format, va_list val)
167 {
168 	qdf_trace_msg_cmn(qdf_pidx, module, level, str_format, val);
169 }
170 qdf_export_symbol(qdf_vtrace_msg);
171 
172 #define ROW_SIZE 16
173 /* Buffer size = data bytes(2 hex chars plus space) + NULL */
174 #define BUFFER_SIZE ((QDF_DP_TRACE_RECORD_SIZE * 3) + 1)
175 
176 static void __qdf_trace_hex_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
177 				 void *data, int buf_len, bool print_ascii)
178 {
179 	const u8 *ptr = data;
180 	int i = 0;
181 
182 	if (!qdf_print_is_verbose_enabled(qdf_pidx, module, level))
183 		return;
184 
185 	while (buf_len > 0) {
186 		unsigned char linebuf[BUFFER_SIZE] = {0};
187 		int linelen = min(buf_len, ROW_SIZE);
188 
189 		buf_len -= ROW_SIZE;
190 
191 		hex_dump_to_buffer(ptr, linelen, ROW_SIZE, 1,
192 				   linebuf, sizeof(linebuf), print_ascii);
193 
194 		qdf_trace_msg(module, level, "%.8x: %s", i, linebuf);
195 		ptr += ROW_SIZE;
196 		i += ROW_SIZE;
197 	}
198 }
199 
200 void qdf_trace_hex_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
201 			void *data, int buf_len)
202 {
203 	__qdf_trace_hex_dump(module, level, data, buf_len, false);
204 }
205 
206 qdf_export_symbol(qdf_trace_hex_dump);
207 
208 void qdf_trace_hex_ascii_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
209 			      void *data, int buf_len)
210 {
211 	__qdf_trace_hex_dump(module, level, data, buf_len, true);
212 }
213 
214 qdf_export_symbol(qdf_trace_hex_ascii_dump);
215 
216 #endif
217 
218 #ifdef TRACE_RECORD
219 
220 #ifdef WLAN_LOGGING_BUFFERS_DYNAMICALLY
221 static inline QDF_STATUS allocate_g_qdf_trace_tbl_buffer(void)
222 {
223 	g_qdf_trace_tbl = qdf_mem_valloc(MAX_QDF_TRACE_RECORDS *
224 					 sizeof(*g_qdf_trace_tbl));
225 	QDF_BUG(g_qdf_trace_tbl);
226 	return g_qdf_trace_tbl ? QDF_STATUS_SUCCESS : QDF_STATUS_E_NOMEM;
227 }
228 
229 static inline void free_g_qdf_trace_tbl_buffer(void)
230 {
231 	qdf_mem_vfree(g_qdf_trace_tbl);
232 	g_qdf_trace_tbl = NULL;
233 }
234 #else
235 static inline QDF_STATUS allocate_g_qdf_trace_tbl_buffer(void)
236 {
237 	return QDF_STATUS_SUCCESS;
238 }
239 
240 static inline void free_g_qdf_trace_tbl_buffer(void)
241 { }
242 #endif
243 void qdf_trace_enable(uint32_t bitmask_of_module_id, uint8_t enable)
244 {
245 	int i;
246 
247 	if (bitmask_of_module_id) {
248 		for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
249 			if (((bitmask_of_module_id >> i) & 1)) {
250 				if (enable) {
251 					if (NULL !=
252 					    qdf_trace_restore_cb_table[i]) {
253 						qdf_trace_cb_table[i] =
254 						qdf_trace_restore_cb_table[i];
255 					}
256 				} else {
257 					qdf_trace_restore_cb_table[i] =
258 						qdf_trace_cb_table[i];
259 					qdf_trace_cb_table[i] = NULL;
260 				}
261 			}
262 		}
263 	} else {
264 		if (enable) {
265 			for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
266 				if (qdf_trace_restore_cb_table[i]) {
267 					qdf_trace_cb_table[i] =
268 						qdf_trace_restore_cb_table[i];
269 				}
270 			}
271 		} else {
272 			for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
273 				qdf_trace_restore_cb_table[i] =
274 					qdf_trace_cb_table[i];
275 				qdf_trace_cb_table[i] = NULL;
276 			}
277 		}
278 	}
279 }
280 qdf_export_symbol(qdf_trace_enable);
281 
282 void qdf_trace_init(void)
283 {
284 	uint8_t i;
285 
286 	if (allocate_g_qdf_trace_tbl_buffer() != QDF_STATUS_SUCCESS)
287 		return;
288 	g_qdf_trace_data.head = INVALID_QDF_TRACE_ADDR;
289 	g_qdf_trace_data.tail = INVALID_QDF_TRACE_ADDR;
290 	g_qdf_trace_data.num = 0;
291 	g_qdf_trace_data.enable = true;
292 	g_qdf_trace_data.dump_count = DEFAULT_QDF_TRACE_DUMP_COUNT;
293 	g_qdf_trace_data.num_since_last_dump = 0;
294 
295 	for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
296 		qdf_trace_cb_table[i] = NULL;
297 		qdf_trace_restore_cb_table[i] = NULL;
298 	}
299 }
300 qdf_export_symbol(qdf_trace_init);
301 
302 void qdf_trace_deinit(void)
303 {
304 	g_qdf_trace_data.enable = false;
305 	g_qdf_trace_data.num = 0;
306 	g_qdf_trace_data.head = INVALID_QDF_TRACE_ADDR;
307 	g_qdf_trace_data.tail = INVALID_QDF_TRACE_ADDR;
308 
309 	free_g_qdf_trace_tbl_buffer();
310 }
311 
312 qdf_export_symbol(qdf_trace_deinit);
313 
314 void qdf_trace(uint8_t module, uint16_t code, uint16_t session, uint32_t data)
315 {
316 	tp_qdf_trace_record rec = NULL;
317 	unsigned long flags;
318 	char time[18];
319 
320 	if (!g_qdf_trace_data.enable)
321 		return;
322 
323 	/* if module is not registered, don't record for that module */
324 	if (!qdf_trace_cb_table[module])
325 		return;
326 
327 	qdf_get_time_of_the_day_in_hr_min_sec_usec(time, sizeof(time));
328 	/* Acquire the lock so that only one thread at a time can fill the ring
329 	 * buffer
330 	 */
331 	spin_lock_irqsave(&ltrace_lock, flags);
332 
333 	g_qdf_trace_data.num++;
334 
335 	if (g_qdf_trace_data.num > MAX_QDF_TRACE_RECORDS)
336 		g_qdf_trace_data.num = MAX_QDF_TRACE_RECORDS;
337 
338 	if (INVALID_QDF_TRACE_ADDR == g_qdf_trace_data.head) {
339 		/* first record */
340 		g_qdf_trace_data.head = 0;
341 		g_qdf_trace_data.tail = 0;
342 	} else {
343 		/* queue is not empty */
344 		uint32_t tail = g_qdf_trace_data.tail + 1;
345 
346 		if (MAX_QDF_TRACE_RECORDS == tail)
347 			tail = 0;
348 
349 		if (g_qdf_trace_data.head == tail) {
350 			/* full */
351 			if (MAX_QDF_TRACE_RECORDS == ++g_qdf_trace_data.head)
352 				g_qdf_trace_data.head = 0;
353 		}
354 		g_qdf_trace_data.tail = tail;
355 	}
356 
357 	rec = &g_qdf_trace_tbl[g_qdf_trace_data.tail];
358 	rec->code = code;
359 	rec->session = session;
360 	rec->data = data;
361 	rec->qtime = qdf_get_log_timestamp();
362 	scnprintf(rec->time, sizeof(rec->time), "%s", time);
363 	rec->module = module;
364 	rec->pid = (in_interrupt() ? 0 : current->pid);
365 	g_qdf_trace_data.num_since_last_dump++;
366 	spin_unlock_irqrestore(&ltrace_lock, flags);
367 }
368 qdf_export_symbol(qdf_trace);
369 
370 #ifdef ENABLE_MTRACE_LOG
371 void qdf_mtrace_log(QDF_MODULE_ID src_module, QDF_MODULE_ID dst_module,
372 		    uint16_t message_id, uint8_t vdev_id)
373 {
374 	uint32_t trace_log, payload;
375 	static uint16_t counter;
376 
377 	trace_log = (src_module << 23) | (dst_module << 15) | message_id;
378 	payload = (vdev_id << 16) | counter++;
379 
380 	QDF_TRACE(src_module, QDF_TRACE_LEVEL_TRACE, "%x %x",
381 		  trace_log, payload);
382 }
383 
384 qdf_export_symbol(qdf_mtrace_log);
385 #endif
386 
387 void qdf_mtrace(QDF_MODULE_ID src_module, QDF_MODULE_ID dst_module,
388 		uint16_t message_id, uint8_t vdev_id, uint32_t data)
389 {
390 	qdf_trace(src_module, message_id, vdev_id, data);
391 	qdf_mtrace_log(src_module, dst_module, message_id, vdev_id);
392 }
393 
394 qdf_export_symbol(qdf_mtrace);
395 
396 QDF_STATUS qdf_trace_spin_lock_init(void)
397 {
398 	spin_lock_init(&ltrace_lock);
399 
400 	return QDF_STATUS_SUCCESS;
401 }
402 qdf_export_symbol(qdf_trace_spin_lock_init);
403 
404 void qdf_trace_register(QDF_MODULE_ID module_id,
405 			tp_qdf_trace_cb qdf_trace_callback)
406 {
407 	qdf_trace_cb_table[module_id] = qdf_trace_callback;
408 }
409 qdf_export_symbol(qdf_trace_register);
410 
411 void qdf_trace_dump_all(void *p_mac, uint8_t code, uint8_t session,
412 	uint32_t count, uint32_t bitmask_of_module)
413 {
414 	qdf_trace_record_t p_record;
415 	int32_t i, tail;
416 
417 	if (!g_qdf_trace_data.enable) {
418 		QDF_TRACE(QDF_MODULE_ID_SYS,
419 			  QDF_TRACE_LEVEL_ERROR, "Tracing Disabled");
420 		return;
421 	}
422 
423 	QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_INFO,
424 		  "DPT: Total Records: %d, Head: %d, Tail: %d",
425 		  g_qdf_trace_data.num, g_qdf_trace_data.head,
426 		  g_qdf_trace_data.tail);
427 
428 	/* acquire the lock so that only one thread at a time can read
429 	 * the ring buffer
430 	 */
431 	spin_lock(&ltrace_lock);
432 
433 	if (g_qdf_trace_data.head != INVALID_QDF_TRACE_ADDR) {
434 		i = g_qdf_trace_data.head;
435 		tail = g_qdf_trace_data.tail;
436 
437 		if (count) {
438 			if (count > g_qdf_trace_data.num)
439 				count = g_qdf_trace_data.num;
440 			if (tail >= (count - 1))
441 				i = tail - count + 1;
442 			else if (count != MAX_QDF_TRACE_RECORDS)
443 				i = MAX_QDF_TRACE_RECORDS - ((count - 1) -
444 							     tail);
445 		}
446 
447 		p_record = g_qdf_trace_tbl[i];
448 		/* right now we are not using num_since_last_dump member but
449 		 * in future we might re-visit and use this member to track
450 		 * how many latest messages got added while we were dumping
451 		 * from ring buffer
452 		 */
453 		g_qdf_trace_data.num_since_last_dump = 0;
454 		spin_unlock(&ltrace_lock);
455 		for (;; ) {
456 			if ((code == 0 || (code == p_record.code)) &&
457 			    (qdf_trace_cb_table[p_record.module])) {
458 				if (0 == bitmask_of_module) {
459 					qdf_trace_cb_table[p_record.
460 							   module] (p_mac,
461 								    &p_record,
462 								    (uint16_t)
463 								    i);
464 				} else {
465 					if (bitmask_of_module &
466 					    (1 << p_record.module)) {
467 						qdf_trace_cb_table[p_record.
468 								   module]
469 							(p_mac, &p_record,
470 							(uint16_t) i);
471 					}
472 				}
473 			}
474 
475 			if (i == tail)
476 				break;
477 			i += 1;
478 
479 			spin_lock(&ltrace_lock);
480 			if (MAX_QDF_TRACE_RECORDS == i) {
481 				i = 0;
482 				p_record = g_qdf_trace_tbl[0];
483 			} else {
484 				p_record = g_qdf_trace_tbl[i];
485 			}
486 			spin_unlock(&ltrace_lock);
487 		}
488 	} else {
489 		spin_unlock(&ltrace_lock);
490 	}
491 }
492 qdf_export_symbol(qdf_trace_dump_all);
493 #endif
494 
495 #ifdef WLAN_FEATURE_MEMDUMP_ENABLE
496 void qdf_register_debugcb_init(void)
497 {
498 	uint8_t i;
499 
500 	for (i = 0; i < QDF_MODULE_ID_MAX; i++)
501 		qdf_state_info_table[i] = NULL;
502 }
503 qdf_export_symbol(qdf_register_debugcb_init);
504 
505 void qdf_register_debug_callback(QDF_MODULE_ID module_id,
506 					tp_qdf_state_info_cb qdf_state_infocb)
507 {
508 	qdf_state_info_table[module_id] = qdf_state_infocb;
509 }
510 qdf_export_symbol(qdf_register_debug_callback);
511 
512 QDF_STATUS qdf_state_info_dump_all(char *buf, uint16_t size,
513 				   uint16_t *driver_dump_size)
514 {
515 	uint8_t module, ret = QDF_STATUS_SUCCESS;
516 	uint16_t buf_len = size;
517 	char *buf_ptr = buf;
518 
519 	for (module = 0; module < QDF_MODULE_ID_MAX; module++) {
520 		if (qdf_state_info_table[module]) {
521 			qdf_state_info_table[module](&buf_ptr, &buf_len);
522 			if (!buf_len) {
523 				ret = QDF_STATUS_E_NOMEM;
524 				break;
525 			}
526 		}
527 	}
528 
529 	*driver_dump_size = size - buf_len;
530 	return ret;
531 }
532 qdf_export_symbol(qdf_state_info_dump_all);
533 #endif
534 
535 #ifdef CONFIG_DP_TRACE
536 
537 #ifdef WLAN_LOGGING_BUFFERS_DYNAMICALLY
538 static inline QDF_STATUS allocate_g_qdf_dp_trace_tbl_buffer(void)
539 {
540 	g_qdf_dp_trace_tbl = qdf_mem_valloc(MAX_QDF_DP_TRACE_RECORDS *
541 					    sizeof(*g_qdf_dp_trace_tbl));
542 	QDF_BUG(g_qdf_dp_trace_tbl);
543 	return g_qdf_dp_trace_tbl ? QDF_STATUS_SUCCESS : QDF_STATUS_E_NOMEM;
544 }
545 
546 static inline void free_g_qdf_dp_trace_tbl_buffer(void)
547 {
548 	qdf_mem_vfree(g_qdf_dp_trace_tbl);
549 	g_qdf_dp_trace_tbl = NULL;
550 }
551 #else
552 static inline QDF_STATUS allocate_g_qdf_dp_trace_tbl_buffer(void)
553 {
554 	return QDF_STATUS_SUCCESS;
555 }
556 
557 static inline void free_g_qdf_dp_trace_tbl_buffer(void)
558 { }
559 #endif
560 
561 #define QDF_DP_TRACE_PREPEND_STR_SIZE 100
562 /*
563  * one dp trace record can't be greater than 300 bytes.
564  * Max Size will be QDF_DP_TRACE_PREPEND_STR_SIZE(100) + BUFFER_SIZE(121).
565  * Always make sure to change this QDF_DP_TRACE_MAX_RECORD_SIZE
566  * value accordingly whenever above two mentioned MACRO value changes.
567  */
568 #define QDF_DP_TRACE_MAX_RECORD_SIZE 300
569 
570 static void qdf_dp_unused(struct qdf_dp_trace_record_s *record,
571 			  uint16_t index, uint8_t pdev_id, uint8_t info)
572 {
573 	qdf_print("%s: QDF_DP_TRACE_MAX event should not be generated",
574 		  __func__);
575 }
576 
577 void qdf_dp_trace_init(bool live_mode_config, uint8_t thresh,
578 				uint16_t time_limit, uint8_t verbosity,
579 				uint32_t proto_bitmap)
580 {
581 	uint8_t i;
582 
583 	if (allocate_g_qdf_dp_trace_tbl_buffer() != QDF_STATUS_SUCCESS) {
584 		QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
585 				"Failed!!! DP Trace buffer allocation");
586 		return;
587 	}
588 	qdf_dp_trace_spin_lock_init();
589 	qdf_dp_trace_clear_buffer();
590 	g_qdf_dp_trace_data.enable = true;
591 	g_qdf_dp_trace_data.no_of_record = 1;
592 
593 	g_qdf_dp_trace_data.live_mode_config = live_mode_config;
594 	g_qdf_dp_trace_data.live_mode = live_mode_config;
595 	g_qdf_dp_trace_data.high_tput_thresh = thresh;
596 	g_qdf_dp_trace_data.thresh_time_limit = time_limit;
597 	g_qdf_dp_trace_data.proto_bitmap = proto_bitmap;
598 	g_qdf_dp_trace_data.verbosity = verbosity;
599 	g_qdf_dp_trace_data.ini_conf_verbosity = verbosity;
600 
601 	for (i = 0; i < ARRAY_SIZE(qdf_dp_trace_cb_table); i++)
602 		qdf_dp_trace_cb_table[i] = qdf_dp_display_record;
603 
604 	qdf_dp_trace_cb_table[QDF_DP_TRACE_HDD_TX_PACKET_RECORD] =
605 		qdf_dp_trace_cb_table[QDF_DP_TRACE_HDD_RX_PACKET_RECORD] =
606 		qdf_dp_trace_cb_table[QDF_DP_TRACE_TX_PACKET_RECORD] =
607 		qdf_dp_trace_cb_table[QDF_DP_TRACE_RX_PACKET_RECORD] =
608 		qdf_dp_trace_cb_table[QDF_DP_TRACE_DROP_PACKET_RECORD] =
609 		qdf_dp_trace_cb_table[QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD] =
610 		qdf_dp_trace_cb_table[QDF_DP_TRACE_LI_DP_RX_PACKET_RECORD] =
611 		qdf_dp_display_data_pkt_record;
612 
613 	qdf_dp_trace_cb_table[QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD] =
614 	qdf_dp_trace_cb_table[QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD] =
615 	qdf_dp_trace_cb_table[QDF_DP_TRACE_FREE_PACKET_PTR_RECORD] =
616 	qdf_dp_trace_cb_table[QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD] =
617 						qdf_dp_display_ptr_record;
618 	qdf_dp_trace_cb_table[QDF_DP_TRACE_EAPOL_PACKET_RECORD] =
619 	qdf_dp_trace_cb_table[QDF_DP_TRACE_DHCP_PACKET_RECORD] =
620 	qdf_dp_trace_cb_table[QDF_DP_TRACE_ARP_PACKET_RECORD] =
621 	qdf_dp_trace_cb_table[QDF_DP_TRACE_ICMP_PACKET_RECORD] =
622 	qdf_dp_trace_cb_table[QDF_DP_TRACE_ICMPv6_PACKET_RECORD] =
623 						qdf_dp_display_proto_pkt;
624 	qdf_dp_trace_cb_table[QDF_DP_TRACE_MGMT_PACKET_RECORD] =
625 					qdf_dp_display_mgmt_pkt;
626 	qdf_dp_trace_cb_table[QDF_DP_TRACE_TX_CREDIT_RECORD] =
627 					qdf_dp_display_credit_record;
628 	qdf_dp_trace_cb_table[QDF_DP_TRACE_EVENT_RECORD] =
629 					qdf_dp_display_event_record;
630 
631 	qdf_dp_trace_cb_table[QDF_DP_TRACE_MAX] = qdf_dp_unused;
632 }
633 qdf_export_symbol(qdf_dp_trace_init);
634 
635 void qdf_dp_trace_deinit(void)
636 {
637 	if (!g_qdf_dp_trace_data.enable)
638 		return;
639 	spin_lock_bh(&l_dp_trace_lock);
640 	g_qdf_dp_trace_data.enable = false;
641 	g_qdf_dp_trace_data.no_of_record = 0;
642 	spin_unlock_bh(&l_dp_trace_lock);
643 
644 	free_g_qdf_dp_trace_tbl_buffer();
645 }
646 
647 void qdf_dp_trace_set_value(uint32_t proto_bitmap, uint8_t no_of_record,
648 			    uint8_t verbosity)
649 {
650 	g_qdf_dp_trace_data.proto_bitmap = proto_bitmap;
651 	g_qdf_dp_trace_data.no_of_record = no_of_record;
652 	g_qdf_dp_trace_data.verbosity    = verbosity;
653 	g_qdf_dp_trace_data.dynamic_verbosity_modify = true;
654 }
655 qdf_export_symbol(qdf_dp_trace_set_value);
656 
657 void qdf_dp_trace_set_verbosity(uint32_t val)
658 {
659 	g_qdf_dp_trace_data.verbosity = val;
660 }
661 qdf_export_symbol(qdf_dp_trace_set_verbosity);
662 
663 /**
664  * qdf_dp_get_verbosity() - get verbosity value
665  *
666  * Return: int
667  */
668 uint8_t qdf_dp_get_verbosity(void)
669 {
670 	return g_qdf_dp_trace_data.verbosity;
671 }
672 qdf_export_symbol(qdf_dp_get_verbosity);
673 
674 void qdf_dp_set_proto_bitmap(uint32_t val)
675 {
676 	g_qdf_dp_trace_data.proto_bitmap = val;
677 }
678 qdf_export_symbol(qdf_dp_set_proto_bitmap);
679 
680 void qdf_dp_set_proto_event_bitmap(uint32_t value)
681 {
682 	g_qdf_dp_trace_data.proto_event_bitmap = value;
683 }
684 
685 qdf_export_symbol(qdf_dp_set_proto_event_bitmap);
686 
687 static uint32_t qdf_dp_get_proto_event_bitmap(void)
688 {
689 	return g_qdf_dp_trace_data.proto_event_bitmap;
690 }
691 
692 void qdf_dp_set_no_of_record(uint32_t val)
693 {
694 	g_qdf_dp_trace_data.no_of_record = val;
695 }
696 qdf_export_symbol(qdf_dp_set_no_of_record);
697 
698 uint8_t qdf_dp_get_no_of_record(void)
699 {
700 	return g_qdf_dp_trace_data.no_of_record;
701 }
702 qdf_export_symbol(qdf_dp_get_no_of_record);
703 
704 
705 /**
706  * qdf_dp_trace_verbosity_check() - check whether verbosity level is enabled
707  * @code: defines the event
708  *
709  * In High verbosity all codes are logged.
710  * For Med/Low and Default case code which has
711  * less value than corresponding verbosity codes
712  * are logged.
713  *
714  * Return: true or false depends on whether tracing enabled
715  */
716 static bool qdf_dp_trace_verbosity_check(enum QDF_DP_TRACE_ID code)
717 {
718 	switch (g_qdf_dp_trace_data.verbosity) {
719 	case QDF_DP_TRACE_VERBOSITY_HIGH:
720 		return true;
721 	case QDF_DP_TRACE_VERBOSITY_MEDIUM:
722 		if (code <= QDF_DP_TRACE_MED_VERBOSITY)
723 			return true;
724 		return false;
725 	case QDF_DP_TRACE_VERBOSITY_LOW:
726 		if (code <= QDF_DP_TRACE_LOW_VERBOSITY)
727 			return true;
728 		return false;
729 	case QDF_DP_TRACE_VERBOSITY_ULTRA_LOW:
730 		if (code <= QDF_DP_TRACE_ULTRA_LOW_VERBOSITY)
731 			return true;
732 		return false;
733 	case QDF_DP_TRACE_VERBOSITY_BASE:
734 		if (code <= QDF_DP_TRACE_BASE_VERBOSITY)
735 			return true;
736 		return false;
737 	default:
738 		return false;
739 	}
740 }
741 
742 uint32_t qdf_dp_get_proto_bitmap(void)
743 {
744 	if (g_qdf_dp_trace_data.enable)
745 		return g_qdf_dp_trace_data.proto_bitmap;
746 	else
747 		return 0;
748 }
749 
750 void qdf_dp_trace_set_track(qdf_nbuf_t nbuf, enum qdf_proto_dir dir)
751 {
752 	uint32_t count = 0;
753 
754 	if (!g_qdf_dp_trace_data.enable)
755 		return;
756 
757 	spin_lock_bh(&l_dp_trace_lock);
758 	if (QDF_TX == dir)
759 		count = ++g_qdf_dp_trace_data.tx_count;
760 	else if (QDF_RX == dir)
761 		count = ++g_qdf_dp_trace_data.rx_count;
762 
763 	if ((g_qdf_dp_trace_data.no_of_record != 0) &&
764 		(count % g_qdf_dp_trace_data.no_of_record == 0)) {
765 		if (QDF_TX == dir)
766 			QDF_NBUF_CB_TX_DP_TRACE(nbuf) = 1;
767 		else if (QDF_RX == dir)
768 			QDF_NBUF_CB_RX_DP_TRACE(nbuf) = 1;
769 	}
770 	spin_unlock_bh(&l_dp_trace_lock);
771 }
772 qdf_export_symbol(qdf_dp_trace_set_track);
773 
774 /* Number of bytes to be grouped together while printing DP-Trace data */
775 #define QDF_DUMP_DP_GROUP_SIZE 6
776 
777 /**
778  * dump_dp_hex_trace() - Display the data in buffer
779  * @prepend_str:     string to prepend the hexdump with.
780  * @inbuf:     buffer which contains data to be displayed
781  * @inbuf_len: defines the size of the data to be displayed
782  *
783  * Return: None
784  */
785 static void
786 dump_dp_hex_trace(char *prepend_str, uint8_t *inbuf, uint8_t inbuf_len)
787 {
788 	unsigned char outbuf[BUFFER_SIZE];
789 	const uint8_t *inbuf_ptr = inbuf;
790 	char *outbuf_ptr = outbuf;
791 	int outbytes_written = 0;
792 
793 	qdf_mem_zero(outbuf, sizeof(outbuf));
794 	do {
795 		outbytes_written += scnprintf(outbuf_ptr,
796 					BUFFER_SIZE - outbytes_written,
797 					"%02x", *inbuf_ptr);
798 		outbuf_ptr = outbuf + outbytes_written;
799 
800 		if ((inbuf_ptr - inbuf) &&
801 		    (inbuf_ptr - inbuf + 1) % QDF_DUMP_DP_GROUP_SIZE == 0) {
802 			outbytes_written += scnprintf(outbuf_ptr,
803 						BUFFER_SIZE - outbytes_written,
804 						" ");
805 			outbuf_ptr = outbuf + outbytes_written;
806 		}
807 		inbuf_ptr++;
808 	} while (inbuf_ptr < (inbuf + inbuf_len));
809 	DPTRACE_PRINT("%s %s", prepend_str, outbuf);
810 }
811 
812 /**
813  * qdf_dp_code_to_string() - convert dptrace code to string
814  * @code: dptrace code
815  *
816  * Return: string version of code
817  */
818 static
819 const char *qdf_dp_code_to_string(enum QDF_DP_TRACE_ID code)
820 {
821 	switch (code) {
822 	case QDF_DP_TRACE_DROP_PACKET_RECORD:
823 		return "DROP:";
824 	case QDF_DP_TRACE_EAPOL_PACKET_RECORD:
825 		return "EAPOL:";
826 	case QDF_DP_TRACE_DHCP_PACKET_RECORD:
827 		return "DHCP:";
828 	case QDF_DP_TRACE_ARP_PACKET_RECORD:
829 		return "ARP:";
830 	case QDF_DP_TRACE_ICMP_PACKET_RECORD:
831 		return "ICMP:";
832 	case QDF_DP_TRACE_ICMPv6_PACKET_RECORD:
833 		return "ICMPv6:";
834 	case QDF_DP_TRACE_MGMT_PACKET_RECORD:
835 		return "MGMT:";
836 	case QDF_DP_TRACE_TX_CREDIT_RECORD:
837 		return "CREDIT:";
838 	case QDF_DP_TRACE_EVENT_RECORD:
839 		return "EVENT:";
840 	case QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD:
841 		return "HDD: TX: PTR:";
842 	case QDF_DP_TRACE_LI_DP_TX_PACKET_PTR_RECORD:
843 		return "LI_DP: TX: PTR:";
844 	case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
845 		return "HDD: TX: DATA:";
846 	case QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD:
847 	case QDF_DP_TRACE_TX_PACKET_RECORD:
848 		return "TX:";
849 	case QDF_DP_TRACE_CE_PACKET_PTR_RECORD:
850 		return "CE: TX: PTR:";
851 	case QDF_DP_TRACE_CE_FAST_PACKET_PTR_RECORD:
852 		return "CE: TX: FAST: PTR:";
853 	case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
854 		return "CE: TX: FAST: ERR:";
855 	case QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD:
856 	case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD:
857 		return "FREE: TX: PTR:";
858 	case QDF_DP_TRACE_RX_HTT_PACKET_PTR_RECORD:
859 		return "HTT: RX: PTR:";
860 	case QDF_DP_TRACE_RX_OFFLOAD_HTT_PACKET_PTR_RECORD:
861 		return "HTT: RX: OF: PTR:";
862 	case QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD:
863 		return "HDD: RX: PTR:";
864 	case QDF_DP_TRACE_RX_LI_DP_PACKET_PTR_RECORD:
865 		return "LI_DP: RX: PTR:";
866 	case QDF_DP_TRACE_HDD_RX_PACKET_RECORD:
867 		return "HDD: RX: DATA:";
868 	case QDF_DP_TRACE_LI_DP_NULL_RX_PACKET_RECORD:
869 		return "LI_DP_NULL: RX: DATA:";
870 	case QDF_DP_TRACE_LI_DP_RX_PACKET_RECORD:
871 	case QDF_DP_TRACE_RX_PACKET_RECORD:
872 		return "RX:";
873 	case QDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD:
874 		return "TXRX: TX: Q: PTR:";
875 	case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD:
876 		return "TXRX: TX: PTR:";
877 	case QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD:
878 		return "TXRX: TX: FAST: PTR:";
879 	case QDF_DP_TRACE_HTT_PACKET_PTR_RECORD:
880 		return "HTT: TX: PTR:";
881 	case QDF_DP_TRACE_HTC_PACKET_PTR_RECORD:
882 		return "HTC: TX: PTR:";
883 	case QDF_DP_TRACE_HIF_PACKET_PTR_RECORD:
884 		return "HIF: TX: PTR:";
885 	case QDF_DP_TRACE_RX_TXRX_PACKET_PTR_RECORD:
886 		return "TXRX: RX: PTR:";
887 	case QDF_DP_TRACE_HDD_TX_TIMEOUT:
888 		return "HDD: STA: TO:";
889 	case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
890 		return "HDD: SAP: TO:";
891 	default:
892 		return "Invalid";
893 	}
894 }
895 
896 /**
897  * qdf_dp_dir_to_str() - convert direction to string
898  * @dir: direction
899  *
900  * Return: string version of direction
901  */
902 static const char *qdf_dp_dir_to_str(enum qdf_proto_dir dir)
903 {
904 	switch (dir) {
905 	case QDF_TX:
906 		return " --> ";
907 	case QDF_RX:
908 		return " <-- ";
909 	default:
910 		return "invalid";
911 	}
912 }
913 
914 static const char *qdf_dp_credit_source_to_str(
915 		enum QDF_CREDIT_UPDATE_SOURCE source)
916 {
917 	switch (source) {
918 	case QDF_TX_SCHED:
919 		return "TX SCHED";
920 	case QDF_TX_COMP:
921 		return "TX COMP";
922 	case QDF_TX_CREDIT_UPDATE:
923 		return "CREDIT UP";
924 	case QDF_TX_HTT_MSG:
925 		return "HTT TX MSG";
926 	case QDF_HTT_ATTACH:
927 		return "HTT ATTACH";
928 	default:
929 		return "invalid";
930 	}
931 }
932 
933 static const char *qdf_dp_operation_to_str(enum QDF_CREDIT_OPERATION op)
934 {
935 	switch (op) {
936 	case QDF_CREDIT_INC:
937 		return "+";
938 	case QDF_CREDIT_DEC:
939 		return "-";
940 	case QDF_CREDIT_ABS:
941 		return "ABS";
942 	default:
943 		return "invalid";
944 	}
945 }
946 
947 /**
948  * qdf_dp_type_to_str() - convert packet type to string
949  * @type: type
950  *
951  * Return: string version of packet type
952  */
953 static const char *qdf_dp_type_to_str(enum qdf_proto_type type)
954 {
955 	switch (type) {
956 	case QDF_PROTO_TYPE_DHCP:
957 		return "DHCP";
958 	case QDF_PROTO_TYPE_EAPOL:
959 		return "EAPOL";
960 	case QDF_PROTO_TYPE_ARP:
961 		return "ARP";
962 	case QDF_PROTO_TYPE_ICMP:
963 		return "ICMP";
964 	case QDF_PROTO_TYPE_ICMPv6:
965 		return "ICMPv6";
966 	case QDF_PROTO_TYPE_MGMT:
967 		return "MGMT";
968 	case QDF_PROTO_TYPE_EVENT:
969 		return "EVENT";
970 	default:
971 		return "invalid";
972 	}
973 }
974 
975 /**
976  * qdf_dp_subtype_to_str() - convert packet subtype to string
977  * @subtype: subtype
978  *
979  * Return: string version of packet subtype
980  */
981 static const char *qdf_dp_subtype_to_str(enum qdf_proto_subtype subtype)
982 {
983 	switch (subtype) {
984 	case QDF_PROTO_EAPOL_M1:
985 		return "M1";
986 	case QDF_PROTO_EAPOL_M2:
987 		return "M2";
988 	case QDF_PROTO_EAPOL_M3:
989 		return "M3";
990 	case QDF_PROTO_EAPOL_M4:
991 		return "M4";
992 	case QDF_PROTO_DHCP_DISCOVER:
993 		return "DISC";
994 	case QDF_PROTO_DHCP_REQUEST:
995 		return "REQ";
996 	case QDF_PROTO_DHCP_OFFER:
997 		return "OFF";
998 	case QDF_PROTO_DHCP_ACK:
999 		return "ACK";
1000 	case QDF_PROTO_DHCP_NACK:
1001 		return "NACK";
1002 	case QDF_PROTO_DHCP_RELEASE:
1003 		return "REL";
1004 	case QDF_PROTO_DHCP_INFORM:
1005 		return "INFORM";
1006 	case QDF_PROTO_DHCP_DECLINE:
1007 		return "DECL";
1008 	case QDF_PROTO_ARP_REQ:
1009 	case QDF_PROTO_ICMP_REQ:
1010 	case QDF_PROTO_ICMPV6_REQ:
1011 		return "REQ";
1012 	case QDF_PROTO_ARP_RES:
1013 	case QDF_PROTO_ICMP_RES:
1014 	case QDF_PROTO_ICMPV6_RES:
1015 		return "RSP";
1016 	case QDF_PROTO_ICMPV6_RS:
1017 		return "RS";
1018 	case QDF_PROTO_ICMPV6_RA:
1019 		return "RA";
1020 	case QDF_PROTO_ICMPV6_NS:
1021 		return "NS";
1022 	case QDF_PROTO_ICMPV6_NA:
1023 		return "NA";
1024 	case QDF_PROTO_MGMT_ASSOC:
1025 		return "ASSOC";
1026 	case QDF_PROTO_MGMT_DISASSOC:
1027 		return "DISASSOC";
1028 	case QDF_PROTO_MGMT_AUTH:
1029 		return "AUTH";
1030 	case QDF_PROTO_MGMT_DEAUTH:
1031 		return "DEAUTH";
1032 	case QDF_ROAM_SYNCH:
1033 		return "ROAM SYNCH";
1034 	case QDF_ROAM_COMPLETE:
1035 		return "ROAM COMP";
1036 	case QDF_ROAM_EVENTID:
1037 		return "ROAM EVENTID";
1038 	case QDF_PROTO_EAP_REQUEST:
1039 		return "EAP REQ";
1040 	case QDF_PROTO_EAP_RESPONSE:
1041 		return "EAP RSP";
1042 	case QDF_PROTO_EAP_SUCCESS:
1043 		return "EAP SUC";
1044 	case QDF_PROTO_EAP_FAILURE:
1045 		return "EAP FAIL";
1046 	case QDF_PROTO_EAP_INITIATE:
1047 		return "EAP INIT";
1048 	case QDF_PROTO_EAP_FINISH:
1049 		return "EAP FINISH";
1050 	case QDF_PROTO_EAPOL_START:
1051 		return "START";
1052 	case QDF_PROTO_EAPOL_LOGOFF:
1053 		return "LOGOFF";
1054 	case QDF_PROTO_EAPOL_ASF:
1055 		return "ASF";
1056 	case QDF_PROTO_EAP_REQ_ID:
1057 		return "EAP REQ ID";
1058 	case QDF_PROTO_EAP_RSP_ID:
1059 		return "EAP RSP ID";
1060 	case QDF_PROTO_EAP_M1:
1061 		return "EAP M1";
1062 	case QDF_PROTO_EAP_M2:
1063 		return "EAP M2";
1064 	case QDF_PROTO_EAP_M3:
1065 		return "EAP M3";
1066 	case QDF_PROTO_EAP_M4:
1067 		return "EAP M4";
1068 	case QDF_PROTO_EAP_M5:
1069 		return "EAP M5";
1070 	case QDF_PROTO_EAP_M6:
1071 		return "EAP M6";
1072 	case QDF_PROTO_EAP_M7:
1073 		return "EAP M7";
1074 	case QDF_PROTO_EAP_M8:
1075 		return "EAP M8";
1076 	case QDF_PROTO_EAP_WSC_START:
1077 		return "EAP WSC START";
1078 	case QDF_PROTO_EAP_WSC_DONE:
1079 		return "EAP WSC DONE";
1080 	case QDF_PROTO_EAP_WSC_ACK:
1081 		return "EAP WSC ACK";
1082 	case QDF_PROTO_EAP_WSC_NACK:
1083 		return "EAP WSC NACK";
1084 	case QDF_PROTO_EAP_WSC_FRAG_ACK:
1085 		return "EAP WSC FRAG ACK";
1086 	default:
1087 		return "invalid";
1088 	}
1089 }
1090 
1091 /**
1092  * qdf_dp_enable_check() - check if dptrace, TX/RX tracing is enabled
1093  * @nbuf: nbuf
1094  * @code: dptrace code
1095  * @dir: TX or RX direction
1096  *
1097  * Return: true/false
1098  */
1099 static bool qdf_dp_enable_check(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
1100 				enum qdf_proto_dir dir)
1101 {
1102 	/* Return when Dp trace is not enabled */
1103 	if (!g_qdf_dp_trace_data.enable)
1104 		return false;
1105 
1106 	if (qdf_dp_trace_verbosity_check(code) == false)
1107 		return false;
1108 
1109 	if (nbuf && (dir == QDF_TX && ((QDF_NBUF_CB_TX_DP_TRACE(nbuf) == 0) ||
1110 				       (QDF_NBUF_CB_TX_PACKET_TRACK(nbuf) !=
1111 					QDF_NBUF_TX_PKT_DATA_TRACK))))
1112 		return false;
1113 
1114 	if (nbuf && (dir == QDF_RX && (QDF_NBUF_CB_RX_DP_TRACE(nbuf) == 0)))
1115 		return false;
1116 
1117 	/*
1118 	 * Special packets called with NULL nbuf and this API is expected to
1119 	 * return true
1120 	 */
1121 	return true;
1122 }
1123 
1124 /**
1125  * qdf_dp_trace_fill_meta_str() - fill up a common meta string
1126  * @prepend_str: pointer to string
1127  * @size: size of prepend_str
1128  * @rec_index: index of record
1129  * @info: info related to the record
1130  * @record: pointer to the record
1131  *
1132  * Return: ret value from scnprintf
1133  */
1134 static inline
1135 int qdf_dp_trace_fill_meta_str(char *prepend_str, int size,
1136 			       int rec_index, uint8_t info,
1137 			       struct qdf_dp_trace_record_s *record)
1138 {
1139 	char buffer[20];
1140 	int ret = 0;
1141 	bool live = info & QDF_DP_TRACE_RECORD_INFO_LIVE ? true : false;
1142 	bool throttled = info & QDF_DP_TRACE_RECORD_INFO_THROTTLED ?
1143 								true : false;
1144 
1145 	scnprintf(buffer, sizeof(buffer), "%llu", record->time);
1146 	ret = scnprintf(prepend_str, size,
1147 			"%s DPT: %04d:%02d%s %s",
1148 			throttled ? "*" : "",
1149 			rec_index,
1150 			record->pdev_id,
1151 			live ? "" : buffer,
1152 			qdf_dp_code_to_string(record->code));
1153 
1154 	return ret;
1155 }
1156 
1157 /**
1158  * qdf_dp_fill_record_data() - fill meta data and data into the record
1159  * @rec: pointer to record data
1160  * @data: pointer to data
1161  * @data_size: size of the data
1162  * @meta_data: pointer to metadata
1163  * @metadata_size: size of metadata
1164  *
1165  * Should be called from within a spin_lock for the qdf record.
1166  * Fills up rec->data with |metadata|data|
1167  *
1168  * Return: none
1169  */
1170 static void qdf_dp_fill_record_data
1171 	(struct qdf_dp_trace_record_s *rec,
1172 	uint8_t *data, uint8_t data_size,
1173 	uint8_t *meta_data, uint8_t metadata_size)
1174 {
1175 	int32_t available = QDF_DP_TRACE_RECORD_SIZE;
1176 	uint8_t *rec_data = rec->data;
1177 	uint8_t data_to_copy = 0;
1178 
1179 	qdf_mem_zero(rec_data, QDF_DP_TRACE_RECORD_SIZE);
1180 
1181 	/* copy meta data */
1182 	if (meta_data) {
1183 		if (metadata_size > available) {
1184 			QDF_TRACE_WARN(QDF_MODULE_ID_QDF,
1185 				       "%s: meta data does not fit into the record",
1186 				       __func__);
1187 			goto end;
1188 		}
1189 		qdf_mem_copy(rec_data, meta_data, metadata_size);
1190 		available = available - metadata_size;
1191 	} else {
1192 		metadata_size = 0;
1193 	}
1194 
1195 	/* copy data */
1196 	if (data && (data_size > 0) && (available > 0)) {
1197 		data_to_copy = data_size;
1198 		if (data_size > available)
1199 			data_to_copy = available;
1200 		qdf_mem_copy(&rec_data[metadata_size], data, data_to_copy);
1201 	}
1202 end:
1203 	rec->size = data_to_copy;
1204 }
1205 
1206 /**
1207  * qdf_dp_add_record() - add dp trace record
1208  * @code: dptrace code
1209  * @pdev_id: pdev_id
1210  * @print: true to print it in kmsg
1211  * @data: data pointer
1212  * @data_size: size of data to be copied
1213  * @meta_data: meta data to be prepended to data
1214  * @metadata_size: sizeof meta data
1215  * @print: whether to print record
1216  *
1217  * Return: none
1218  */
1219 static void qdf_dp_add_record(enum QDF_DP_TRACE_ID code, uint8_t pdev_id,
1220 			      uint8_t *data, uint8_t data_size,
1221 			      uint8_t *meta_data, uint8_t metadata_size,
1222 			      bool print)
1223 
1224 {
1225 	struct qdf_dp_trace_record_s *rec = NULL;
1226 	int index;
1227 	bool print_this_record = false;
1228 	u8 info = 0;
1229 
1230 	if (code >= QDF_DP_TRACE_MAX) {
1231 		QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
1232 				"invalid record code %u, max code %u",
1233 				code, QDF_DP_TRACE_MAX);
1234 		return;
1235 	}
1236 
1237 	spin_lock_bh(&l_dp_trace_lock);
1238 
1239 	if (print || g_qdf_dp_trace_data.force_live_mode) {
1240 		print_this_record = true;
1241 	} else if (g_qdf_dp_trace_data.live_mode == 1) {
1242 		print_this_record = true;
1243 		g_qdf_dp_trace_data.print_pkt_cnt++;
1244 		if (g_qdf_dp_trace_data.print_pkt_cnt >
1245 				g_qdf_dp_trace_data.high_tput_thresh) {
1246 			g_qdf_dp_trace_data.live_mode = 0;
1247 			g_qdf_dp_trace_data.verbosity =
1248 					QDF_DP_TRACE_VERBOSITY_ULTRA_LOW;
1249 			info |= QDF_DP_TRACE_RECORD_INFO_THROTTLED;
1250 		}
1251 	}
1252 
1253 	g_qdf_dp_trace_data.num++;
1254 
1255 	if (g_qdf_dp_trace_data.num > MAX_QDF_DP_TRACE_RECORDS)
1256 		g_qdf_dp_trace_data.num = MAX_QDF_DP_TRACE_RECORDS;
1257 
1258 	if (INVALID_QDF_DP_TRACE_ADDR == g_qdf_dp_trace_data.head) {
1259 		/* first record */
1260 		g_qdf_dp_trace_data.head = 0;
1261 		g_qdf_dp_trace_data.tail = 0;
1262 	} else {
1263 		/* queue is not empty */
1264 		g_qdf_dp_trace_data.tail++;
1265 
1266 		if (MAX_QDF_DP_TRACE_RECORDS == g_qdf_dp_trace_data.tail)
1267 			g_qdf_dp_trace_data.tail = 0;
1268 
1269 		if (g_qdf_dp_trace_data.head == g_qdf_dp_trace_data.tail) {
1270 			/* full */
1271 			if (MAX_QDF_DP_TRACE_RECORDS ==
1272 				++g_qdf_dp_trace_data.head)
1273 				g_qdf_dp_trace_data.head = 0;
1274 		}
1275 	}
1276 
1277 	rec = &g_qdf_dp_trace_tbl[g_qdf_dp_trace_data.tail];
1278 	index = g_qdf_dp_trace_data.tail;
1279 	rec->code = code;
1280 	rec->pdev_id = pdev_id;
1281 	rec->size = 0;
1282 	qdf_dp_fill_record_data(rec, data, data_size,
1283 				meta_data, metadata_size);
1284 	rec->time = qdf_get_log_timestamp();
1285 	rec->pid = (in_interrupt() ? 0 : current->pid);
1286 
1287 	if (rec->code >= QDF_DP_TRACE_MAX) {
1288 		QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
1289 				"invalid record code %u, max code %u",
1290 				rec->code, QDF_DP_TRACE_MAX);
1291 		return;
1292 	}
1293 
1294 	spin_unlock_bh(&l_dp_trace_lock);
1295 
1296 	info |= QDF_DP_TRACE_RECORD_INFO_LIVE;
1297 	if (print_this_record)
1298 		qdf_dp_trace_cb_table[rec->code] (rec, index,
1299 					QDF_TRACE_DEFAULT_PDEV_ID, info);
1300 }
1301 
1302 /**
1303  * qdf_get_rate_limit_by_type() - Get the rate limit by pkt type
1304  * @type: packet type
1305  *
1306  * Return: Rate limit value for a particular packet type
1307  */
1308 static inline
1309 uint8_t qdf_get_rate_limit_by_type(uint8_t type)
1310 {
1311 	switch (type) {
1312 	case QDF_PROTO_TYPE_DHCP:
1313 		return QDF_MAX_DHCP_PKTS_PER_SEC;
1314 	case QDF_PROTO_TYPE_EAPOL:
1315 		return QDF_MAX_EAPOL_PKTS_PER_SEC;
1316 	case QDF_PROTO_TYPE_ARP:
1317 		return QDF_MAX_ARP_PKTS_PER_SEC;
1318 	case QDF_PROTO_TYPE_DNS:
1319 		return QDF_MAX_DNS_PKTS_PER_SEC;
1320 	default:
1321 		return QDF_MAX_OTHER_PKTS_PER_SEC;
1322 	}
1323 }
1324 
1325 /**
1326  * qdf_get_pkt_type_string() - Get the string based on pkt type
1327  * @type: packet type
1328  * @subtype: packet subtype
1329  *
1330  * Return: String based on pkt type
1331  */
1332 static
1333 uint8_t *qdf_get_pkt_type_string(uint8_t type, uint8_t subtype)
1334 {
1335 	switch (subtype) {
1336 	case QDF_PROTO_EAPOL_M1:
1337 		return "EAPOL-1";
1338 	case QDF_PROTO_EAPOL_M2:
1339 		return "EAPOL-2";
1340 	case QDF_PROTO_EAPOL_M3:
1341 		return "EAPOL-3";
1342 	case QDF_PROTO_EAPOL_M4:
1343 		return "EAPOL-4";
1344 	case QDF_PROTO_DHCP_DISCOVER:
1345 		return "DHCP-D";
1346 	case QDF_PROTO_DHCP_REQUEST:
1347 		return "DHCP-R";
1348 	case QDF_PROTO_DHCP_OFFER:
1349 		return "DHCP-O";
1350 	case QDF_PROTO_DHCP_ACK:
1351 		return "DHCP-A";
1352 	case QDF_PROTO_DHCP_NACK:
1353 		return "DHCP-NA";
1354 	case QDF_PROTO_DHCP_RELEASE:
1355 		return "DHCP-REL";
1356 	case QDF_PROTO_DHCP_INFORM:
1357 		return "DHCP-IN";
1358 	case QDF_PROTO_DHCP_DECLINE:
1359 		return "DHCP-DEC";
1360 	case QDF_PROTO_ARP_REQ:
1361 		return "ARP-RQ";
1362 	case QDF_PROTO_ARP_RES:
1363 		return "ARP-RS";
1364 	case QDF_PROTO_DNS_QUERY:
1365 		return "DNS_Q";
1366 	case QDF_PROTO_DNS_RES:
1367 		return "DNS_RS";
1368 	case QDF_PROTO_EAP_REQUEST:
1369 		return "EAP_REQ";
1370 	case QDF_PROTO_EAP_RESPONSE:
1371 		return "EAP-RSP";
1372 	case QDF_PROTO_EAP_SUCCESS:
1373 		return "EAP-SUCCESS";
1374 	case QDF_PROTO_EAP_FAILURE:
1375 		return "EAP-FAIL";
1376 	case QDF_PROTO_EAP_INITIATE:
1377 		return "EAP-INIT";
1378 	case QDF_PROTO_EAP_FINISH:
1379 		return "EAP-FINISH";
1380 	case QDF_PROTO_EAPOL_START:
1381 		return "EAPOL-START";
1382 	case QDF_PROTO_EAPOL_LOGOFF:
1383 		return "EAPOL-LOGOFF";
1384 	case QDF_PROTO_EAPOL_ASF:
1385 		return "EAPOL-ASF";
1386 	case QDF_PROTO_EAP_REQ_ID:
1387 		return "EAP-REQ-ID";
1388 	case QDF_PROTO_EAP_RSP_ID:
1389 		return "EAP-RSP-ID";
1390 	case QDF_PROTO_EAP_M1:
1391 		return "EAP-M1";
1392 	case QDF_PROTO_EAP_M2:
1393 		return "EAP-M2";
1394 	case QDF_PROTO_EAP_M3:
1395 		return "EAP-M3";
1396 	case QDF_PROTO_EAP_M4:
1397 		return "EAP-M4";
1398 	case QDF_PROTO_EAP_M5:
1399 		return "EAP-M5";
1400 	case QDF_PROTO_EAP_M6:
1401 		return "EAP-M6";
1402 	case QDF_PROTO_EAP_M7:
1403 		return "EAP-M7";
1404 	case QDF_PROTO_EAP_M8:
1405 		return "EAP-M8";
1406 	case QDF_PROTO_EAP_WSC_START:
1407 		return "EAP-WSC-START";
1408 	case QDF_PROTO_EAP_WSC_DONE:
1409 		return "EAP-WSC-DONE";
1410 	case QDF_PROTO_EAP_WSC_ACK:
1411 		return "EAP-WSC-ACK";
1412 	case QDF_PROTO_EAP_WSC_NACK:
1413 		return "EAP-WSC-NACK";
1414 	case QDF_PROTO_EAP_WSC_FRAG_ACK:
1415 		return "EAP-WSC-FRAG-ACK";
1416 	default:
1417 		switch (type) {
1418 		case QDF_PROTO_TYPE_EAPOL:
1419 			return "EAP";
1420 		case QDF_PROTO_TYPE_DHCP:
1421 			return "DHCP";
1422 		case QDF_PROTO_TYPE_ARP:
1423 			return "ARP";
1424 		case QDF_PROTO_TYPE_DNS:
1425 			return "DNS";
1426 		default:
1427 			return "UNKNOWN";
1428 		}
1429 	}
1430 }
1431 
1432 /**
1433  * qdf_get_pkt_status_string() - Get the string based on pkt status
1434  * @status: packet status
1435  *
1436  * Return: String based on pkt status
1437  */
1438 static
1439 uint8_t *qdf_get_pkt_status_string(uint8_t status)
1440 {
1441 	switch (status) {
1442 	case QDF_TX_RX_STATUS_INVALID:
1443 		return "inv";
1444 	case QDF_TX_RX_STATUS_OK:
1445 		return "succ";
1446 	case QDF_TX_RX_STATUS_FW_DISCARD:
1447 		return "disc";
1448 	case QDF_TX_RX_STATUS_NO_ACK:
1449 		return "nack";
1450 	case QDF_TX_RX_STATUS_DROP:
1451 		return "drop";
1452 	default:
1453 		return "unknown";
1454 	}
1455 }
1456 
1457 void qdf_dp_log_proto_pkt_info(uint8_t *sa, uint8_t *da, uint8_t type,
1458 			       uint8_t subtype, uint8_t dir, uint16_t msdu_id,
1459 			       uint8_t status)
1460 {
1461 	uint8_t pkt_rate_limit;
1462 	static ulong last_ticks_tx[QDF_PROTO_SUBTYPE_MAX] = {0};
1463 	static ulong last_ticks_rx[QDF_PROTO_SUBTYPE_MAX] = {0};
1464 	ulong curr_ticks = jiffies;
1465 
1466 	pkt_rate_limit = qdf_get_rate_limit_by_type(type);
1467 
1468 	if ((dir == QDF_TX &&
1469 	     !time_after(curr_ticks,
1470 			 last_ticks_tx[subtype] + HZ / pkt_rate_limit)) ||
1471 	    (dir == QDF_RX &&
1472 	     !time_after(curr_ticks,
1473 			 last_ticks_rx[subtype] + HZ / pkt_rate_limit)))
1474 		return;
1475 
1476 	if (dir == QDF_TX)
1477 		last_ticks_tx[subtype] = curr_ticks;
1478 	else
1479 		last_ticks_rx[subtype] = curr_ticks;
1480 
1481 	if (status == QDF_TX_RX_STATUS_INVALID)
1482 		qdf_nofl_info("%s %s: SA:" QDF_MAC_ADDR_FMT " DA:" QDF_MAC_ADDR_FMT,
1483 			      qdf_get_pkt_type_string(type, subtype),
1484 			      dir ? "RX" : "TX", QDF_MAC_ADDR_REF(sa),
1485 			      QDF_MAC_ADDR_REF(da));
1486 	else
1487 		qdf_nofl_info("%s %s: SA:" QDF_MAC_ADDR_FMT " DA:" QDF_MAC_ADDR_FMT " msdu_id:%d status: %s",
1488 			      qdf_get_pkt_type_string(type, subtype),
1489 			      dir ? "RX" : "TX", QDF_MAC_ADDR_REF(sa),
1490 			      QDF_MAC_ADDR_REF(da), msdu_id,
1491 			      qdf_get_pkt_status_string(status));
1492 }
1493 
1494 qdf_export_symbol(qdf_dp_log_proto_pkt_info);
1495 
1496 /**
1497  * qdf_log_icmpv6_pkt() - log ICMPv6 packet
1498  * @vdev_id: ID of the vdev
1499  * @skb: skb pointer
1500  * @dir: direction
1501  * @pdev_id: ID of the pdev
1502  *
1503  * Return: true/false
1504  */
1505 static bool qdf_log_icmpv6_pkt(uint8_t vdev_id, struct sk_buff *skb,
1506 			       enum qdf_proto_dir dir, uint8_t pdev_id)
1507 {
1508 	enum qdf_proto_subtype subtype;
1509 
1510 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMPv6) &&
1511 		((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ICMPv6 ==
1512 			QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1513 		 (dir == QDF_RX && qdf_nbuf_is_icmpv6_pkt(skb) == true))) {
1514 
1515 		subtype = qdf_nbuf_get_icmpv6_subtype(skb);
1516 
1517 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false;
1518 		if (dir == QDF_TX)
1519 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1520 		else if (dir == QDF_RX)
1521 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1522 
1523 		DPTRACE(qdf_dp_trace_proto_pkt(
1524 			QDF_DP_TRACE_ICMPv6_PACKET_RECORD,
1525 			vdev_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
1526 			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
1527 			QDF_PROTO_TYPE_ICMPv6, subtype, dir, pdev_id, false, 0));
1528 
1529 		switch (subtype) {
1530 		case QDF_PROTO_ICMPV6_REQ:
1531 			g_qdf_dp_trace_data.icmpv6_req++;
1532 			break;
1533 		case QDF_PROTO_ICMPV6_RES:
1534 			g_qdf_dp_trace_data.icmpv6_resp++;
1535 			break;
1536 		case QDF_PROTO_ICMPV6_RS:
1537 			g_qdf_dp_trace_data.icmpv6_rs++;
1538 			break;
1539 		case QDF_PROTO_ICMPV6_RA:
1540 			g_qdf_dp_trace_data.icmpv6_ra++;
1541 			break;
1542 		case QDF_PROTO_ICMPV6_NS:
1543 			g_qdf_dp_trace_data.icmpv6_ns++;
1544 			break;
1545 		case QDF_PROTO_ICMPV6_NA:
1546 			g_qdf_dp_trace_data.icmpv6_na++;
1547 			break;
1548 		default:
1549 			break;
1550 		}
1551 		return true;
1552 	}
1553 
1554 	return false;
1555 }
1556 
1557 /**
1558  * qdf_log_icmp_pkt() - log ICMP packet
1559  * @vdev_id: ID of the vdev
1560  * @skb: skb pointer
1561  * @dir: direction
1562  * @pdev_id: ID of the pdev
1563  *
1564  * Return: true/false
1565  */
1566 static bool qdf_log_icmp_pkt(uint8_t vdev_id, struct sk_buff *skb,
1567 			     enum qdf_proto_dir dir, uint8_t pdev_id)
1568 {
1569 	enum qdf_proto_subtype proto_subtype;
1570 	uint8_t *data = NULL;
1571 	uint16_t seq_num = 0;
1572 	uint16_t icmp_id = 0;
1573 	uint32_t proto_priv_data = 0;
1574 
1575 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMP) &&
1576 	    (qdf_nbuf_is_icmp_pkt(skb) == true)) {
1577 
1578 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false;
1579 		proto_subtype = qdf_nbuf_get_icmp_subtype(skb);
1580 
1581 		data = qdf_nbuf_data(skb);
1582 		icmp_id = qdf_cpu_to_be16(*(uint16_t *)(data + ICMP_ID_OFFSET));
1583 		seq_num = qdf_cpu_to_be16(*(uint16_t *)(data + ICMP_SEQ_NUM_OFFSET));
1584 
1585 		proto_priv_data |= ((proto_priv_data | ((uint32_t)icmp_id)) << 16);
1586 		proto_priv_data |= (uint32_t)seq_num;
1587 
1588 		if (QDF_TX == dir)
1589 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1590 		else if (QDF_RX == dir)
1591 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1592 
1593 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ICMP_PACKET_RECORD,
1594 					       vdev_id,
1595 					       skb->data +
1596 					       QDF_NBUF_SRC_MAC_OFFSET,
1597 					       skb->data +
1598 					       QDF_NBUF_DEST_MAC_OFFSET,
1599 					       QDF_PROTO_TYPE_ICMP,
1600 					       proto_subtype, dir, pdev_id,
1601 					       false, proto_priv_data));
1602 
1603 		if (proto_subtype == QDF_PROTO_ICMP_REQ)
1604 			g_qdf_dp_trace_data.icmp_req++;
1605 		else
1606 			g_qdf_dp_trace_data.icmp_resp++;
1607 
1608 		return true;
1609 	}
1610 	return false;
1611 }
1612 
1613 #ifdef CONNECTIVITY_DIAG_EVENT
1614 enum diag_tx_status wlan_get_diag_tx_status(enum qdf_dp_tx_rx_status tx_status)
1615 {
1616 	switch (tx_status) {
1617 	case DIAG_TX_RX_STATUS_FW_DISCARD:
1618 	case DIAG_TX_RX_STATUS_INVALID:
1619 	case DIAG_TX_RX_STATUS_DROP:
1620 	case DIAG_TX_RX_STATUS_DOWNLOAD_SUCC:
1621 	case DIAG_TX_RX_STATUS_DEFAULT:
1622 	default:
1623 		return DIAG_TX_STATUS_FAIL;
1624 	case DIAG_TX_RX_STATUS_NO_ACK:
1625 		return DIAG_TX_STATUS_NO_ACK;
1626 	case DIAG_TX_RX_STATUS_OK:
1627 		return DIAG_TX_STATUS_ACK;
1628 	}
1629 
1630 	return DIAG_TX_STATUS_FAIL;
1631 }
1632 
1633 /**
1634  * qdf_subtype_to_wlan_main_tag() - Convert qdf subtype to wlan main tag
1635  * @subtype: EAPoL key subtype
1636  *
1637  * Return: Wlan main tag subtype
1638  */
1639 static int qdf_subtype_to_wlan_main_tag(enum qdf_proto_subtype subtype)
1640 {
1641 	switch (subtype) {
1642 	case QDF_PROTO_DHCP_DISCOVER:
1643 		return WLAN_CONN_DIAG_DHCP_DISC_EVENT;
1644 	case QDF_PROTO_DHCP_REQUEST:
1645 		return WLAN_CONN_DIAG_DHCP_REQUEST_EVENT;
1646 	case QDF_PROTO_DHCP_OFFER:
1647 		return WLAN_CONN_DIAG_DHCP_OFFER_EVENT;
1648 	case QDF_PROTO_DHCP_ACK:
1649 		return WLAN_CONN_DIAG_DHCP_ACK_EVENT;
1650 	case QDF_PROTO_DHCP_NACK:
1651 		return WLAN_CONN_DIAG_DHCP_NACK_EVENT;
1652 	case QDF_PROTO_EAPOL_M1:
1653 		return WLAN_CONN_DIAG_EAPOL_M1_EVENT;
1654 	case QDF_PROTO_EAPOL_M2:
1655 		return WLAN_CONN_DIAG_EAPOL_M2_EVENT;
1656 	case QDF_PROTO_EAPOL_M3:
1657 		return WLAN_CONN_DIAG_EAPOL_M3_EVENT;
1658 	case QDF_PROTO_EAPOL_M4:
1659 		return WLAN_CONN_DIAG_EAPOL_M4_EVENT;
1660 	case QDF_PROTO_EAP_REQUEST:
1661 		return WLAN_CONN_DIAG_EAP_REQ_EVENT;
1662 	case QDF_PROTO_EAP_RESPONSE:
1663 		return WLAN_CONN_DIAG_EAP_RESP_EVENT;
1664 	case QDF_PROTO_EAP_SUCCESS:
1665 		return WLAN_CONN_DIAG_EAP_SUCC_EVENT;
1666 	case QDF_PROTO_EAP_FAILURE:
1667 		return WLAN_CONN_DIAG_EAP_FAIL_EVENT;
1668 	case QDF_PROTO_EAPOL_START:
1669 		return WLAN_CONN_DIAG_EAP_START_EVENT;
1670 	default:
1671 		return WLAN_CONN_DIAG_MAX;
1672 	}
1673 }
1674 
1675 /**
1676  * qdf_get_wlan_eap_code() - Get EAP code
1677  * @data: skb data pointer
1678  *
1679  * Return: EAP code value
1680  */
1681 static int qdf_get_wlan_eap_code(uint8_t *data)
1682 {
1683 	uint8_t code = *(data + EAP_CODE_OFFSET);
1684 
1685 	switch (code) {
1686 	case QDF_EAP_REQUEST:
1687 		return WLAN_CONN_DIAG_EAP_REQ_EVENT;
1688 	case QDF_EAP_RESPONSE:
1689 		return WLAN_CONN_DIAG_EAP_RESP_EVENT;
1690 	case QDF_EAP_SUCCESS:
1691 		return WLAN_CONN_DIAG_EAP_SUCC_EVENT;
1692 	case QDF_EAP_FAILURE:
1693 		return WLAN_CONN_DIAG_EAP_FAIL_EVENT;
1694 	default:
1695 		return WLAN_CONN_DIAG_MAX;
1696 	}
1697 }
1698 
1699 /**
1700  * qdf_eapol_get_key_type() - Get EAPOL key type
1701  * @data: skb data pointer
1702  * @subtype: EAPoL key subtype
1703  *
1704  * Return: EAPOL key type
1705  */
1706 static
1707 uint8_t qdf_eapol_get_key_type(uint8_t *data, enum qdf_proto_subtype subtype)
1708 {
1709 	uint16_t key_info = *(uint16_t *)(data + EAPOL_KEY_INFO_OFFSET);
1710 
1711 	/* If key type is PTK, key type will be set in EAPOL Key info */
1712 	if (key_info & EAPOL_KEY_TYPE_MASK)
1713 		return qdf_subtype_to_wlan_main_tag(subtype);
1714 	else if (key_info & EAPOL_KEY_ENCRYPTED_MASK)
1715 		return WLAN_CONN_DIAG_GTK_M1_EVENT;
1716 	else
1717 		return WLAN_CONN_DIAG_GTK_M2_EVENT;
1718 }
1719 
1720 /**
1721  * qdf_skip_wlan_connectivity_log() - Check if connectivity log need to skip
1722  * @type: Protocol type
1723  * @subtype: Protocol subtype
1724  * @dir: Rx or Tx
1725  *
1726  * Return: true or false
1727  */
1728 static inline
1729 bool qdf_skip_wlan_connectivity_log(enum qdf_proto_type type,
1730 				    enum qdf_proto_subtype subtype,
1731 				    enum qdf_proto_dir dir)
1732 {
1733 	if (dir == QDF_RX && type == QDF_PROTO_TYPE_DHCP &&
1734 	    (subtype == QDF_PROTO_DHCP_DISCOVER ||
1735 	     subtype == QDF_PROTO_DHCP_REQUEST))
1736 		return true;
1737 	return false;
1738 }
1739 
1740 /**
1741  * qdf_fill_wlan_connectivity_log() - Fill and queue protocol packet to logging
1742  * the logging queue
1743  * @type: Protocol type
1744  * @subtype: Protocol subtype
1745  * @dir: Rx or Tx
1746  * @qdf_tx_status: Tx completion status
1747  * @vdev_id: DP vdev ID
1748  * @data: skb data pointer
1749  *
1750  * Return: None
1751  */
1752 static
1753 void qdf_fill_wlan_connectivity_log(enum qdf_proto_type type,
1754 				    enum qdf_proto_subtype subtype,
1755 				    enum qdf_proto_dir dir,
1756 				    enum qdf_dp_tx_rx_status qdf_tx_status,
1757 				    uint8_t vdev_id, uint8_t *data)
1758 {
1759 	uint8_t pkt_type;
1760 
1761 	WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_packet_info);
1762 
1763 	if (qdf_skip_wlan_connectivity_log(type, subtype, dir))
1764 		return;
1765 
1766 	qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
1767 
1768 	wlan_diag_event.diag_cmn.timestamp_us =
1769 					qdf_get_time_of_the_day_ms() * 1000;
1770 	wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get());
1771 	wlan_diag_event.diag_cmn.vdev_id = vdev_id;
1772 
1773 	wlan_diag_event.version = DIAG_MGMT_VERSION;
1774 
1775 	if (type == QDF_PROTO_TYPE_DHCP) {
1776 		wlan_diag_event.subtype =
1777 					qdf_subtype_to_wlan_main_tag(subtype);
1778 	} else if (type == QDF_PROTO_TYPE_EAPOL) {
1779 		pkt_type = *(data + EAPOL_PACKET_TYPE_OFFSET);
1780 		if (pkt_type == EAPOL_PACKET_TYPE_EAP) {
1781 			wlan_diag_event.subtype =
1782 						qdf_get_wlan_eap_code(data);
1783 			wlan_diag_event.eap_type =
1784 						*(data + EAP_TYPE_OFFSET);
1785 			wlan_diag_event.eap_len =
1786 			   qdf_ntohs(*(uint16_t *)(data + EAP_LENGTH_OFFSET));
1787 		} else if (pkt_type == EAPOL_PACKET_TYPE_KEY) {
1788 			wlan_diag_event.subtype =
1789 					qdf_eapol_get_key_type(data, subtype);
1790 		} else if (pkt_type == EAPOL_PACKET_TYPE_START) {
1791 			wlan_diag_event.subtype =
1792 					WLAN_CONN_DIAG_EAP_START_EVENT;
1793 			wlan_diag_event.eap_len =
1794 			    qdf_ntohs(*(uint16_t *)(data + EAPOL_PKT_LEN_OFFSET));
1795 		} else {
1796 			return;
1797 		}
1798 	} else {
1799 		return;
1800 	}
1801 
1802 	/*Tx completion status needs to be logged*/
1803 	if (dir == QDF_TX)
1804 		wlan_diag_event.tx_status =
1805 					wlan_get_diag_tx_status(qdf_tx_status);
1806 
1807 	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_CONN_DP);
1808 }
1809 
1810 #elif defined(WLAN_FEATURE_CONNECTIVITY_LOGGING)
1811 /**
1812  * qdf_subtype_to_wlan_main_tag() - Convert qdf subtype to wlan main tag
1813  * @subtype: EAPoL key subtype
1814  *
1815  * Return: Wlan main tag subtype
1816  */
1817 static int qdf_subtype_to_wlan_main_tag(enum qdf_proto_subtype subtype)
1818 {
1819 	switch (subtype) {
1820 	case QDF_PROTO_DHCP_DISCOVER:
1821 		return WLAN_DHCP_DISCOVER;
1822 	case QDF_PROTO_DHCP_REQUEST:
1823 		return WLAN_DHCP_REQUEST;
1824 	case QDF_PROTO_DHCP_OFFER:
1825 		return WLAN_DHCP_OFFER;
1826 	case QDF_PROTO_DHCP_ACK:
1827 		return WLAN_DHCP_ACK;
1828 	case QDF_PROTO_DHCP_NACK:
1829 		return WLAN_DHCP_NACK;
1830 	case QDF_PROTO_EAPOL_M1:
1831 		return WLAN_EAPOL_M1;
1832 	case QDF_PROTO_EAPOL_M2:
1833 		return WLAN_EAPOL_M2;
1834 	case QDF_PROTO_EAPOL_M3:
1835 		return WLAN_EAPOL_M3;
1836 	case QDF_PROTO_EAPOL_M4:
1837 		return WLAN_EAPOL_M4;
1838 	default:
1839 		return WLAN_TAG_MAX;
1840 	}
1841 }
1842 
1843 /**
1844  * qdf_get_wlan_eap_code() - Get EAP code
1845  * @data: skb data pointer
1846  *
1847  * Return: EAP code value
1848  */
1849 static int qdf_get_wlan_eap_code(uint8_t *data)
1850 {
1851 	uint8_t code = *(data + EAP_CODE_OFFSET);
1852 
1853 	switch (code) {
1854 	case QDF_EAP_REQUEST:
1855 		return WLAN_EAP_REQUEST;
1856 	case QDF_EAP_RESPONSE:
1857 		return WLAN_EAP_RESPONSE;
1858 	case QDF_EAP_SUCCESS:
1859 		return WLAN_EAP_SUCCESS;
1860 	case QDF_EAP_FAILURE:
1861 		return WLAN_EAP_FAILURE;
1862 	default:
1863 		return WLAN_TAG_MAX;
1864 	}
1865 }
1866 
1867 /**
1868  * qdf_eapol_get_key_type() - Get EAPOL key type
1869  * @data: skb data pointer
1870  * @subtype: EAPoL key subtype
1871  *
1872  * Return: EAPOL key type
1873  */
1874 static
1875 uint8_t qdf_eapol_get_key_type(uint8_t *data, enum qdf_proto_subtype subtype)
1876 {
1877 	uint16_t key_info = *(uint16_t *)(data + EAPOL_KEY_INFO_OFFSET);
1878 
1879 	/* If key type is PTK, key type will be set in EAPOL Key info */
1880 	if (key_info & EAPOL_KEY_TYPE_MASK)
1881 		return qdf_subtype_to_wlan_main_tag(subtype);
1882 	else if (key_info & EAPOL_KEY_ENCRYPTED_MASK)
1883 		return WLAN_GTK_M1;
1884 	else
1885 		return WLAN_GTK_M2;
1886 }
1887 
1888 /**
1889  * qdf_skip_wlan_connectivity_log() - Check if connectivity log need to skip
1890  * @type: Protocol type
1891  * @subtype: Protocol subtype
1892  * @dir: Rx or Tx
1893  *
1894  * Return: true or false
1895  */
1896 static inline
1897 bool qdf_skip_wlan_connectivity_log(enum qdf_proto_type type,
1898 				    enum qdf_proto_subtype subtype,
1899 				    enum qdf_proto_dir dir)
1900 {
1901 	if ((dir == QDF_RX) && (type == QDF_PROTO_TYPE_DHCP) &&
1902 	    ((subtype == QDF_PROTO_DHCP_DISCOVER) ||
1903 	     (subtype == QDF_PROTO_DHCP_REQUEST)))
1904 		return true;
1905 	return false;
1906 }
1907 
1908 static
1909 void qdf_fill_wlan_connectivity_log(enum qdf_proto_type type,
1910 				    enum qdf_proto_subtype subtype,
1911 				    enum qdf_proto_dir dir,
1912 				    enum qdf_dp_tx_rx_status qdf_tx_status,
1913 				    uint8_t vdev_id, uint8_t *data)
1914 {
1915 	struct wlan_log_record log_buf = {0};
1916 	uint8_t pkt_type;
1917 
1918 	if (qdf_skip_wlan_connectivity_log(type, subtype, dir))
1919 		return;
1920 
1921 	log_buf.timestamp_us = qdf_get_time_of_the_day_ms() * 1000;
1922 	log_buf.ktime_us = qdf_ktime_to_us(qdf_ktime_get());
1923 	log_buf.vdev_id = vdev_id;
1924 	if (type == QDF_PROTO_TYPE_DHCP) {
1925 		log_buf.log_subtype = qdf_subtype_to_wlan_main_tag(subtype);
1926 	} else if (type == QDF_PROTO_TYPE_EAPOL) {
1927 		pkt_type = *(data + EAPOL_PACKET_TYPE_OFFSET);
1928 		if (pkt_type == EAPOL_PACKET_TYPE_EAP) {
1929 			log_buf.log_subtype = qdf_get_wlan_eap_code(data);
1930 			log_buf.pkt_info.eap_type = *(data + EAP_TYPE_OFFSET);
1931 			log_buf.pkt_info.eap_len =
1932 			   qdf_ntohs(*(uint16_t *)(data + EAP_LENGTH_OFFSET));
1933 		} else if (pkt_type == EAPOL_PACKET_TYPE_KEY) {
1934 			log_buf.log_subtype = qdf_eapol_get_key_type(data,
1935 								     subtype);
1936 		} else {
1937 			return;
1938 		}
1939 	} else {
1940 		return;
1941 	}
1942 
1943 	/*Tx completion status needs to be logged*/
1944 	if (dir == QDF_TX)
1945 		log_buf.pkt_info.tx_status = qdf_tx_status;
1946 
1947 	wlan_connectivity_log_enqueue(&log_buf);
1948 }
1949 
1950 #else
1951 static inline
1952 void qdf_fill_wlan_connectivity_log(enum qdf_proto_type type,
1953 				    enum qdf_proto_subtype subtype,
1954 				    enum qdf_proto_dir dir,
1955 				    enum qdf_dp_tx_rx_status qdf_tx_status,
1956 				    uint8_t vdev_id, uint8_t *data)
1957 {
1958 }
1959 #endif
1960 
1961 /**
1962  * qdf_log_eapol_pkt() - log EAPOL packet
1963  * @vdev_id: ID of the vdev
1964  * @skb: skb pointer
1965  * @dir: direction
1966  * @pdev_id: ID of the pdev
1967  *
1968  * Return: true/false
1969  */
1970 static bool qdf_log_eapol_pkt(uint8_t vdev_id, struct sk_buff *skb,
1971 			      enum qdf_proto_dir dir, uint8_t pdev_id)
1972 {
1973 	enum qdf_proto_subtype subtype;
1974 	uint32_t dp_eap_trace;
1975 	uint32_t dp_eap_event;
1976 
1977 	dp_eap_trace = qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
1978 	dp_eap_event = qdf_dp_get_proto_event_bitmap() &
1979 				QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
1980 
1981 	if (!dp_eap_trace && !dp_eap_event)
1982 		return false;
1983 
1984 	if (!((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_EAPOL ==
1985 	       QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1986 	      (dir == QDF_RX && qdf_nbuf_is_ipv4_eapol_pkt(skb) == true)))
1987 		return false;
1988 
1989 	subtype = qdf_nbuf_get_eapol_subtype(skb);
1990 
1991 	if (dp_eap_event && dir == QDF_RX) {
1992 		qdf_dp_log_proto_pkt_info(skb->data + QDF_NBUF_SRC_MAC_OFFSET,
1993 					  skb->data + QDF_NBUF_DEST_MAC_OFFSET,
1994 					  QDF_PROTO_TYPE_EAPOL, subtype, dir,
1995 					  QDF_TRACE_DEFAULT_MSDU_ID,
1996 					  QDF_TX_RX_STATUS_INVALID);
1997 		qdf_fill_wlan_connectivity_log(QDF_PROTO_TYPE_EAPOL, subtype,
1998 					       QDF_RX, 0, vdev_id, skb->data);
1999 	}
2000 
2001 	if (dp_eap_trace) {
2002 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
2003 		if (QDF_TX == dir)
2004 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
2005 		else if (QDF_RX == dir)
2006 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
2007 
2008 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_EAPOL_PACKET_RECORD,
2009 					       vdev_id,
2010 					       skb->data +
2011 					       QDF_NBUF_SRC_MAC_OFFSET,
2012 					       skb->data +
2013 					       QDF_NBUF_DEST_MAC_OFFSET,
2014 					       QDF_PROTO_TYPE_EAPOL, subtype,
2015 					       dir, pdev_id, true, 0));
2016 
2017 		switch (subtype) {
2018 		case QDF_PROTO_EAPOL_M1:
2019 			g_qdf_dp_trace_data.eapol_m1++;
2020 			break;
2021 		case QDF_PROTO_EAPOL_M2:
2022 			g_qdf_dp_trace_data.eapol_m2++;
2023 			break;
2024 		case QDF_PROTO_EAPOL_M3:
2025 			g_qdf_dp_trace_data.eapol_m3++;
2026 			break;
2027 		case QDF_PROTO_EAPOL_M4:
2028 			g_qdf_dp_trace_data.eapol_m4++;
2029 			break;
2030 		default:
2031 			g_qdf_dp_trace_data.eapol_others++;
2032 			break;
2033 		}
2034 	}
2035 
2036 	return true;
2037 }
2038 
2039 /**
2040  * qdf_log_dhcp_pkt() - log DHCP packet
2041  * @vdev_id: ID of the vdev
2042  * @skb: skb pointer
2043  * @dir: direction
2044  * @pdev_id: ID of the pdev
2045  *
2046  * Return: true/false
2047  */
2048 static bool qdf_log_dhcp_pkt(uint8_t vdev_id, struct sk_buff *skb,
2049 			     enum qdf_proto_dir dir, uint8_t pdev_id)
2050 {
2051 	enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
2052 	uint32_t dp_dhcp_trace;
2053 	uint32_t dp_dhcp_event;
2054 
2055 	dp_dhcp_trace = qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_DHCP;
2056 	dp_dhcp_event = qdf_dp_get_proto_event_bitmap() &
2057 				QDF_NBUF_PKT_TRAC_TYPE_DHCP;
2058 
2059 	if (!dp_dhcp_trace && !dp_dhcp_event)
2060 		return false;
2061 
2062 	if (!((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_DHCP ==
2063 	       QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
2064 	      (dir == QDF_RX && qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true)))
2065 		return false;
2066 
2067 	subtype = qdf_nbuf_get_dhcp_subtype(skb);
2068 
2069 	if (dp_dhcp_event && dir == QDF_RX) {
2070 		qdf_dp_log_proto_pkt_info(skb->data + QDF_NBUF_SRC_MAC_OFFSET,
2071 					  skb->data + QDF_NBUF_DEST_MAC_OFFSET,
2072 					  QDF_PROTO_TYPE_DHCP, subtype, dir,
2073 					  QDF_TRACE_DEFAULT_MSDU_ID,
2074 					  QDF_TX_RX_STATUS_INVALID);
2075 		qdf_fill_wlan_connectivity_log(QDF_PROTO_TYPE_DHCP, subtype,
2076 					       QDF_RX, 0, vdev_id, 0);
2077 	}
2078 
2079 	if (dp_dhcp_trace) {
2080 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
2081 		if (QDF_TX == dir)
2082 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
2083 		else if (QDF_RX == dir)
2084 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
2085 
2086 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_DHCP_PACKET_RECORD,
2087 					       vdev_id,
2088 					       skb->data +
2089 					       QDF_NBUF_SRC_MAC_OFFSET,
2090 					       skb->data +
2091 					       QDF_NBUF_DEST_MAC_OFFSET,
2092 					       QDF_PROTO_TYPE_DHCP, subtype,
2093 					       dir, pdev_id, true, 0));
2094 
2095 		switch (subtype) {
2096 		case QDF_PROTO_DHCP_DISCOVER:
2097 			g_qdf_dp_trace_data.dhcp_disc++;
2098 			break;
2099 		case QDF_PROTO_DHCP_OFFER:
2100 			g_qdf_dp_trace_data.dhcp_off++;
2101 			break;
2102 		case QDF_PROTO_DHCP_REQUEST:
2103 			g_qdf_dp_trace_data.dhcp_req++;
2104 			break;
2105 		case QDF_PROTO_DHCP_ACK:
2106 			g_qdf_dp_trace_data.dhcp_ack++;
2107 			break;
2108 		case QDF_PROTO_DHCP_NACK:
2109 			g_qdf_dp_trace_data.dhcp_nack++;
2110 			break;
2111 		default:
2112 			g_qdf_dp_trace_data.eapol_others++;
2113 			break;
2114 		}
2115 	}
2116 
2117 	return true;
2118 }
2119 
2120 /**
2121  * qdf_log_arp_pkt() - log ARP packet
2122  * @vdev_id: ID of the vdev
2123  * @skb: skb pointer
2124  * @dir: direction
2125  * @pdev_id: ID of the pdev
2126  *
2127  * Return: true/false
2128  */
2129 static bool qdf_log_arp_pkt(uint8_t vdev_id, struct sk_buff *skb,
2130 			    enum qdf_proto_dir dir, uint8_t pdev_id)
2131 {
2132 	enum qdf_proto_subtype proto_subtype;
2133 
2134 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ARP) &&
2135 		((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ARP ==
2136 			QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
2137 		 (dir == QDF_RX && qdf_nbuf_is_ipv4_arp_pkt(skb) == true))) {
2138 
2139 		proto_subtype = qdf_nbuf_get_arp_subtype(skb);
2140 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
2141 		if (QDF_TX == dir)
2142 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
2143 		else if (QDF_RX == dir)
2144 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
2145 
2146 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ARP_PACKET_RECORD,
2147 					       vdev_id,
2148 					       skb->data +
2149 					       QDF_NBUF_SRC_MAC_OFFSET,
2150 					       skb->data +
2151 					       QDF_NBUF_DEST_MAC_OFFSET,
2152 					       QDF_PROTO_TYPE_ARP,
2153 					       proto_subtype, dir, pdev_id,
2154 					       true, 0));
2155 
2156 		if (QDF_PROTO_ARP_REQ == proto_subtype)
2157 			g_qdf_dp_trace_data.arp_req++;
2158 		else
2159 			g_qdf_dp_trace_data.arp_resp++;
2160 
2161 		return true;
2162 	}
2163 	return false;
2164 }
2165 
2166 
2167 bool qdf_dp_trace_log_pkt(uint8_t vdev_id, struct sk_buff *skb,
2168 			  enum qdf_proto_dir dir, uint8_t pdev_id)
2169 {
2170 	if (!qdf_dp_get_proto_bitmap() && !qdf_dp_get_proto_event_bitmap())
2171 		return false;
2172 	if (qdf_log_arp_pkt(vdev_id, skb, dir, pdev_id))
2173 		return true;
2174 	if (qdf_log_dhcp_pkt(vdev_id, skb, dir, pdev_id))
2175 		return true;
2176 	if (qdf_log_eapol_pkt(vdev_id, skb, dir, pdev_id))
2177 		return true;
2178 	if (qdf_log_icmp_pkt(vdev_id, skb, dir, pdev_id))
2179 		return true;
2180 	if (qdf_log_icmpv6_pkt(vdev_id, skb, dir, pdev_id))
2181 		return true;
2182 	return false;
2183 }
2184 qdf_export_symbol(qdf_dp_trace_log_pkt);
2185 
2186 void qdf_dp_display_mgmt_pkt(struct qdf_dp_trace_record_s *record,
2187 			      uint16_t index, uint8_t pdev_id, uint8_t info)
2188 {
2189 	int loc;
2190 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2191 	struct qdf_dp_trace_mgmt_buf *buf =
2192 		(struct qdf_dp_trace_mgmt_buf *)record->data;
2193 
2194 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2195 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2196 					 index, info, record);
2197 
2198 	DPTRACE_PRINT("%s [%d] [%s %s]",
2199 		      prepend_str,
2200 		      buf->vdev_id,
2201 		      qdf_dp_type_to_str(buf->type),
2202 		      qdf_dp_subtype_to_str(buf->subtype));
2203 }
2204 qdf_export_symbol(qdf_dp_display_mgmt_pkt);
2205 
2206 
2207 void qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
2208 		uint8_t pdev_id, enum qdf_proto_type type,
2209 		enum qdf_proto_subtype subtype)
2210 {
2211 	struct qdf_dp_trace_mgmt_buf buf;
2212 	int buf_size = sizeof(struct qdf_dp_trace_mgmt_buf);
2213 
2214 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
2215 		return;
2216 
2217 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2218 		QDF_BUG(0);
2219 
2220 	buf.type = type;
2221 	buf.subtype = subtype;
2222 	buf.vdev_id = vdev_id;
2223 	qdf_dp_add_record(code, pdev_id, (uint8_t *)&buf, buf_size,
2224 			  NULL, 0, true);
2225 }
2226 qdf_export_symbol(qdf_dp_trace_mgmt_pkt);
2227 
2228 static void
2229 qdf_dpt_display_credit_record_debugfs(qdf_debugfs_file_t file,
2230 				      struct qdf_dp_trace_record_s *record,
2231 				      uint32_t index)
2232 {
2233 	int loc;
2234 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2235 	struct qdf_dp_trace_credit_record *buf =
2236 		(struct qdf_dp_trace_credit_record *)record->data;
2237 
2238 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2239 					 index, 0, record);
2240 	if (buf->operation == QDF_OP_NA)
2241 		qdf_debugfs_printf(file, "%s [%s] [T: %d G0: %d G1: %d]\n",
2242 				   prepend_str,
2243 				   qdf_dp_credit_source_to_str(buf->source),
2244 				   buf->total_credits, buf->g0_credit,
2245 				   buf->g1_credit);
2246 	else
2247 		qdf_debugfs_printf(file,
2248 				   "%s [%s] [T: %d G0: %d G1: %d] [%s %d]\n",
2249 				   prepend_str,
2250 				   qdf_dp_credit_source_to_str(buf->source),
2251 				   buf->total_credits, buf->g0_credit,
2252 				   buf->g1_credit,
2253 				   qdf_dp_operation_to_str(buf->operation),
2254 				   buf->delta);
2255 }
2256 
2257 void qdf_dp_display_credit_record(struct qdf_dp_trace_record_s *record,
2258 				  uint16_t index, uint8_t pdev_id, uint8_t info)
2259 {
2260 	int loc;
2261 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2262 	struct qdf_dp_trace_credit_record *buf =
2263 		(struct qdf_dp_trace_credit_record *)record->data;
2264 
2265 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2266 					 index, info, record);
2267 	if (buf->operation == QDF_OP_NA)
2268 		DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d]",
2269 			      prepend_str,
2270 			      qdf_dp_credit_source_to_str(buf->source),
2271 			      buf->total_credits, buf->g0_credit,
2272 			      buf->g1_credit);
2273 	else
2274 		DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d] [%s %d]",
2275 			      prepend_str,
2276 			      qdf_dp_credit_source_to_str(buf->source),
2277 			      buf->total_credits, buf->g0_credit,
2278 			      buf->g1_credit,
2279 			      qdf_dp_operation_to_str(buf->operation),
2280 			      buf->delta);
2281 }
2282 
2283 void qdf_dp_trace_credit_record(enum QDF_CREDIT_UPDATE_SOURCE source,
2284 				enum QDF_CREDIT_OPERATION operation,
2285 				int delta, int total_credits,
2286 				int g0_credit, int g1_credit)
2287 {
2288 	struct qdf_dp_trace_credit_record buf;
2289 	int buf_size = sizeof(struct qdf_dp_trace_credit_record);
2290 	enum QDF_DP_TRACE_ID code = QDF_DP_TRACE_TX_CREDIT_RECORD;
2291 
2292 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
2293 		return;
2294 
2295 	if (!(qdf_dp_get_proto_bitmap() & QDF_HL_CREDIT_TRACKING))
2296 		return;
2297 
2298 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2299 		QDF_BUG(0);
2300 
2301 	buf.source = source;
2302 	buf.operation = operation;
2303 	buf.delta = delta;
2304 	buf.total_credits = total_credits;
2305 	buf.g0_credit = g0_credit;
2306 	buf.g1_credit = g1_credit;
2307 
2308 	qdf_dp_add_record(code, QDF_TRACE_DEFAULT_PDEV_ID, (uint8_t *)&buf,
2309 			  buf_size, NULL, 0, false);
2310 }
2311 qdf_export_symbol(qdf_dp_trace_credit_record);
2312 
2313 void qdf_dp_display_event_record(struct qdf_dp_trace_record_s *record,
2314 			      uint16_t index, uint8_t pdev_id, uint8_t info)
2315 {
2316 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2317 	struct qdf_dp_trace_event_buf *buf =
2318 		(struct qdf_dp_trace_event_buf *)record->data;
2319 
2320 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2321 	qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2322 				   index, info, record);
2323 
2324 	DPTRACE_PRINT("%s [%d] [%s %s]",
2325 		      prepend_str,
2326 		      buf->vdev_id,
2327 		      qdf_dp_type_to_str(buf->type),
2328 		      qdf_dp_subtype_to_str(buf->subtype));
2329 }
2330 qdf_export_symbol(qdf_dp_display_event_record);
2331 
2332 void qdf_dp_trace_record_event(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
2333 			       uint8_t pdev_id, enum qdf_proto_type type,
2334 			       enum qdf_proto_subtype subtype)
2335 {
2336 	struct qdf_dp_trace_event_buf buf;
2337 	int buf_size = sizeof(struct qdf_dp_trace_event_buf);
2338 
2339 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
2340 		return;
2341 
2342 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2343 		QDF_BUG(0);
2344 
2345 	buf.type = type;
2346 	buf.subtype = subtype;
2347 	buf.vdev_id = vdev_id;
2348 	qdf_dp_add_record(code, pdev_id,
2349 			  (uint8_t *)&buf, buf_size, NULL, 0, true);
2350 }
2351 qdf_export_symbol(qdf_dp_trace_record_event);
2352 
2353 
2354 void qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s *record,
2355 			      uint16_t index, uint8_t pdev_id, uint8_t info)
2356 {
2357 	int loc;
2358 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2359 	struct qdf_dp_trace_proto_buf *buf =
2360 		(struct qdf_dp_trace_proto_buf *)record->data;
2361 
2362 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2363 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2364 					 index, info, record);
2365 	DPTRACE_PRINT("%s [%d] [%s] SA: "
2366 		      QDF_MAC_ADDR_FMT " %s DA:"
2367 		      QDF_MAC_ADDR_FMT " proto priv data = %08x",
2368 		      prepend_str,
2369 		      buf->vdev_id,
2370 		      qdf_dp_subtype_to_str(buf->subtype),
2371 		      QDF_MAC_ADDR_REF(buf->sa.bytes),
2372 		      qdf_dp_dir_to_str(buf->dir),
2373 		      QDF_MAC_ADDR_REF(buf->da.bytes),
2374 		      buf->proto_priv_data);
2375 }
2376 qdf_export_symbol(qdf_dp_display_proto_pkt);
2377 
2378 void qdf_dp_trace_proto_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
2379 		uint8_t *sa, uint8_t *da, enum qdf_proto_type type,
2380 		enum qdf_proto_subtype subtype, enum qdf_proto_dir dir,
2381 		uint8_t pdev_id, bool print, uint32_t proto_priv_data)
2382 {
2383 	struct qdf_dp_trace_proto_buf buf;
2384 	int buf_size = sizeof(struct qdf_dp_trace_proto_buf);
2385 
2386 	if (qdf_dp_enable_check(NULL, code, dir) == false)
2387 		return;
2388 
2389 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2390 		QDF_BUG(0);
2391 
2392 	memcpy(&buf.sa, sa, QDF_NET_ETH_LEN);
2393 	memcpy(&buf.da, da, QDF_NET_ETH_LEN);
2394 	buf.dir = dir;
2395 	buf.type = type;
2396 	buf.subtype = subtype;
2397 	buf.vdev_id = vdev_id;
2398 	buf.proto_priv_data = proto_priv_data;
2399 	qdf_dp_add_record(code, pdev_id,
2400 			  (uint8_t *)&buf, buf_size, NULL, 0, print);
2401 }
2402 qdf_export_symbol(qdf_dp_trace_proto_pkt);
2403 
2404 void qdf_dp_display_ptr_record(struct qdf_dp_trace_record_s *record,
2405 				uint16_t index, uint8_t pdev_id, uint8_t info)
2406 {
2407 	int loc;
2408 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2409 	struct qdf_dp_trace_ptr_buf *buf =
2410 		(struct qdf_dp_trace_ptr_buf *)record->data;
2411 	bool is_free_pkt_ptr_record = false;
2412 
2413 	if ((record->code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) ||
2414 	    (record->code == QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD))
2415 		is_free_pkt_ptr_record = true;
2416 
2417 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2418 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2419 					 index, info, record);
2420 
2421 	if (loc < sizeof(prepend_str))
2422 		scnprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2423 			  "[msdu id %d %s %d]",
2424 			  buf->msdu_id,
2425 			  is_free_pkt_ptr_record ? "status" : "vdev_id",
2426 			  buf->status);
2427 
2428 	if (info & QDF_DP_TRACE_RECORD_INFO_LIVE) {
2429 		/* In live mode donot dump the contents of the cookie */
2430 		DPTRACE_PRINT("%s", prepend_str);
2431 	} else {
2432 		dump_dp_hex_trace(prepend_str, (uint8_t *)&buf->cookie,
2433 			sizeof(buf->cookie));
2434 	}
2435 }
2436 qdf_export_symbol(qdf_dp_display_ptr_record);
2437 
2438 static
2439 enum qdf_proto_type qdf_dp_get_pkt_proto_type(qdf_nbuf_t nbuf)
2440 {
2441 	uint8_t pkt_type;
2442 
2443 	if (!nbuf)
2444 		return QDF_PROTO_TYPE_MAX;
2445 
2446 	if (qdf_nbuf_data_is_dns_query(nbuf) ||
2447 	    qdf_nbuf_data_is_dns_response(nbuf))
2448 		return QDF_PROTO_TYPE_DNS;
2449 
2450 	pkt_type = QDF_NBUF_CB_GET_PACKET_TYPE(nbuf);
2451 
2452 	switch (pkt_type) {
2453 	case QDF_NBUF_CB_PACKET_TYPE_EAPOL:
2454 		return QDF_PROTO_TYPE_EAPOL;
2455 	case QDF_NBUF_CB_PACKET_TYPE_ARP:
2456 		return QDF_PROTO_TYPE_ARP;
2457 	case QDF_NBUF_CB_PACKET_TYPE_DHCP:
2458 		return QDF_PROTO_TYPE_DHCP;
2459 	default:
2460 		return QDF_PROTO_TYPE_MAX;
2461 	}
2462 }
2463 
2464 static
2465 enum qdf_proto_subtype qdf_dp_get_pkt_subtype(qdf_nbuf_t nbuf,
2466 					      enum qdf_proto_type pkt_type)
2467 {
2468 	switch (pkt_type) {
2469 	case QDF_PROTO_TYPE_EAPOL:
2470 		return qdf_nbuf_get_eapol_subtype(nbuf);
2471 	case QDF_PROTO_TYPE_ARP:
2472 		return qdf_nbuf_get_arp_subtype(nbuf);
2473 	case QDF_PROTO_TYPE_DHCP:
2474 		return qdf_nbuf_get_dhcp_subtype(nbuf);
2475 	case QDF_PROTO_TYPE_DNS:
2476 		return (qdf_nbuf_data_is_dns_query(nbuf)) ?
2477 				QDF_PROTO_DNS_QUERY : QDF_PROTO_DNS_RES;
2478 	default:
2479 		return QDF_PROTO_INVALID;
2480 	}
2481 }
2482 
2483 static
2484 bool qdf_dp_proto_log_enable_check(enum qdf_proto_type pkt_type,
2485 				   uint16_t status)
2486 {
2487 	if (pkt_type == QDF_PROTO_TYPE_MAX)
2488 		return false;
2489 
2490 	switch (pkt_type) {
2491 	case QDF_PROTO_TYPE_EAPOL:
2492 		return qdf_dp_get_proto_event_bitmap() &
2493 				QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
2494 	case QDF_PROTO_TYPE_DHCP:
2495 		return qdf_dp_get_proto_event_bitmap() &
2496 				QDF_NBUF_PKT_TRAC_TYPE_DHCP;
2497 	case QDF_PROTO_TYPE_ARP:
2498 		if (status == QDF_TX_RX_STATUS_OK)
2499 			return false;
2500 		else
2501 			return qdf_dp_get_proto_event_bitmap() &
2502 					QDF_NBUF_PKT_TRAC_TYPE_ARP;
2503 	case QDF_PROTO_TYPE_DNS:
2504 		if (status == QDF_TX_RX_STATUS_OK)
2505 			return false;
2506 		else
2507 			return qdf_dp_get_proto_event_bitmap() &
2508 					QDF_NBUF_PKT_TRAC_TYPE_DNS;
2509 	default:
2510 		return false;
2511 	}
2512 }
2513 
2514 void qdf_dp_track_noack_check(qdf_nbuf_t nbuf, enum qdf_proto_subtype *subtype)
2515 {
2516 	enum qdf_proto_type pkt_type = qdf_dp_get_pkt_proto_type(nbuf);
2517 	uint16_t dp_track = 0;
2518 
2519 	switch (pkt_type) {
2520 	case QDF_PROTO_TYPE_EAPOL:
2521 		dp_track = qdf_dp_get_proto_bitmap() &
2522 				QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
2523 		break;
2524 	case QDF_PROTO_TYPE_DHCP:
2525 		dp_track = qdf_dp_get_proto_bitmap() &
2526 				QDF_NBUF_PKT_TRAC_TYPE_DHCP;
2527 		break;
2528 	case QDF_PROTO_TYPE_ARP:
2529 		dp_track = qdf_dp_get_proto_bitmap() &
2530 					QDF_NBUF_PKT_TRAC_TYPE_ARP;
2531 		break;
2532 	case QDF_PROTO_TYPE_DNS:
2533 		dp_track = qdf_dp_get_proto_bitmap() &
2534 					QDF_NBUF_PKT_TRAC_TYPE_DNS;
2535 		break;
2536 	default:
2537 		break;
2538 	}
2539 
2540 	if (!dp_track) {
2541 		*subtype = QDF_PROTO_INVALID;
2542 		return;
2543 	}
2544 
2545 	*subtype = qdf_dp_get_pkt_subtype(nbuf, pkt_type);
2546 }
2547 qdf_export_symbol(qdf_dp_track_noack_check);
2548 
2549 enum qdf_dp_tx_rx_status qdf_dp_get_status_from_a_status(uint8_t status)
2550 {
2551 	if (status == QDF_A_STATUS_ERROR)
2552 		return QDF_TX_RX_STATUS_INVALID;
2553 	else if (status == QDF_A_STATUS_OK)
2554 		return QDF_TX_RX_STATUS_OK;
2555 	else
2556 		return QDF_TX_RX_STATUS_MAX;
2557 }
2558 qdf_export_symbol(qdf_dp_get_status_from_a_status);
2559 
2560 void qdf_dp_trace_ptr(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
2561 		uint8_t pdev_id, uint8_t *data, uint8_t size,
2562 		uint16_t msdu_id, uint16_t buf_arg_status,
2563 		enum qdf_dp_tx_rx_status qdf_tx_status)
2564 {
2565 	struct qdf_dp_trace_ptr_buf buf;
2566 	int buf_size = sizeof(struct qdf_dp_trace_ptr_buf);
2567 	enum qdf_proto_type pkt_type;
2568 	enum qdf_proto_subtype subtype;
2569 
2570 	pkt_type = qdf_dp_get_pkt_proto_type(nbuf);
2571 	if ((code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD ||
2572 	     code == QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD) &&
2573 	    qdf_dp_proto_log_enable_check(pkt_type, qdf_tx_status)) {
2574 		subtype = qdf_dp_get_pkt_subtype(nbuf, pkt_type);
2575 		qdf_dp_log_proto_pkt_info(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET,
2576 					 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET,
2577 					 pkt_type, subtype,
2578 					 QDF_TX, msdu_id, qdf_tx_status);
2579 		qdf_fill_wlan_connectivity_log(pkt_type, subtype,
2580 					       QDF_TX, qdf_tx_status,
2581 					       QDF_NBUF_CB_TX_VDEV_CTX(nbuf),
2582 					       nbuf->data);
2583 	}
2584 
2585 	if (qdf_dp_enable_check(nbuf, code, QDF_TX) == false)
2586 		return;
2587 
2588 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2589 		QDF_BUG(0);
2590 
2591 	qdf_mem_copy(&buf.cookie, data, size);
2592 	buf.msdu_id = msdu_id;
2593 	buf.status = buf_arg_status;
2594 	qdf_dp_add_record(code, pdev_id, (uint8_t *)&buf, buf_size, NULL, 0,
2595 			  QDF_NBUF_CB_DP_TRACE_PRINT(nbuf));
2596 }
2597 qdf_export_symbol(qdf_dp_trace_ptr);
2598 
2599 void qdf_dp_trace_data_pkt(qdf_nbuf_t nbuf, uint8_t pdev_id,
2600 			   enum QDF_DP_TRACE_ID code, uint16_t msdu_id,
2601 			   enum qdf_proto_dir dir)
2602 {
2603 	struct qdf_dp_trace_data_buf buf;
2604 	enum qdf_proto_type pkt_type;
2605 
2606 	pkt_type = qdf_dp_get_pkt_proto_type(nbuf);
2607 	if (code == QDF_DP_TRACE_DROP_PACKET_RECORD &&
2608 	    qdf_dp_proto_log_enable_check(pkt_type, QDF_TX_RX_STATUS_DROP))
2609 		qdf_dp_log_proto_pkt_info(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET,
2610 					 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET,
2611 					 pkt_type,
2612 					 qdf_dp_get_pkt_subtype(nbuf, pkt_type),
2613 					 QDF_TX, msdu_id,
2614 					 QDF_TX_RX_STATUS_DROP);
2615 
2616 	buf.msdu_id = msdu_id;
2617 	if (!qdf_dp_enable_check(nbuf, code, dir))
2618 		return;
2619 
2620 	qdf_dp_add_record(code, pdev_id,
2621 			  nbuf ? qdf_nbuf_data(nbuf) : NULL,
2622 			  nbuf ? nbuf->len - nbuf->data_len : 0,
2623 			  (uint8_t *)&buf, sizeof(struct qdf_dp_trace_data_buf),
2624 			  (nbuf) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false);
2625 }
2626 
2627 qdf_export_symbol(qdf_dp_trace_data_pkt);
2628 
2629 void qdf_dp_display_record(struct qdf_dp_trace_record_s *record,
2630 			   uint16_t index, uint8_t pdev_id, uint8_t info)
2631 {
2632 	int loc;
2633 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2634 
2635 	if (!(pdev_id == QDF_TRACE_DEFAULT_PDEV_ID ||
2636 		pdev_id == record->pdev_id))
2637 		return;
2638 
2639 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2640 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2641 					 index, info, record);
2642 
2643 	switch (record->code) {
2644 	case  QDF_DP_TRACE_HDD_TX_TIMEOUT:
2645 		DPTRACE_PRINT(" %s: HDD TX Timeout", prepend_str);
2646 		break;
2647 	case  QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
2648 		DPTRACE_PRINT(" %s: HDD SoftAP TX Timeout", prepend_str);
2649 		break;
2650 	case  QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
2651 		DPTRACE_PRINT(" %s: CE Fast Packet Error", prepend_str);
2652 		break;
2653 	case QDF_DP_TRACE_LI_DP_NULL_RX_PACKET_RECORD:
2654 	default:
2655 		dump_dp_hex_trace(prepend_str, record->data, record->size);
2656 		break;
2657 	};
2658 }
2659 qdf_export_symbol(qdf_dp_display_record);
2660 
2661 void
2662 qdf_dp_display_data_pkt_record(struct qdf_dp_trace_record_s *record,
2663 			       uint16_t rec_index, uint8_t pdev_id,
2664 			       uint8_t info)
2665 {
2666 	int loc;
2667 	char prepend_str[DP_TRACE_META_DATA_STRLEN + 10];
2668 	struct qdf_dp_trace_data_buf *buf =
2669 		(struct qdf_dp_trace_data_buf *)record->data;
2670 
2671 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2672 
2673 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2674 					 rec_index, info, record);
2675 	if (loc < sizeof(prepend_str))
2676 		loc += snprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2677 				"[%d]", buf->msdu_id);
2678 	dump_dp_hex_trace(prepend_str,
2679 			  &record->data[sizeof(struct qdf_dp_trace_data_buf)],
2680 			  record->size);
2681 }
2682 
2683 void qdf_dp_trace(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code, uint8_t pdev_id,
2684 	uint8_t *data, uint8_t size, enum qdf_proto_dir dir)
2685 {
2686 
2687 	if (qdf_dp_enable_check(nbuf, code, dir) == false)
2688 		return;
2689 
2690 	qdf_dp_add_record(code, pdev_id, nbuf ? qdf_nbuf_data(nbuf) : NULL,
2691 			  size, NULL, 0,
2692 			  (nbuf) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false);
2693 }
2694 qdf_export_symbol(qdf_dp_trace);
2695 
2696 void qdf_dp_trace_spin_lock_init(void)
2697 {
2698 	spin_lock_init(&l_dp_trace_lock);
2699 }
2700 qdf_export_symbol(qdf_dp_trace_spin_lock_init);
2701 
2702 void qdf_dp_trace_disable_live_mode(void)
2703 {
2704 	g_qdf_dp_trace_data.force_live_mode = 0;
2705 }
2706 qdf_export_symbol(qdf_dp_trace_disable_live_mode);
2707 
2708 void qdf_dp_trace_enable_live_mode(void)
2709 {
2710 	g_qdf_dp_trace_data.force_live_mode = 1;
2711 }
2712 qdf_export_symbol(qdf_dp_trace_enable_live_mode);
2713 
2714 void qdf_dp_trace_clear_buffer(void)
2715 {
2716 	g_qdf_dp_trace_data.head = INVALID_QDF_DP_TRACE_ADDR;
2717 	g_qdf_dp_trace_data.tail = INVALID_QDF_DP_TRACE_ADDR;
2718 	g_qdf_dp_trace_data.num = 0;
2719 	g_qdf_dp_trace_data.dump_counter = 0;
2720 	g_qdf_dp_trace_data.num_records_to_dump = MAX_QDF_DP_TRACE_RECORDS;
2721 	if (g_qdf_dp_trace_data.enable)
2722 		memset(g_qdf_dp_trace_tbl, 0,
2723 		       MAX_QDF_DP_TRACE_RECORDS *
2724 		       sizeof(struct qdf_dp_trace_record_s));
2725 }
2726 qdf_export_symbol(qdf_dp_trace_clear_buffer);
2727 
2728 void qdf_dp_trace_dump_stats(void)
2729 {
2730 		DPTRACE_PRINT("STATS |DPT: tx %u rx %u icmp(%u %u) arp(%u %u) icmpv6(%u %u %u %u %u %u) dhcp(%u %u %u %u %u %u) eapol(%u %u %u %u %u)",
2731 			      g_qdf_dp_trace_data.tx_count,
2732 			      g_qdf_dp_trace_data.rx_count,
2733 			      g_qdf_dp_trace_data.icmp_req,
2734 			      g_qdf_dp_trace_data.icmp_resp,
2735 			      g_qdf_dp_trace_data.arp_req,
2736 			      g_qdf_dp_trace_data.arp_resp,
2737 			      g_qdf_dp_trace_data.icmpv6_req,
2738 			      g_qdf_dp_trace_data.icmpv6_resp,
2739 			      g_qdf_dp_trace_data.icmpv6_ns,
2740 			      g_qdf_dp_trace_data.icmpv6_na,
2741 			      g_qdf_dp_trace_data.icmpv6_rs,
2742 			      g_qdf_dp_trace_data.icmpv6_ra,
2743 			      g_qdf_dp_trace_data.dhcp_disc,
2744 			      g_qdf_dp_trace_data.dhcp_off,
2745 			      g_qdf_dp_trace_data.dhcp_req,
2746 			      g_qdf_dp_trace_data.dhcp_ack,
2747 			      g_qdf_dp_trace_data.dhcp_nack,
2748 			      g_qdf_dp_trace_data.dhcp_others,
2749 			      g_qdf_dp_trace_data.eapol_m1,
2750 			      g_qdf_dp_trace_data.eapol_m2,
2751 			      g_qdf_dp_trace_data.eapol_m3,
2752 			      g_qdf_dp_trace_data.eapol_m4,
2753 			      g_qdf_dp_trace_data.eapol_others);
2754 }
2755 qdf_export_symbol(qdf_dp_trace_dump_stats);
2756 
2757 /**
2758  * qdf_dpt_dump_hex_trace_debugfs() - read data in file
2759  * @file: file to read
2760  * @str: string to prepend the hexdump with.
2761  * @buf: buffer which contains data to be written
2762  * @buf_len: defines the size of the data to be written
2763  *
2764  * Return: None
2765  */
2766 static void qdf_dpt_dump_hex_trace_debugfs(qdf_debugfs_file_t file,
2767 				char *str, uint8_t *buf, uint8_t buf_len)
2768 {
2769 	unsigned char linebuf[BUFFER_SIZE];
2770 	const u8 *ptr = buf;
2771 	int i, linelen, remaining = buf_len;
2772 
2773 	/* Dump the bytes in the last line */
2774 	for (i = 0; i < buf_len; i += ROW_SIZE) {
2775 		linelen = min(remaining, ROW_SIZE);
2776 		remaining -= ROW_SIZE;
2777 
2778 		hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1,
2779 				linebuf, sizeof(linebuf), false);
2780 
2781 		qdf_debugfs_printf(file, "%s %s\n", str, linebuf);
2782 	}
2783 }
2784 
2785 /**
2786  * qdf_dpt_display_proto_pkt_debugfs() - display proto packet
2787  * @file: file to read
2788  * @record: dptrace record
2789  * @index: index
2790  *
2791  * Return: none
2792  */
2793 static void qdf_dpt_display_proto_pkt_debugfs(qdf_debugfs_file_t file,
2794 				struct qdf_dp_trace_record_s *record,
2795 				uint32_t index)
2796 {
2797 	int loc;
2798 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2799 	struct qdf_dp_trace_proto_buf *buf =
2800 		(struct qdf_dp_trace_proto_buf *)record->data;
2801 
2802 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2803 					 index, 0, record);
2804 	qdf_debugfs_printf(file, "%s [%d] [%s] SA: "
2805 			   QDF_MAC_ADDR_FMT " %s DA: "
2806 			   QDF_MAC_ADDR_FMT,
2807 			   prepend_str,
2808 			   buf->vdev_id,
2809 			   qdf_dp_subtype_to_str(buf->subtype),
2810 			   QDF_MAC_ADDR_REF(buf->sa.bytes),
2811 			   qdf_dp_dir_to_str(buf->dir),
2812 			   QDF_MAC_ADDR_REF(buf->da.bytes));
2813 	qdf_debugfs_printf(file, "\n");
2814 }
2815 
2816 /**
2817  * qdf_dpt_display_mgmt_pkt_debugfs() - display mgmt packet
2818  * @file: file to read
2819  * @record: dptrace record
2820  * @index: index
2821  *
2822  * Return: none
2823  */
2824 static void qdf_dpt_display_mgmt_pkt_debugfs(qdf_debugfs_file_t file,
2825 				struct qdf_dp_trace_record_s *record,
2826 				uint32_t index)
2827 {
2828 
2829 	int loc;
2830 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2831 	struct qdf_dp_trace_mgmt_buf *buf =
2832 		(struct qdf_dp_trace_mgmt_buf *)record->data;
2833 
2834 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2835 					 index, 0, record);
2836 
2837 	qdf_debugfs_printf(file, "%s [%d] [%s %s]\n",
2838 			   prepend_str,
2839 			   buf->vdev_id,
2840 			   qdf_dp_type_to_str(buf->type),
2841 			   qdf_dp_subtype_to_str(buf->subtype));
2842 }
2843 
2844 /**
2845  * qdf_dpt_display_event_record_debugfs() - display event records
2846  * @file: file to read
2847  * @record: dptrace record
2848  * @index: index
2849  *
2850  * Return: none
2851  */
2852 static void qdf_dpt_display_event_record_debugfs(qdf_debugfs_file_t file,
2853 				struct qdf_dp_trace_record_s *record,
2854 				uint32_t index)
2855 {
2856 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2857 	struct qdf_dp_trace_event_buf *buf =
2858 		(struct qdf_dp_trace_event_buf *)record->data;
2859 
2860 	qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2861 				   index, 0, record);
2862 	qdf_debugfs_printf(file, "%s [%d] [%s %s]\n",
2863 			   prepend_str,
2864 			   buf->vdev_id,
2865 			   qdf_dp_type_to_str(buf->type),
2866 			   qdf_dp_subtype_to_str(buf->subtype));
2867 }
2868 
2869 /**
2870  * qdf_dpt_display_ptr_record_debugfs() - display record ptr
2871  * @file: file to read
2872  * @record: dptrace record
2873  * @index: index
2874  *
2875  * Return: none
2876  */
2877 static void qdf_dpt_display_ptr_record_debugfs(qdf_debugfs_file_t file,
2878 				struct qdf_dp_trace_record_s *record,
2879 				uint32_t index)
2880 {
2881 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2882 	int loc;
2883 	struct qdf_dp_trace_ptr_buf *buf =
2884 		(struct qdf_dp_trace_ptr_buf *)record->data;
2885 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2886 					 index, 0, record);
2887 
2888 	if (loc < sizeof(prepend_str))
2889 		scnprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2890 			  "[msdu id %d %s %d]",
2891 			  buf->msdu_id,
2892 			  (record->code ==
2893 				QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) ?
2894 			  "status" : "vdev_id",
2895 			  buf->status);
2896 
2897 	qdf_dpt_dump_hex_trace_debugfs(file, prepend_str,
2898 				       (uint8_t *)&buf->cookie,
2899 				       sizeof(buf->cookie));
2900 }
2901 
2902 /**
2903  * qdf_dpt_display_record_debugfs() - display record
2904  * @file: file to read
2905  * @record: dptrace record
2906  * @index: index
2907  *
2908  * Return: none
2909  */
2910 static void qdf_dpt_display_record_debugfs(qdf_debugfs_file_t file,
2911 				struct qdf_dp_trace_record_s *record,
2912 				uint32_t index)
2913 {
2914 	int loc;
2915 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2916 	struct qdf_dp_trace_data_buf *buf =
2917 		(struct qdf_dp_trace_data_buf *)record->data;
2918 
2919 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2920 					 index, 0, record);
2921 	if (loc < sizeof(prepend_str))
2922 		loc += snprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2923 				"[%d]", buf->msdu_id);
2924 	qdf_dpt_dump_hex_trace_debugfs(file, prepend_str,
2925 				       record->data, record->size);
2926 }
2927 
2928 uint32_t qdf_dpt_get_curr_pos_debugfs(qdf_debugfs_file_t file,
2929 				      enum qdf_dpt_debugfs_state state)
2930 {
2931 	uint32_t i = 0;
2932 	uint32_t tail;
2933 	uint32_t count = g_qdf_dp_trace_data.num;
2934 
2935 	if (!g_qdf_dp_trace_data.enable) {
2936 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
2937 		  "%s: Tracing Disabled", __func__);
2938 		return QDF_STATUS_E_EMPTY;
2939 	}
2940 
2941 	if (!count) {
2942 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
2943 		  "%s: no packets", __func__);
2944 		return QDF_STATUS_E_EMPTY;
2945 	}
2946 
2947 	if (state == QDF_DPT_DEBUGFS_STATE_SHOW_IN_PROGRESS)
2948 		return g_qdf_dp_trace_data.curr_pos;
2949 
2950 	qdf_debugfs_printf(file,
2951 		"DPT: config - bitmap 0x%x verb %u #rec %u rec_requested %u live_config %u thresh %u time_limit %u\n",
2952 		g_qdf_dp_trace_data.proto_bitmap,
2953 		g_qdf_dp_trace_data.verbosity,
2954 		g_qdf_dp_trace_data.no_of_record,
2955 		g_qdf_dp_trace_data.num_records_to_dump,
2956 		g_qdf_dp_trace_data.live_mode_config,
2957 		g_qdf_dp_trace_data.high_tput_thresh,
2958 		g_qdf_dp_trace_data.thresh_time_limit);
2959 
2960 	qdf_debugfs_printf(file,
2961 		"STATS |DPT: icmp(%u %u) arp(%u %u) icmpv6(%u %u %u %u %u %u) dhcp(%u %u %u %u %u %u) eapol(%u %u %u %u %u)\n",
2962 		g_qdf_dp_trace_data.icmp_req,
2963 		g_qdf_dp_trace_data.icmp_resp,
2964 		g_qdf_dp_trace_data.arp_req,
2965 		g_qdf_dp_trace_data.arp_resp,
2966 		g_qdf_dp_trace_data.icmpv6_req,
2967 		g_qdf_dp_trace_data.icmpv6_resp,
2968 		g_qdf_dp_trace_data.icmpv6_ns,
2969 		g_qdf_dp_trace_data.icmpv6_na,
2970 		g_qdf_dp_trace_data.icmpv6_rs,
2971 		g_qdf_dp_trace_data.icmpv6_ra,
2972 		g_qdf_dp_trace_data.dhcp_disc,
2973 		g_qdf_dp_trace_data.dhcp_off,
2974 		g_qdf_dp_trace_data.dhcp_req,
2975 		g_qdf_dp_trace_data.dhcp_ack,
2976 		g_qdf_dp_trace_data.dhcp_nack,
2977 		g_qdf_dp_trace_data.dhcp_others,
2978 		g_qdf_dp_trace_data.eapol_m1,
2979 		g_qdf_dp_trace_data.eapol_m2,
2980 		g_qdf_dp_trace_data.eapol_m3,
2981 		g_qdf_dp_trace_data.eapol_m4,
2982 		g_qdf_dp_trace_data.eapol_others);
2983 
2984 	qdf_debugfs_printf(file,
2985 		"DPT: Total Records: %d, Head: %d, Tail: %d\n",
2986 		g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head,
2987 		g_qdf_dp_trace_data.tail);
2988 
2989 	spin_lock_bh(&l_dp_trace_lock);
2990 	if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) {
2991 		i = g_qdf_dp_trace_data.head;
2992 		tail = g_qdf_dp_trace_data.tail;
2993 
2994 		if (count > g_qdf_dp_trace_data.num)
2995 			count = g_qdf_dp_trace_data.num;
2996 
2997 		if (tail >= (count - 1))
2998 			i = tail - count + 1;
2999 		else if (count != MAX_QDF_DP_TRACE_RECORDS)
3000 			i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) -
3001 						     tail);
3002 		g_qdf_dp_trace_data.curr_pos = 0;
3003 		g_qdf_dp_trace_data.saved_tail = tail;
3004 	}
3005 	spin_unlock_bh(&l_dp_trace_lock);
3006 
3007 	return g_qdf_dp_trace_data.saved_tail;
3008 }
3009 qdf_export_symbol(qdf_dpt_get_curr_pos_debugfs);
3010 
3011 QDF_STATUS qdf_dpt_dump_stats_debugfs(qdf_debugfs_file_t file,
3012 				      uint32_t curr_pos)
3013 {
3014 	struct qdf_dp_trace_record_s p_record;
3015 	uint32_t i = curr_pos;
3016 	uint16_t num_records_to_dump = g_qdf_dp_trace_data.num_records_to_dump;
3017 
3018 	if (!g_qdf_dp_trace_data.enable) {
3019 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
3020 			  "%s: Tracing Disabled", __func__);
3021 		return QDF_STATUS_E_FAILURE;
3022 	}
3023 
3024 	if (num_records_to_dump > g_qdf_dp_trace_data.num)
3025 		num_records_to_dump = g_qdf_dp_trace_data.num;
3026 
3027 	/*
3028 	 * Max dp trace record size should always be less than
3029 	 * QDF_DP_TRACE_PREPEND_STR_SIZE(100) + BUFFER_SIZE(121).
3030 	 */
3031 	if (WARN_ON(QDF_DP_TRACE_MAX_RECORD_SIZE <
3032 				QDF_DP_TRACE_PREPEND_STR_SIZE + BUFFER_SIZE))
3033 		return QDF_STATUS_E_FAILURE;
3034 
3035 	spin_lock_bh(&l_dp_trace_lock);
3036 	p_record = g_qdf_dp_trace_tbl[i];
3037 	spin_unlock_bh(&l_dp_trace_lock);
3038 
3039 	for (;; ) {
3040 		/*
3041 		 * Initially we get file as 1 page size, and
3042 		 * if remaining size in file is less than one record max size,
3043 		 * then return so that it gets an extra page.
3044 		 */
3045 		if ((file->size - file->count) < QDF_DP_TRACE_MAX_RECORD_SIZE) {
3046 			spin_lock_bh(&l_dp_trace_lock);
3047 			g_qdf_dp_trace_data.curr_pos = i;
3048 			spin_unlock_bh(&l_dp_trace_lock);
3049 			return QDF_STATUS_E_FAILURE;
3050 		}
3051 
3052 		switch (p_record.code) {
3053 		case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD:
3054 		case QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD:
3055 		case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD:
3056 			qdf_dpt_display_ptr_record_debugfs(file, &p_record, i);
3057 			break;
3058 
3059 		case QDF_DP_TRACE_EAPOL_PACKET_RECORD:
3060 		case QDF_DP_TRACE_DHCP_PACKET_RECORD:
3061 		case QDF_DP_TRACE_ARP_PACKET_RECORD:
3062 		case QDF_DP_TRACE_ICMP_PACKET_RECORD:
3063 		case QDF_DP_TRACE_ICMPv6_PACKET_RECORD:
3064 			qdf_dpt_display_proto_pkt_debugfs(file, &p_record, i);
3065 			break;
3066 
3067 		case QDF_DP_TRACE_TX_CREDIT_RECORD:
3068 			qdf_dpt_display_credit_record_debugfs(file, &p_record,
3069 							      i);
3070 			break;
3071 
3072 		case QDF_DP_TRACE_MGMT_PACKET_RECORD:
3073 			qdf_dpt_display_mgmt_pkt_debugfs(file, &p_record, i);
3074 			break;
3075 
3076 		case QDF_DP_TRACE_EVENT_RECORD:
3077 			qdf_dpt_display_event_record_debugfs(file, &p_record,
3078 							     i);
3079 			break;
3080 
3081 		case QDF_DP_TRACE_HDD_TX_TIMEOUT:
3082 			qdf_debugfs_printf(
3083 					file, "DPT: %04d: %llu %s\n",
3084 					i, p_record.time,
3085 					qdf_dp_code_to_string(p_record.code));
3086 			qdf_debugfs_printf(file, "HDD TX Timeout\n");
3087 			break;
3088 
3089 		case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
3090 			qdf_debugfs_printf(
3091 					file, "DPT: %04d: %llu %s\n",
3092 					i, p_record.time,
3093 					qdf_dp_code_to_string(p_record.code));
3094 			qdf_debugfs_printf(file, "HDD SoftAP TX Timeout\n");
3095 			break;
3096 
3097 		case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
3098 			qdf_debugfs_printf(
3099 					file, "DPT: %04d: %llu %s\n",
3100 					i, p_record.time,
3101 					qdf_dp_code_to_string(p_record.code));
3102 			qdf_debugfs_printf(file, "CE Fast Packet Error\n");
3103 			break;
3104 
3105 		case QDF_DP_TRACE_MAX:
3106 			qdf_debugfs_printf(file,
3107 				"%s: QDF_DP_TRACE_MAX event should not be generated\n",
3108 				__func__);
3109 			break;
3110 
3111 		case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
3112 		case QDF_DP_TRACE_HDD_RX_PACKET_RECORD:
3113 		case QDF_DP_TRACE_TX_PACKET_RECORD:
3114 		case QDF_DP_TRACE_RX_PACKET_RECORD:
3115 		case QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD:
3116 		case QDF_DP_TRACE_LI_DP_RX_PACKET_RECORD:
3117 
3118 		default:
3119 			qdf_dpt_display_record_debugfs(file, &p_record, i);
3120 			break;
3121 		}
3122 
3123 		if (++g_qdf_dp_trace_data.dump_counter == num_records_to_dump)
3124 			break;
3125 
3126 		spin_lock_bh(&l_dp_trace_lock);
3127 		if (i == 0)
3128 			i = MAX_QDF_DP_TRACE_RECORDS;
3129 
3130 		i -= 1;
3131 		p_record = g_qdf_dp_trace_tbl[i];
3132 		spin_unlock_bh(&l_dp_trace_lock);
3133 	}
3134 
3135 	g_qdf_dp_trace_data.dump_counter = 0;
3136 
3137 	return QDF_STATUS_SUCCESS;
3138 }
3139 qdf_export_symbol(qdf_dpt_dump_stats_debugfs);
3140 
3141 void qdf_dpt_set_value_debugfs(uint8_t proto_bitmap, uint8_t no_of_record,
3142 			    uint8_t verbosity, uint16_t num_records_to_dump)
3143 {
3144 	if (g_qdf_dp_trace_data.enable) {
3145 		g_qdf_dp_trace_data.proto_bitmap = proto_bitmap;
3146 		g_qdf_dp_trace_data.no_of_record = no_of_record;
3147 		g_qdf_dp_trace_data.verbosity    = verbosity;
3148 		g_qdf_dp_trace_data.num_records_to_dump = num_records_to_dump;
3149 	}
3150 }
3151 qdf_export_symbol(qdf_dpt_set_value_debugfs);
3152 
3153 
3154 void qdf_dp_trace_dump_all(uint32_t count, uint8_t pdev_id)
3155 {
3156 	struct qdf_dp_trace_record_s p_record;
3157 	int32_t i, tail;
3158 
3159 	if (!g_qdf_dp_trace_data.enable) {
3160 		DPTRACE_PRINT("Tracing Disabled");
3161 		return;
3162 	}
3163 
3164 	DPTRACE_PRINT(
3165 		"DPT: config - bitmap 0x%x verb %u #rec %u live_config %u thresh %u time_limit %u",
3166 		g_qdf_dp_trace_data.proto_bitmap,
3167 		g_qdf_dp_trace_data.verbosity,
3168 		g_qdf_dp_trace_data.no_of_record,
3169 		g_qdf_dp_trace_data.live_mode_config,
3170 		g_qdf_dp_trace_data.high_tput_thresh,
3171 		g_qdf_dp_trace_data.thresh_time_limit);
3172 
3173 	qdf_dp_trace_dump_stats();
3174 
3175 	DPTRACE_PRINT("DPT: Total Records: %d, Head: %d, Tail: %d",
3176 		      g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head,
3177 		      g_qdf_dp_trace_data.tail);
3178 
3179 	/* acquire the lock so that only one thread at a time can read
3180 	 * the ring buffer
3181 	 */
3182 	spin_lock_bh(&l_dp_trace_lock);
3183 
3184 	if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) {
3185 		i = g_qdf_dp_trace_data.head;
3186 		tail = g_qdf_dp_trace_data.tail;
3187 
3188 		if (count) {
3189 			if (count > g_qdf_dp_trace_data.num)
3190 				count = g_qdf_dp_trace_data.num;
3191 			if (tail >= (count - 1))
3192 				i = tail - count + 1;
3193 			else if (count != MAX_QDF_DP_TRACE_RECORDS)
3194 				i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) -
3195 							     tail);
3196 		}
3197 
3198 		p_record = g_qdf_dp_trace_tbl[i];
3199 		spin_unlock_bh(&l_dp_trace_lock);
3200 		for (;; ) {
3201 			qdf_dp_trace_cb_table[p_record.code](&p_record,
3202 							(uint16_t)i, pdev_id, false);
3203 			if (i == tail)
3204 				break;
3205 			i += 1;
3206 
3207 			spin_lock_bh(&l_dp_trace_lock);
3208 			if (MAX_QDF_DP_TRACE_RECORDS == i)
3209 				i = 0;
3210 
3211 			p_record = g_qdf_dp_trace_tbl[i];
3212 			spin_unlock_bh(&l_dp_trace_lock);
3213 		}
3214 	} else {
3215 		spin_unlock_bh(&l_dp_trace_lock);
3216 	}
3217 }
3218 qdf_export_symbol(qdf_dp_trace_dump_all);
3219 
3220 void qdf_dp_trace_throttle_live_mode(bool high_bw_request)
3221 {
3222 	static int bw_interval_counter;
3223 
3224 	if (g_qdf_dp_trace_data.enable == false ||
3225 		g_qdf_dp_trace_data.live_mode_config == false)
3226 		return;
3227 
3228 	if (high_bw_request) {
3229 		g_qdf_dp_trace_data.live_mode = 0;
3230 		bw_interval_counter = 0;
3231 		return;
3232 	}
3233 
3234 	bw_interval_counter++;
3235 
3236 	if (0 == (bw_interval_counter %
3237 			g_qdf_dp_trace_data.thresh_time_limit)) {
3238 
3239 		spin_lock_bh(&l_dp_trace_lock);
3240 			if (g_qdf_dp_trace_data.print_pkt_cnt <=
3241 				g_qdf_dp_trace_data.high_tput_thresh)
3242 				g_qdf_dp_trace_data.live_mode = 1;
3243 
3244 		g_qdf_dp_trace_data.print_pkt_cnt = 0;
3245 		spin_unlock_bh(&l_dp_trace_lock);
3246 	}
3247 }
3248 qdf_export_symbol(qdf_dp_trace_throttle_live_mode);
3249 
3250 void qdf_dp_trace_apply_tput_policy(bool is_data_traffic)
3251 {
3252 	if (g_qdf_dp_trace_data.dynamic_verbosity_modify) {
3253 		goto check_live_mode;
3254 		return;
3255 	}
3256 
3257 	if (is_data_traffic) {
3258 		g_qdf_dp_trace_data.verbosity =
3259 					QDF_DP_TRACE_VERBOSITY_ULTRA_LOW;
3260 	} else {
3261 		g_qdf_dp_trace_data.verbosity =
3262 					g_qdf_dp_trace_data.ini_conf_verbosity;
3263 	}
3264 check_live_mode:
3265 	qdf_dp_trace_throttle_live_mode(is_data_traffic);
3266 }
3267 #endif
3268 
3269 struct qdf_print_ctrl print_ctrl_obj[MAX_PRINT_CONFIG_SUPPORTED];
3270 
3271 struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = {
3272 	[QDF_MODULE_ID_TDLS] = {"tdls"},
3273 	[QDF_MODULE_ID_ACS] = {"ACS"},
3274 	[QDF_MODULE_ID_SCAN_SM] = {"scan state machine"},
3275 	[QDF_MODULE_ID_SCANENTRY] = {"scan entry"},
3276 	[QDF_MODULE_ID_WDS] = {"WDS"},
3277 	[QDF_MODULE_ID_ACTION] = {"action"},
3278 	[QDF_MODULE_ID_ROAM] = {"STA roaming"},
3279 	[QDF_MODULE_ID_INACT] = {"inactivity"},
3280 	[QDF_MODULE_ID_DOTH] = {"11h"},
3281 	[QDF_MODULE_ID_IQUE] = {"IQUE"},
3282 	[QDF_MODULE_ID_WME] = {"WME"},
3283 	[QDF_MODULE_ID_ACL] = {"ACL"},
3284 	[QDF_MODULE_ID_WPA] = {"WPA/RSN"},
3285 	[QDF_MODULE_ID_RADKEYS] = {"dump 802.1x keys"},
3286 	[QDF_MODULE_ID_RADDUMP] = {"dump radius packet"},
3287 	[QDF_MODULE_ID_RADIUS] = {"802.1x radius client"},
3288 	[QDF_MODULE_ID_DOT1XSM] = {"802.1x state machine"},
3289 	[QDF_MODULE_ID_DOT1X] = {"802.1x authenticator"},
3290 	[QDF_MODULE_ID_POWER] = {"power save"},
3291 	[QDF_MODULE_ID_STATE] = {"state"},
3292 	[QDF_MODULE_ID_OUTPUT] = {"output"},
3293 	[QDF_MODULE_ID_SCAN] = {"scan"},
3294 	[QDF_MODULE_ID_AUTH] = {"authentication"},
3295 	[QDF_MODULE_ID_ASSOC] = {"association"},
3296 	[QDF_MODULE_ID_NODE] = {"node"},
3297 	[QDF_MODULE_ID_ELEMID] = {"element ID"},
3298 	[QDF_MODULE_ID_XRATE] = {"rate"},
3299 	[QDF_MODULE_ID_INPUT] = {"input"},
3300 	[QDF_MODULE_ID_CRYPTO] = {"crypto"},
3301 	[QDF_MODULE_ID_DUMPPKTS] = {"dump packet"},
3302 	[QDF_MODULE_ID_DEBUG] = {"debug"},
3303 	[QDF_MODULE_ID_MLME] = {"mlme"},
3304 	[QDF_MODULE_ID_RRM] = {"rrm"},
3305 	[QDF_MODULE_ID_WNM] = {"wnm"},
3306 	[QDF_MODULE_ID_P2P_PROT] = {"p2p_prot"},
3307 	[QDF_MODULE_ID_PROXYARP] = {"proxyarp"},
3308 	[QDF_MODULE_ID_L2TIF] = {"l2tif"},
3309 	[QDF_MODULE_ID_WIFIPOS] = {"wifipos"},
3310 	[QDF_MODULE_ID_WRAP] = {"wrap"},
3311 	[QDF_MODULE_ID_DFS] = {"dfs"},
3312 	[QDF_MODULE_ID_ATF] = {"atf"},
3313 	[QDF_MODULE_ID_SPLITMAC] = {"splitmac"},
3314 	[QDF_MODULE_ID_IOCTL] = {"ioctl"},
3315 	[QDF_MODULE_ID_NAC] = {"nac"},
3316 	[QDF_MODULE_ID_MESH] = {"mesh"},
3317 	[QDF_MODULE_ID_MBO] = {"mbo"},
3318 	[QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = {"extchanswitch"},
3319 	[QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = {"extchanscan"},
3320 	[QDF_MODULE_ID_TLSHIM] = {"tlshim"},
3321 	[QDF_MODULE_ID_WMI] = {"WMI"},
3322 	[QDF_MODULE_ID_HTT] = {"HTT"},
3323 	[QDF_MODULE_ID_HDD] = {"HDD"},
3324 	[QDF_MODULE_ID_SME] = {"SME"},
3325 	[QDF_MODULE_ID_PE] = {"PE"},
3326 	[QDF_MODULE_ID_WMA] = {"WMA"},
3327 	[QDF_MODULE_ID_SYS] = {"SYS"},
3328 	[QDF_MODULE_ID_QDF] = {"QDF"},
3329 	[QDF_MODULE_ID_SAP] = {"SAP"},
3330 	[QDF_MODULE_ID_HDD_SOFTAP] = {"HDD_SAP"},
3331 	[QDF_MODULE_ID_HDD_DATA] = {"DATA"},
3332 	[QDF_MODULE_ID_HDD_SAP_DATA] = {"SAP_DATA"},
3333 	[QDF_MODULE_ID_HIF] = {"HIF"},
3334 	[QDF_MODULE_ID_HTC] = {"HTC"},
3335 	[QDF_MODULE_ID_TXRX] = {"TXRX"},
3336 	[QDF_MODULE_ID_QDF_DEVICE] = {"QDF_DEV"},
3337 	[QDF_MODULE_ID_CFG] = {"CFG"},
3338 	[QDF_MODULE_ID_BMI] = {"BMI"},
3339 	[QDF_MODULE_ID_EPPING] = {"EPPING"},
3340 	[QDF_MODULE_ID_QVIT] = {"QVIT"},
3341 	[QDF_MODULE_ID_DP] = {"DP"},
3342 	[QDF_MODULE_ID_HAL] = {"HAL"},
3343 	[QDF_MODULE_ID_SOC] = {"SOC"},
3344 	[QDF_MODULE_ID_OS_IF] = {"OSIF"},
3345 	[QDF_MODULE_ID_TARGET_IF] = {"TIF"},
3346 	[QDF_MODULE_ID_SCHEDULER] = {"SCH"},
3347 	[QDF_MODULE_ID_MGMT_TXRX] = {"MGMT_TXRX"},
3348 	[QDF_MODULE_ID_PMO] = {"PMO"},
3349 	[QDF_MODULE_ID_POLICY_MGR] = {"POLICY_MGR"},
3350 	[QDF_MODULE_ID_SA_API] = {"SA_API"},
3351 	[QDF_MODULE_ID_NAN] = {"NAN"},
3352 	[QDF_MODULE_ID_SPECTRAL] = {"SPECTRAL"},
3353 	[QDF_MODULE_ID_P2P] = {"P2P"},
3354 	[QDF_MODULE_ID_OFFCHAN_TXRX] = {"OFFCHAN"},
3355 	[QDF_MODULE_ID_REGULATORY] = {"REGULATORY"},
3356 	[QDF_MODULE_ID_OBJ_MGR] = {"OBJMGR"},
3357 	[QDF_MODULE_ID_SERIALIZATION] = {"SER"},
3358 	[QDF_MODULE_ID_NSS] = {"NSS"},
3359 	[QDF_MODULE_ID_ROAM_DEBUG] = {"roam debug"},
3360 	[QDF_MODULE_ID_DIRECT_BUF_RX] = {"DIRECT_BUF_RX"},
3361 	[QDF_MODULE_ID_DISA] = {"disa"},
3362 	[QDF_MODULE_ID_GREEN_AP] = {"GREEN_AP"},
3363 	[QDF_MODULE_ID_FD] = {"FILS discovery"},
3364 	[QDF_MODULE_ID_FTM] = {"FTM"},
3365 	[QDF_MODULE_ID_OCB] = {"OCB"},
3366 	[QDF_MODULE_ID_CONFIG] = {"CONFIG"},
3367 	[QDF_MODULE_ID_IPA] = {"IPA"},
3368 	[QDF_MODULE_ID_CP_STATS] = {"CP_STATS"},
3369 	[QDF_MODULE_ID_DCS] = {"DCS"},
3370 	[QDF_MODULE_ID_ACTION_OUI] = {"action_oui"},
3371 	[QDF_MODULE_ID_TARGET] = {"TARGET"},
3372 	[QDF_MODULE_ID_MBSSIE] = {"MBSSIE"},
3373 	[QDF_MODULE_ID_FWOL] = {"fwol"},
3374 	[QDF_MODULE_ID_SM_ENGINE] = {"SM_ENG"},
3375 	[QDF_MODULE_ID_CMN_MLME] = {"CMN_MLME"},
3376 	[QDF_MODULE_ID_BSSCOLOR] = {"BSSCOLOR"},
3377 	[QDF_MODULE_ID_CFR] = {"CFR"},
3378 	[QDF_MODULE_ID_DP_TX_CAPTURE] = {"TX_CAPTURE_ENHANCE"},
3379 	[QDF_MODULE_ID_INTEROP_ISSUES_AP] = {"INTEROP_ISSUES_AP"},
3380 	[QDF_MODULE_ID_DENYLIST_MGR] = {"dlm"},
3381 	[QDF_MODULE_ID_QLD] = {"QLD"},
3382 	[QDF_MODULE_ID_DYNAMIC_MODE_CHG] = {"Dynamic Mode Change"},
3383 	[QDF_MODULE_ID_COEX] = {"COEX"},
3384 	[QDF_MODULE_ID_MON_FILTER] = {"Monitor Filter"},
3385 	[QDF_MODULE_ID_PKT_CAPTURE] = {"pkt_capture"},
3386 	[QDF_MODULE_ID_RPTR] = {"RPTR"},
3387 	[QDF_MODULE_ID_6GHZ] = {"6GHZ"},
3388 	[QDF_MODULE_ID_IOT_SIM] = {"IOT_SIM"},
3389 	[QDF_MODULE_ID_MSCS] = {"MSCS"},
3390 	[QDF_MODULE_ID_GPIO] = {"GPIO_CFG"},
3391 	[QDF_MODULE_ID_IFMGR] = {"IF_MGR"},
3392 	[QDF_MODULE_ID_DIAG] = {"DIAG"},
3393 	[QDF_MODULE_ID_DP_INIT] = {"DP_INIT"},
3394 	[QDF_MODULE_ID_DP_TX] = {"DP_TX"},
3395 	[QDF_MODULE_ID_DP_RX] = {"DP_RX"},
3396 	[QDF_MODULE_ID_DP_STATS] = {"DP_STATS"},
3397 	[QDF_MODULE_ID_DP_HTT] = {"DP_HTT"},
3398 	[QDF_MODULE_ID_DP_PEER] = {"DP_PEER"},
3399 	[QDF_MODULE_ID_DP_RX_ERROR] = {"DP_RX_ERROR"},
3400 	[QDF_MODULE_ID_DP_HTT_TX_STATS] = {"DP_HTT_TX_STATS"},
3401 	[QDF_MODULE_ID_DP_RX_MON_STATUS] = {"DP_RX_MON_STATUS"},
3402 	[QDF_MODULE_ID_DP_RX_MON_DEST] = {"DP_RX_MON_DEST"},
3403 	[QDF_MODULE_ID_DP_REO] = {"DP_REO"},
3404 	[QDF_MODULE_ID_DP_TX_COMP] = {"DP_TX_COMP"},
3405 	[QDF_MODULE_ID_DP_VDEV] = {"DP_VDEV"},
3406 	[QDF_MODULE_ID_DP_CDP] = {"DP_CDP"},
3407 	[QDF_MODULE_ID_TSO] = {"TSO"},
3408 	[QDF_MODULE_ID_ME] = {"ME"},
3409 	[QDF_MODULE_ID_QWRAP] = {"QWRAP"},
3410 	[QDF_MODULE_ID_DBDC_REP] = {"DBDC_REP"},
3411 	[QDF_MODULE_ID_EXT_AP] = {"EXT_AP"},
3412 	[QDF_MODULE_ID_MLO] = {"MLO_MGR"},
3413 	[QDF_MODULE_ID_MGMT_RX_REO] = {"MGMT_RX_REO"},
3414 	[QDF_MODULE_ID_MLOIE] = {"MLOIE"},
3415 	[QDF_MODULE_ID_MBSS] = {"MBSS"},
3416 	[QDF_MODULE_ID_MON] = {"MONITOR"},
3417 	[QDF_MODULE_ID_AFC] = {"AFC"},
3418 	[QDF_MODULE_ID_TWT] = {"TWT"},
3419 	[QDF_MODULE_ID_SON] = {"SON"},
3420 	[QDF_MODULE_ID_WLAN_PRE_CAC] = {"PRE_CAC"},
3421 	[QDF_MODULE_ID_T2LM] = {"T2LM"},
3422 	[QDF_MODULE_ID_DP_SAWF] = {"DP_SAWF"},
3423 	[QDF_MODULE_ID_SCS] = {"SCS"},
3424 	[QDF_MODULE_ID_DP_UMAC_RESET] = {"UMAC_HW_RESET"},
3425 	[QDF_MODULE_ID_COAP] = {"COAP"},
3426 	[QDF_MODULE_ID_FTM_TIME_SYNC] = {"Time Sync"},
3427 	[QDF_MODULE_ID_WIFI_RADAR] = {"WIFI RADAR"},
3428 	[QDF_MODULE_ID_CDP] =  {"CDP"},
3429 	[QDF_MODULE_ID_QMI] = {"QMI"},
3430 	[QDF_MODULE_ID_ANY] = {"ANY"},
3431 };
3432 qdf_export_symbol(g_qdf_category_name);
3433 
3434 void qdf_trace_display(void)
3435 {
3436 	QDF_MODULE_ID module_id;
3437 
3438 	pr_err("     1)FATAL  2)ERROR  3)WARN  4)INFO  5)INFO_H  6)INFO_M  7)INFO_L 8)DEBUG\n");
3439 	for (module_id = 0; module_id < QDF_MODULE_ID_MAX; ++module_id) {
3440 		pr_err("%2d)%s    %s        %s       %s       %s        %s         %s         %s        %s\n",
3441 		       (int)module_id,
3442 		       g_qdf_category_name[module_id].category_name_str,
3443 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3444 			       QDF_TRACE_LEVEL_FATAL) ? "X" : " ",
3445 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3446 			       QDF_TRACE_LEVEL_ERROR) ? "X" : " ",
3447 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3448 			       QDF_TRACE_LEVEL_WARN) ? "X" : " ",
3449 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3450 			       QDF_TRACE_LEVEL_INFO) ? "X" : " ",
3451 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3452 			       QDF_TRACE_LEVEL_INFO_HIGH) ? "X" : " ",
3453 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3454 			       QDF_TRACE_LEVEL_INFO_MED) ? "X" : " ",
3455 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3456 			       QDF_TRACE_LEVEL_INFO_LOW) ? "X" : " ",
3457 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3458 			       QDF_TRACE_LEVEL_DEBUG) ? "X" : " ");
3459 	}
3460 }
3461 qdf_export_symbol(qdf_trace_display);
3462 
3463 #ifdef WLAN_MAX_LOGS_PER_SEC
3464 static qdf_time_t __log_window_end;
3465 static qdf_atomic_t __log_window_count;
3466 uint32_t qdf_rl_print_count = WLAN_MAX_LOGS_PER_SEC;
3467 uint32_t qdf_rl_print_time = 1;
3468 uint32_t qdf_rl_print_suppressed;
3469 
3470 bool qdf_detected_excessive_logging(void)
3471 {
3472 	qdf_time_t now = qdf_system_ticks();
3473 	bool excessive_prints = false;
3474 
3475 	/*
3476 	 * If 'now' is more recent than the end of the window, reset.
3477 	 *
3478 	 * Note: This is not thread safe, and can result in more than one reset.
3479 	 * For our purposes, this is fine.
3480 	 */
3481 	if (!qdf_atomic_read(&__log_window_count)) {
3482 		__log_window_end = now + (qdf_system_ticks_per_sec * qdf_rl_print_time);
3483 	} else if (qdf_system_time_after(now, __log_window_end)) {
3484 		__log_window_end = now + (qdf_system_ticks_per_sec * qdf_rl_print_time);
3485 		qdf_atomic_set(&__log_window_count, 0);
3486 	}
3487 
3488 	if (qdf_atomic_inc_return(&__log_window_count) > qdf_rl_print_count)
3489 		excessive_prints = true;
3490 
3491 	return excessive_prints;
3492 }
3493 
3494 void qdf_rl_print_count_set(uint32_t rl_print_count)
3495 {
3496 	qdf_rl_print_count = rl_print_count;
3497 }
3498 
3499 qdf_export_symbol(qdf_rl_print_count_set);
3500 
3501 void qdf_rl_print_time_set(uint32_t rl_print_time)
3502 {
3503 	qdf_rl_print_time = rl_print_time;
3504 }
3505 
3506 qdf_export_symbol(qdf_rl_print_time_set);
3507 
3508 void qdf_rl_print_suppressed_log(void)
3509 {
3510 	if (qdf_rl_print_suppressed) {
3511 		pr_err("QDF Ratelimiting: %d prints suppressed",
3512 		       qdf_rl_print_suppressed);
3513 		qdf_rl_print_suppressed = 0;
3514 	}
3515 }
3516 
3517 void qdf_rl_print_suppressed_inc(void)
3518 {
3519 	qdf_rl_print_suppressed++;
3520 }
3521 #else
3522 #define qdf_rl_print_suppressed_log()
3523 #define qdf_rl_print_suppressed_inc()
3524 #endif /* WLAN_MAX_LOGS_PER_SEC */
3525 
3526 #ifdef QDF_TRACE_PRINT_ENABLE
3527 static inline void print_to_console(char *str_buffer)
3528 {
3529 	if (qdf_in_interrupt() && qdf_detected_excessive_logging()) {
3530 		qdf_rl_print_suppressed_inc();
3531 		return;
3532 	}
3533 	qdf_rl_print_suppressed_log();
3534 	pr_err("%s\n", str_buffer);
3535 }
3536 #else
3537 
3538 #define print_to_console(str)
3539 #endif
3540 
3541 #ifdef MULTI_IF_NAME
3542 static const char *qdf_trace_wlan_modname(void)
3543 {
3544 	return MULTI_IF_NAME;
3545 }
3546 #else
3547 static const char *qdf_trace_wlan_modname(void)
3548 {
3549 	return "wlan";
3550 }
3551 #endif
3552 
3553 void qdf_trace_msg_cmn(unsigned int idx,
3554 			QDF_MODULE_ID category,
3555 			QDF_TRACE_LEVEL verbose,
3556 			const char *str_format, va_list val)
3557 {
3558 	char str_buffer[QDF_TRACE_BUFFER_SIZE];
3559 	int n;
3560 
3561 	/* Check if index passed is valid */
3562 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3563 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3564 		return;
3565 	}
3566 
3567 	/* Check if print control object is in use */
3568 	if (!print_ctrl_obj[idx].in_use) {
3569 		pr_info("%s: Invalid print control object\n", __func__);
3570 		return;
3571 	}
3572 
3573 	/* Check if category passed is valid */
3574 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
3575 		vscnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, str_format, val);
3576 		pr_info("%s: Invalid category: %d, log: %s\n",
3577 			__func__, category, str_buffer);
3578 		return;
3579 	}
3580 
3581 	/* Check if verbose mask is valid */
3582 	if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
3583 		vscnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, str_format, val);
3584 		pr_info("%s: Invalid verbose level %d, log: %s\n",
3585 			__func__, verbose, str_buffer);
3586 		return;
3587 	}
3588 
3589 	/*
3590 	 * Print the trace message when the desired verbose level is set in
3591 	 * the desired category for the print control object
3592 	 */
3593 	if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
3594 	    QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
3595 		static const char * const VERBOSE_STR[] = {
3596 			[QDF_TRACE_LEVEL_NONE] = "",
3597 			[QDF_TRACE_LEVEL_FATAL] = "F",
3598 			[QDF_TRACE_LEVEL_ERROR] = "E",
3599 			[QDF_TRACE_LEVEL_WARN] = "W",
3600 			[QDF_TRACE_LEVEL_INFO] = "I",
3601 			[QDF_TRACE_LEVEL_INFO_HIGH] = "IH",
3602 			[QDF_TRACE_LEVEL_INFO_MED] = "IM",
3603 			[QDF_TRACE_LEVEL_INFO_LOW] = "IL",
3604 			[QDF_TRACE_LEVEL_DEBUG] = "D",
3605 			[QDF_TRACE_LEVEL_TRACE] = "T",
3606 			[QDF_TRACE_LEVEL_ALL] = "" };
3607 
3608 		/* print the prefix string into the string buffer... */
3609 		n = scnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE,
3610 			     "%s: [%d:%s:%s] ", qdf_trace_wlan_modname(),
3611 			     in_interrupt() ? 0 : current->pid,
3612 			     VERBOSE_STR[verbose],
3613 			     g_qdf_category_name[category].category_name_str);
3614 
3615 		/* print the formatted log message after the prefix string */
3616 		vscnprintf(str_buffer + n, QDF_TRACE_BUFFER_SIZE - n,
3617 			   str_format, val);
3618 #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE)
3619 		wlan_log_to_user(verbose, (char *)str_buffer,
3620 				 strlen(str_buffer));
3621 		if (qdf_unlikely(qdf_log_dump_at_kernel_enable))
3622 			print_to_console(str_buffer);
3623 #else
3624 		pr_err("%s\n", str_buffer);
3625 #endif
3626 	}
3627 }
3628 qdf_export_symbol(qdf_trace_msg_cmn);
3629 
3630 QDF_STATUS qdf_print_setup(void)
3631 {
3632 	int i;
3633 
3634 	/* Loop through all print ctrl objects */
3635 	for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
3636 		if (qdf_print_ctrl_cleanup(i))
3637 			return QDF_STATUS_E_FAILURE;
3638 	}
3639 	return QDF_STATUS_SUCCESS;
3640 }
3641 qdf_export_symbol(qdf_print_setup);
3642 
3643 QDF_STATUS qdf_print_ctrl_cleanup(unsigned int idx)
3644 {
3645 	int i = 0;
3646 
3647 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3648 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3649 		return QDF_STATUS_E_FAILURE;
3650 	}
3651 
3652 	/* Clean up the print control object corresponding to that index
3653 	 * If success, callee to change print control index to -1
3654 	 */
3655 
3656 	for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3657 		print_ctrl_obj[idx].cat_info[i].category_verbose_mask =
3658 							QDF_TRACE_LEVEL_NONE;
3659 	}
3660 	print_ctrl_obj[idx].custom_print = NULL;
3661 	print_ctrl_obj[idx].custom_ctxt = NULL;
3662 	qdf_print_clean_node_flag(idx);
3663 	print_ctrl_obj[idx].in_use = false;
3664 
3665 	return QDF_STATUS_SUCCESS;
3666 }
3667 qdf_export_symbol(qdf_print_ctrl_cleanup);
3668 
3669 int qdf_print_ctrl_register(const struct category_info *cinfo,
3670 			    void *custom_print_handler,
3671 			    void *custom_ctx,
3672 			    const char *pctrl_name)
3673 {
3674 	int idx = -1;
3675 	int i = 0;
3676 
3677 	for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
3678 		if (!print_ctrl_obj[i].in_use) {
3679 			idx = i;
3680 			break;
3681 		}
3682 	}
3683 
3684 	/* Callee to handle idx -1 appropriately */
3685 	if (idx == -1) {
3686 		pr_info("%s: Allocation failed! No print control object free\n",
3687 			__func__);
3688 		return idx;
3689 	}
3690 
3691 	print_ctrl_obj[idx].in_use = true;
3692 
3693 	/*
3694 	 * In case callee does not pass category info,
3695 	 * custom print handler, custom context and print control name,
3696 	 * we do not set any value here. Clean up for the print control
3697 	 * getting allocated would have taken care of initializing
3698 	 * default values.
3699 	 *
3700 	 * We need to only set in_use to 1 in such a case
3701 	 */
3702 
3703 	if (pctrl_name) {
3704 		qdf_str_lcopy(print_ctrl_obj[idx].name, pctrl_name,
3705 			      sizeof(print_ctrl_obj[idx].name));
3706 	}
3707 
3708 	if (custom_print_handler)
3709 		print_ctrl_obj[idx].custom_print = custom_print_handler;
3710 
3711 	if (custom_ctx)
3712 		print_ctrl_obj[idx].custom_ctxt = custom_ctx;
3713 
3714 	if (cinfo) {
3715 		for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3716 			if (cinfo[i].category_verbose_mask ==
3717 			    QDF_TRACE_LEVEL_ALL) {
3718 				print_ctrl_obj[idx].cat_info[i]
3719 				.category_verbose_mask = 0xFFFF;
3720 			} else if ((cinfo[i].category_verbose_mask ==
3721 				   QDF_TRACE_LEVEL_NONE) ||
3722 				   (cinfo[i].category_verbose_mask ==
3723 				   QDF_TRACE_LEVEL_TO_MODULE_BITMASK(
3724 				   QDF_TRACE_LEVEL_NONE))) {
3725 				print_ctrl_obj[idx].cat_info[i]
3726 				.category_verbose_mask = 0;
3727 			} else {
3728 				print_ctrl_obj[idx].cat_info[i]
3729 				.category_verbose_mask =
3730 				cinfo[i].category_verbose_mask;
3731 			}
3732 		}
3733 	}
3734 
3735 	return idx;
3736 }
3737 qdf_export_symbol(qdf_print_ctrl_register);
3738 
3739 #ifdef QDF_TRACE_PRINT_ENABLE
3740 void qdf_shared_print_ctrl_cleanup(void)
3741 {
3742 	qdf_print_ctrl_cleanup(qdf_pidx);
3743 }
3744 qdf_export_symbol(qdf_shared_print_ctrl_cleanup);
3745 
3746 /*
3747  * Set this to invalid value to differentiate with user-provided
3748  * value.
3749  */
3750 int qdf_dbg_mask = QDF_TRACE_LEVEL_MAX;
3751 qdf_export_symbol(qdf_dbg_mask);
3752 qdf_declare_param(qdf_dbg_mask, int);
3753 
3754 /*
3755  * QDF can be passed parameters which indicate the
3756  * debug level for each module.
3757  * an array of string values are passed, each string hold the following form
3758  *
3759  * <module name string>=<integer debug level value>
3760  *
3761  * The array qdf_dbg_arr will hold these module-string=value strings
3762  * The variable qdf_dbg_arr_cnt will have the count of how many such
3763  * string values were passed.
3764  */
3765 static char *qdf_dbg_arr[QDF_MODULE_ID_MAX];
3766 static int qdf_dbg_arr_cnt;
3767 qdf_declare_param_array(qdf_dbg_arr, charp, &qdf_dbg_arr_cnt);
3768 
3769 static uint16_t set_cumulative_verbose_mask(QDF_TRACE_LEVEL max_level)
3770 {
3771 	uint16_t category_verbose_mask = 0;
3772 	QDF_TRACE_LEVEL level;
3773 
3774 	for (level = QDF_TRACE_LEVEL_FATAL; level <= max_level; level++) {
3775 		category_verbose_mask |=
3776 			QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level);
3777 	}
3778 	return category_verbose_mask;
3779 }
3780 
3781 static QDF_MODULE_ID find_qdf_module_from_string(char *str)
3782 {
3783 	QDF_MODULE_ID mod_id;
3784 
3785 	for (mod_id = 0; mod_id < QDF_MODULE_ID_MAX; mod_id++) {
3786 		if (strcasecmp(str,
3787 				g_qdf_category_name[mod_id].category_name_str)
3788 				== 0) {
3789 			break;
3790 		}
3791 	}
3792 	return mod_id;
3793 }
3794 
3795 static void process_qdf_dbg_arr_param(struct category_info *cinfo,
3796 					int array_index)
3797 {
3798 	char *mod_val_str, *mod_str, *val_str;
3799 	unsigned long dbg_level;
3800 	QDF_MODULE_ID mod_id;
3801 
3802 	mod_val_str = qdf_dbg_arr[array_index];
3803 	mod_str = strsep(&mod_val_str, "=");
3804 	val_str = mod_val_str;
3805 	if (!val_str) {
3806 		pr_info("qdf_dbg_arr: %s not in the <mod>=<val> form\n",
3807 				mod_str);
3808 		return;
3809 	}
3810 
3811 	mod_id = find_qdf_module_from_string(mod_str);
3812 	if (mod_id >= QDF_MODULE_ID_MAX) {
3813 		pr_info("ERROR!!Module name %s not in the list of modules\n",
3814 				mod_str);
3815 		return;
3816 	}
3817 
3818 	if (kstrtol(val_str, 10, &dbg_level) < 0) {
3819 		pr_info("ERROR!!Invalid debug level for module: %s\n",
3820 				mod_str);
3821 		return;
3822 	}
3823 
3824 	if (dbg_level >= QDF_TRACE_LEVEL_MAX) {
3825 		pr_info("ERROR!!Debug level for %s too high", mod_str);
3826 		pr_info("max: %d given %lu\n", QDF_TRACE_LEVEL_MAX,
3827 				dbg_level);
3828 		return;
3829 	}
3830 
3831 	pr_info("User passed setting module %s(%d) to level %lu\n",
3832 			mod_str,
3833 			mod_id,
3834 			dbg_level);
3835 	cinfo[mod_id].category_verbose_mask =
3836 		set_cumulative_verbose_mask((QDF_TRACE_LEVEL)dbg_level);
3837 }
3838 
3839 static void set_default_trace_levels(struct category_info *cinfo)
3840 {
3841 	int i;
3842 	static QDF_TRACE_LEVEL module_trace_default_level[QDF_MODULE_ID_MAX] = {
3843 		[QDF_MODULE_ID_TDLS] = QDF_TRACE_LEVEL_NONE,
3844 		[QDF_MODULE_ID_ACS] = QDF_TRACE_LEVEL_NONE,
3845 		[QDF_MODULE_ID_SCAN_SM] = QDF_TRACE_LEVEL_NONE,
3846 		[QDF_MODULE_ID_SCANENTRY] = QDF_TRACE_LEVEL_NONE,
3847 		[QDF_MODULE_ID_WDS] = QDF_TRACE_LEVEL_NONE,
3848 		[QDF_MODULE_ID_ACTION] = QDF_TRACE_LEVEL_NONE,
3849 		[QDF_MODULE_ID_ROAM] = QDF_TRACE_LEVEL_NONE,
3850 		[QDF_MODULE_ID_INACT] = QDF_TRACE_LEVEL_NONE,
3851 		[QDF_MODULE_ID_DOTH] = QDF_TRACE_LEVEL_NONE,
3852 		[QDF_MODULE_ID_IQUE] = QDF_TRACE_LEVEL_NONE,
3853 		[QDF_MODULE_ID_WME] = QDF_TRACE_LEVEL_NONE,
3854 		[QDF_MODULE_ID_ACL] = QDF_TRACE_LEVEL_NONE,
3855 		[QDF_MODULE_ID_WPA] = QDF_TRACE_LEVEL_NONE,
3856 		[QDF_MODULE_ID_RADKEYS] = QDF_TRACE_LEVEL_NONE,
3857 		[QDF_MODULE_ID_RADDUMP] = QDF_TRACE_LEVEL_NONE,
3858 		[QDF_MODULE_ID_RADIUS] = QDF_TRACE_LEVEL_NONE,
3859 		[QDF_MODULE_ID_DOT1XSM] = QDF_TRACE_LEVEL_NONE,
3860 		[QDF_MODULE_ID_DOT1X] = QDF_TRACE_LEVEL_NONE,
3861 		[QDF_MODULE_ID_POWER] = QDF_TRACE_LEVEL_NONE,
3862 		[QDF_MODULE_ID_STATE] = QDF_TRACE_LEVEL_NONE,
3863 		[QDF_MODULE_ID_OUTPUT] = QDF_TRACE_LEVEL_NONE,
3864 		[QDF_MODULE_ID_SCAN] = QDF_TRACE_LEVEL_ERROR,
3865 		[QDF_MODULE_ID_AUTH] = QDF_TRACE_LEVEL_NONE,
3866 		[QDF_MODULE_ID_ASSOC] = QDF_TRACE_LEVEL_NONE,
3867 		[QDF_MODULE_ID_NODE] = QDF_TRACE_LEVEL_NONE,
3868 		[QDF_MODULE_ID_ELEMID] = QDF_TRACE_LEVEL_NONE,
3869 		[QDF_MODULE_ID_XRATE] = QDF_TRACE_LEVEL_NONE,
3870 		[QDF_MODULE_ID_INPUT] = QDF_TRACE_LEVEL_NONE,
3871 		[QDF_MODULE_ID_CRYPTO] = QDF_TRACE_LEVEL_NONE,
3872 		[QDF_MODULE_ID_DUMPPKTS] = QDF_TRACE_LEVEL_NONE,
3873 		[QDF_MODULE_ID_DEBUG] = QDF_TRACE_LEVEL_NONE,
3874 		[QDF_MODULE_ID_MLME] = QDF_TRACE_LEVEL_ERROR,
3875 		[QDF_MODULE_ID_RRM] = QDF_TRACE_LEVEL_NONE,
3876 		[QDF_MODULE_ID_WNM] = QDF_TRACE_LEVEL_NONE,
3877 		[QDF_MODULE_ID_P2P_PROT] = QDF_TRACE_LEVEL_NONE,
3878 		[QDF_MODULE_ID_PROXYARP] = QDF_TRACE_LEVEL_NONE,
3879 		[QDF_MODULE_ID_L2TIF] = QDF_TRACE_LEVEL_NONE,
3880 		[QDF_MODULE_ID_WIFIPOS] = QDF_TRACE_LEVEL_NONE,
3881 		[QDF_MODULE_ID_WRAP] = QDF_TRACE_LEVEL_NONE,
3882 		[QDF_MODULE_ID_DFS] = QDF_TRACE_LEVEL_NONE,
3883 		[QDF_MODULE_ID_ATF] = QDF_TRACE_LEVEL_ERROR,
3884 		[QDF_MODULE_ID_SPLITMAC] = QDF_TRACE_LEVEL_NONE,
3885 		[QDF_MODULE_ID_IOCTL] = QDF_TRACE_LEVEL_NONE,
3886 		[QDF_MODULE_ID_NAC] = QDF_TRACE_LEVEL_NONE,
3887 		[QDF_MODULE_ID_MESH] = QDF_TRACE_LEVEL_NONE,
3888 		[QDF_MODULE_ID_MBO] = QDF_TRACE_LEVEL_NONE,
3889 		[QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = QDF_TRACE_LEVEL_NONE,
3890 		[QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = QDF_TRACE_LEVEL_NONE,
3891 		[QDF_MODULE_ID_TLSHIM] = QDF_TRACE_LEVEL_NONE,
3892 		[QDF_MODULE_ID_WMI] = QDF_TRACE_LEVEL_ERROR,
3893 		[QDF_MODULE_ID_HTT] = QDF_TRACE_LEVEL_NONE,
3894 		[QDF_MODULE_ID_HDD] = QDF_TRACE_LEVEL_NONE,
3895 		[QDF_MODULE_ID_SME] = QDF_TRACE_LEVEL_NONE,
3896 		[QDF_MODULE_ID_PE] = QDF_TRACE_LEVEL_NONE,
3897 		[QDF_MODULE_ID_WMA] = QDF_TRACE_LEVEL_NONE,
3898 		[QDF_MODULE_ID_SYS] = QDF_TRACE_LEVEL_NONE,
3899 		[QDF_MODULE_ID_QDF] = QDF_TRACE_LEVEL_ERROR,
3900 		[QDF_MODULE_ID_SAP] = QDF_TRACE_LEVEL_NONE,
3901 		[QDF_MODULE_ID_HDD_SOFTAP] = QDF_TRACE_LEVEL_NONE,
3902 		[QDF_MODULE_ID_HDD_DATA] = QDF_TRACE_LEVEL_NONE,
3903 		[QDF_MODULE_ID_HDD_SAP_DATA] = QDF_TRACE_LEVEL_NONE,
3904 		[QDF_MODULE_ID_HIF] = QDF_TRACE_LEVEL_ERROR,
3905 		[QDF_MODULE_ID_HTC] = QDF_TRACE_LEVEL_NONE,
3906 		[QDF_MODULE_ID_TXRX] = QDF_TRACE_LEVEL_NONE,
3907 		[QDF_MODULE_ID_QDF_DEVICE] = QDF_TRACE_LEVEL_NONE,
3908 		[QDF_MODULE_ID_CFG] = QDF_TRACE_LEVEL_NONE,
3909 		[QDF_MODULE_ID_BMI] = QDF_TRACE_LEVEL_NONE,
3910 		[QDF_MODULE_ID_EPPING] = QDF_TRACE_LEVEL_NONE,
3911 		[QDF_MODULE_ID_QVIT] = QDF_TRACE_LEVEL_NONE,
3912 		[QDF_MODULE_ID_DP] = QDF_TRACE_LEVEL_FATAL,
3913 		[QDF_MODULE_ID_HAL] = QDF_TRACE_LEVEL_NONE,
3914 		[QDF_MODULE_ID_SOC] = QDF_TRACE_LEVEL_NONE,
3915 		[QDF_MODULE_ID_OS_IF] = QDF_TRACE_LEVEL_NONE,
3916 		[QDF_MODULE_ID_TARGET_IF] = QDF_TRACE_LEVEL_INFO,
3917 		[QDF_MODULE_ID_SCHEDULER] = QDF_TRACE_LEVEL_FATAL,
3918 		[QDF_MODULE_ID_MGMT_TXRX] = QDF_TRACE_LEVEL_NONE,
3919 		[QDF_MODULE_ID_SERIALIZATION] = QDF_TRACE_LEVEL_ERROR,
3920 		[QDF_MODULE_ID_PMO] = QDF_TRACE_LEVEL_NONE,
3921 		[QDF_MODULE_ID_P2P] = QDF_TRACE_LEVEL_NONE,
3922 		[QDF_MODULE_ID_POLICY_MGR] = QDF_TRACE_LEVEL_NONE,
3923 		[QDF_MODULE_ID_CONFIG] = QDF_TRACE_LEVEL_ERROR,
3924 		[QDF_MODULE_ID_REGULATORY] = QDF_TRACE_LEVEL_NONE,
3925 		[QDF_MODULE_ID_SA_API] = QDF_TRACE_LEVEL_NONE,
3926 		[QDF_MODULE_ID_NAN] = QDF_TRACE_LEVEL_NONE,
3927 		[QDF_MODULE_ID_OFFCHAN_TXRX] = QDF_TRACE_LEVEL_NONE,
3928 		[QDF_MODULE_ID_SON] = QDF_TRACE_LEVEL_NONE,
3929 		[QDF_MODULE_ID_SPECTRAL] = QDF_TRACE_LEVEL_ERROR,
3930 		[QDF_MODULE_ID_OBJ_MGR] = QDF_TRACE_LEVEL_FATAL,
3931 		[QDF_MODULE_ID_NSS] = QDF_TRACE_LEVEL_ERROR,
3932 		[QDF_MODULE_ID_ROAM_DEBUG] = QDF_TRACE_LEVEL_ERROR,
3933 		[QDF_MODULE_ID_CDP] = QDF_TRACE_LEVEL_NONE,
3934 		[QDF_MODULE_ID_DIRECT_BUF_RX] = QDF_TRACE_LEVEL_ERROR,
3935 		[QDF_MODULE_ID_DISA] = QDF_TRACE_LEVEL_NONE,
3936 		[QDF_MODULE_ID_GREEN_AP] = QDF_TRACE_LEVEL_ERROR,
3937 		[QDF_MODULE_ID_FTM] = QDF_TRACE_LEVEL_ERROR,
3938 		[QDF_MODULE_ID_FD] = QDF_TRACE_LEVEL_ERROR,
3939 		[QDF_MODULE_ID_OCB] = QDF_TRACE_LEVEL_ERROR,
3940 		[QDF_MODULE_ID_IPA] = QDF_TRACE_LEVEL_NONE,
3941 		[QDF_MODULE_ID_ACTION_OUI] = QDF_TRACE_LEVEL_NONE,
3942 		[QDF_MODULE_ID_CP_STATS] = QDF_TRACE_LEVEL_ERROR,
3943 		[QDF_MODULE_ID_DCS] = QDF_TRACE_LEVEL_ERROR,
3944 		[QDF_MODULE_ID_MBSSIE] = QDF_TRACE_LEVEL_INFO,
3945 		[QDF_MODULE_ID_FWOL] = QDF_TRACE_LEVEL_NONE,
3946 		[QDF_MODULE_ID_SM_ENGINE] = QDF_TRACE_LEVEL_ERROR,
3947 		[QDF_MODULE_ID_CMN_MLME] = QDF_TRACE_LEVEL_INFO,
3948 		[QDF_MODULE_ID_BSSCOLOR] = QDF_TRACE_LEVEL_ERROR,
3949 		[QDF_MODULE_ID_CFR] = QDF_TRACE_LEVEL_ERROR,
3950 		[QDF_MODULE_ID_DP_TX_CAPTURE] = QDF_TRACE_LEVEL_FATAL,
3951 		[QDF_MODULE_ID_INTEROP_ISSUES_AP] = QDF_TRACE_LEVEL_NONE,
3952 		[QDF_MODULE_ID_DENYLIST_MGR] = QDF_TRACE_LEVEL_NONE,
3953 		[QDF_MODULE_ID_QLD] = QDF_TRACE_LEVEL_ERROR,
3954 		[QDF_MODULE_ID_DYNAMIC_MODE_CHG] = QDF_TRACE_LEVEL_INFO,
3955 		[QDF_MODULE_ID_COEX] = QDF_TRACE_LEVEL_ERROR,
3956 		[QDF_MODULE_ID_MON_FILTER] = QDF_TRACE_LEVEL_INFO,
3957 		[QDF_MODULE_ID_PKT_CAPTURE] = QDF_TRACE_LEVEL_NONE,
3958 		[QDF_MODULE_ID_RPTR] = QDF_TRACE_LEVEL_INFO,
3959 		[QDF_MODULE_ID_6GHZ] = QDF_TRACE_LEVEL_ERROR,
3960 		[QDF_MODULE_ID_IOT_SIM] = QDF_TRACE_LEVEL_ERROR,
3961 		[QDF_MODULE_ID_MSCS] = QDF_TRACE_LEVEL_INFO,
3962 		[QDF_MODULE_ID_GPIO] = QDF_TRACE_LEVEL_NONE,
3963 		[QDF_MODULE_ID_IFMGR] = QDF_TRACE_LEVEL_ERROR,
3964 		[QDF_MODULE_ID_DIAG] = QDF_TRACE_LEVEL_ERROR,
3965 		[QDF_MODULE_ID_DP_INIT] = QDF_TRACE_LEVEL_FATAL,
3966 		[QDF_MODULE_ID_DP_TX] = QDF_TRACE_LEVEL_FATAL,
3967 		[QDF_MODULE_ID_DP_RX] = QDF_TRACE_LEVEL_FATAL,
3968 		[QDF_MODULE_ID_DP_STATS] = QDF_TRACE_LEVEL_FATAL,
3969 		[QDF_MODULE_ID_DP_HTT] = QDF_TRACE_LEVEL_FATAL,
3970 		[QDF_MODULE_ID_DP_PEER] = QDF_TRACE_LEVEL_FATAL,
3971 		[QDF_MODULE_ID_DP_RX_ERROR] = QDF_TRACE_LEVEL_FATAL,
3972 		[QDF_MODULE_ID_DP_HTT_TX_STATS] = QDF_TRACE_LEVEL_FATAL,
3973 		[QDF_MODULE_ID_DP_RX_MON_STATUS] = QDF_TRACE_LEVEL_FATAL,
3974 		[QDF_MODULE_ID_DP_RX_MON_DEST] = QDF_TRACE_LEVEL_FATAL,
3975 		[QDF_MODULE_ID_DP_REO] = QDF_TRACE_LEVEL_FATAL,
3976 		[QDF_MODULE_ID_DP_TX_COMP] = QDF_TRACE_LEVEL_FATAL,
3977 		[QDF_MODULE_ID_DP_VDEV] = QDF_TRACE_LEVEL_FATAL,
3978 		[QDF_MODULE_ID_DP_CDP] = QDF_TRACE_LEVEL_FATAL,
3979 		[QDF_MODULE_ID_TSO] = QDF_TRACE_LEVEL_FATAL,
3980 		[QDF_MODULE_ID_ME] = QDF_TRACE_LEVEL_INFO,
3981 		[QDF_MODULE_ID_QWRAP] = QDF_TRACE_LEVEL_FATAL,
3982 		[QDF_MODULE_ID_DBDC_REP] = QDF_TRACE_LEVEL_FATAL,
3983 		[QDF_MODULE_ID_EXT_AP] = QDF_TRACE_LEVEL_NONE,
3984 		[QDF_MODULE_ID_MLO] = QDF_TRACE_LEVEL_INFO,
3985 		[QDF_MODULE_ID_MLOIE] = QDF_TRACE_LEVEL_INFO,
3986 		[QDF_MODULE_ID_MBSS] = QDF_TRACE_LEVEL_ERROR,
3987 		[QDF_MODULE_ID_MON] = QDF_TRACE_LEVEL_ERROR,
3988 		[QDF_MODULE_ID_MGMT_RX_REO] = QDF_TRACE_LEVEL_ERROR,
3989 		[QDF_MODULE_ID_TWT] = QDF_TRACE_LEVEL_ERROR,
3990 		[QDF_MODULE_ID_WLAN_PRE_CAC] = QDF_TRACE_LEVEL_ERROR,
3991 		[QDF_MODULE_ID_T2LM] = QDF_TRACE_LEVEL_ERROR,
3992 		[QDF_MODULE_ID_DP_SAWF] = QDF_TRACE_LEVEL_ERROR,
3993 		[QDF_MODULE_ID_SCS] = QDF_TRACE_LEVEL_ERROR,
3994 		[QDF_MODULE_ID_DP_UMAC_RESET] = QDF_TRACE_LEVEL_ERROR,
3995 		[QDF_MODULE_ID_COAP] = QDF_TRACE_LEVEL_ERROR,
3996 		[QDF_MODULE_ID_FTM_TIME_SYNC] = QDF_TRACE_LEVEL_NONE,
3997 		[QDF_MODULE_ID_AFC] = QDF_TRACE_LEVEL_NONE,
3998 		[QDF_MODULE_ID_WIFI_RADAR] = QDF_TRACE_LEVEL_NONE,
3999 		[QDF_MODULE_ID_TARGET] = QDF_TRACE_LEVEL_NONE,
4000 		[QDF_MODULE_ID_QMI] = QDF_TRACE_LEVEL_ERROR,
4001 		[QDF_MODULE_ID_ANY] = QDF_TRACE_LEVEL_INFO,
4002 	};
4003 
4004 	for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
4005 		cinfo[i].category_verbose_mask = set_cumulative_verbose_mask(
4006 				module_trace_default_level[i]);
4007 	}
4008 }
4009 
4010 void qdf_shared_print_ctrl_init(void)
4011 {
4012 	int i;
4013 	struct category_info cinfo[MAX_SUPPORTED_CATEGORY];
4014 
4015 	set_default_trace_levels(cinfo);
4016 
4017 	/*
4018 	 * User specified across-module single debug level
4019 	 */
4020 	if ((qdf_dbg_mask >= 0) && (qdf_dbg_mask < QDF_TRACE_LEVEL_MAX)) {
4021 		pr_info("User specified module debug level of %d\n",
4022 			qdf_dbg_mask);
4023 		for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
4024 			cinfo[i].category_verbose_mask =
4025 			set_cumulative_verbose_mask(qdf_dbg_mask);
4026 		}
4027 	} else if (qdf_dbg_mask != QDF_TRACE_LEVEL_MAX) {
4028 		pr_info("qdf_dbg_mask value is invalid\n");
4029 		pr_info("Using the default module debug levels instead\n");
4030 	}
4031 
4032 	/*
4033 	 * Module ID-Level specified as array during module load
4034 	 */
4035 	for (i = 0; i < qdf_dbg_arr_cnt; i++) {
4036 		process_qdf_dbg_arr_param(cinfo, i);
4037 	}
4038 	qdf_pidx = qdf_print_ctrl_register(cinfo, NULL, NULL,
4039 			"LOG_SHARED_OBJ");
4040 }
4041 qdf_export_symbol(qdf_shared_print_ctrl_init);
4042 #endif
4043 
4044 #ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI
4045 QDF_STATUS qdf_module_param_handler(void *context, const char *str_param,
4046 				    const char *str)
4047 {
4048 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
4049 	uint16_t param = 0;
4050 	uint32_t flush_tmr_prd;
4051 	bool dump_flag;
4052 
4053 	while (param < QDF_PARAM_MAX) {
4054 		if (qdf_str_eq(qdf_module_param[param], str_param)) {
4055 			switch (param) {
4056 			case MEM_DEBUG_DISABLED:
4057 				status = qdf_mem_debug_disabled_config_set(str);
4058 				break;
4059 			case QDF_DBG_MASK:
4060 				status = qdf_int32_parse(str, &qdf_dbg_mask);
4061 				break;
4062 			case PREALLOC_DISABLED:
4063 				status = qdf_prealloc_disabled_config_set(str);
4064 				break;
4065 			case QDF_LOG_DUMP_AT_KERNEL_ENABLE:
4066 				status = qdf_bool_parse(str, &dump_flag);
4067 				qdf_log_dump_at_kernel_enable = dump_flag;
4068 				break;
4069 			case QDF_DBG_ARR:
4070 				qdf_dbg_arr[0] = (char *)str;
4071 				status = QDF_STATUS_SUCCESS;
4072 				break;
4073 			case QDF_LOG_FLUSH_TIMER_PERIOD:
4074 				status = qdf_uint32_parse(str, &flush_tmr_prd);
4075 				qdf_log_flush_timer_period = flush_tmr_prd;
4076 				break;
4077 			default:
4078 				break;
4079 			}
4080 			return status;
4081 		}
4082 		param++;
4083 	}
4084 
4085 	return QDF_STATUS_SUCCESS;
4086 }
4087 
4088 void qdf_initialize_module_param_from_ini(void)
4089 {
4090 	QDF_STATUS status;
4091 	char *path = QDF_WIFI_MODULE_PARAMS_FILE;
4092 
4093 	status = qdf_ini_parse(path, NULL, qdf_module_param_handler, NULL);
4094 	if (QDF_IS_STATUS_ERROR(status)) {
4095 		QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
4096 				"Failed to parse *.ini file @ %s; status:%d",
4097 				path, status);
4098 		return;
4099 	}
4100 }
4101 #endif
4102 
4103 QDF_STATUS qdf_print_set_category_verbose(unsigned int idx,
4104 						QDF_MODULE_ID category,
4105 						QDF_TRACE_LEVEL verbose,
4106 						bool is_set)
4107 {
4108 	/* Check if index passed is valid */
4109 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4110 		pr_err("%s: Invalid index - %d\n", __func__, idx);
4111 		return QDF_STATUS_E_FAILURE;
4112 	}
4113 
4114 	/* Check if print control object is in use */
4115 	if (!print_ctrl_obj[idx].in_use) {
4116 		pr_err("%s: Invalid print control object\n", __func__);
4117 		return QDF_STATUS_E_FAILURE;
4118 	}
4119 
4120 	/* Check if category passed is valid */
4121 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
4122 		pr_err("%s: Invalid category: %d\n", __func__, category);
4123 		return QDF_STATUS_E_FAILURE;
4124 	}
4125 
4126 	/* Check if verbose mask is valid */
4127 	if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
4128 		pr_err("%s: Invalid verbose level %d\n", __func__, verbose);
4129 		return QDF_STATUS_E_FAILURE;
4130 	}
4131 
4132 	if (verbose == QDF_TRACE_LEVEL_ALL) {
4133 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
4134 				0xFFFF;
4135 		return QDF_STATUS_SUCCESS;
4136 	}
4137 
4138 	if (verbose == QDF_TRACE_LEVEL_NONE) {
4139 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
4140 				QDF_TRACE_LEVEL_NONE;
4141 		return QDF_STATUS_SUCCESS;
4142 	}
4143 
4144 	if (!is_set) {
4145 		if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask
4146 		    & QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
4147 			print_ctrl_obj[idx].cat_info[category]
4148 				.category_verbose_mask &=
4149 				~QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
4150 		}
4151 	} else {
4152 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask |=
4153 				QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
4154 	}
4155 
4156 	pr_debug("%s: Print control object %d, Category %d, Verbose level %d\n",
4157 		__func__,
4158 		idx,
4159 		category,
4160 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask);
4161 
4162 	return QDF_STATUS_SUCCESS;
4163 }
4164 qdf_export_symbol(qdf_print_set_category_verbose);
4165 
4166 void qdf_log_dump_at_kernel_level(bool enable)
4167 {
4168 	if (qdf_log_dump_at_kernel_enable == enable) {
4169 		QDF_TRACE_INFO(QDF_MODULE_ID_QDF,
4170 			       "qdf_log_dump_at_kernel_enable is already %d\n",
4171 			       enable);
4172 	}
4173 	qdf_log_dump_at_kernel_enable = enable;
4174 }
4175 
4176 qdf_export_symbol(qdf_log_dump_at_kernel_level);
4177 
4178 bool qdf_print_is_category_enabled(unsigned int idx, QDF_MODULE_ID category)
4179 {
4180 	QDF_TRACE_LEVEL verbose_mask;
4181 
4182 	/* Check if index passed is valid */
4183 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4184 		pr_info("%s: Invalid index - %d\n", __func__, idx);
4185 		return false;
4186 	}
4187 
4188 	/* Check if print control object is in use */
4189 	if (!print_ctrl_obj[idx].in_use) {
4190 		pr_info("%s: Invalid print control object\n", __func__);
4191 		return false;
4192 	}
4193 
4194 	/* Check if category passed is valid */
4195 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
4196 		pr_info("%s: Invalid category: %d\n", __func__, category);
4197 		return false;
4198 	}
4199 
4200 	verbose_mask =
4201 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask;
4202 
4203 	if (verbose_mask == QDF_TRACE_LEVEL_NONE)
4204 		return false;
4205 	else
4206 		return true;
4207 }
4208 qdf_export_symbol(qdf_print_is_category_enabled);
4209 
4210 bool qdf_print_is_verbose_enabled(unsigned int idx, QDF_MODULE_ID category,
4211 				  QDF_TRACE_LEVEL verbose)
4212 {
4213 	bool verbose_enabled = false;
4214 
4215 	/* Check if index passed is valid */
4216 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4217 		pr_info("%s: Invalid index - %d\n", __func__, idx);
4218 		return verbose_enabled;
4219 	}
4220 
4221 	/* Check if print control object is in use */
4222 	if (!print_ctrl_obj[idx].in_use) {
4223 		pr_info("%s: Invalid print control object\n", __func__);
4224 		return verbose_enabled;
4225 	}
4226 
4227 	/* Check if category passed is valid */
4228 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
4229 		pr_info("%s: Invalid category: %d\n", __func__, category);
4230 		return verbose_enabled;
4231 	}
4232 
4233 	if ((verbose == QDF_TRACE_LEVEL_NONE) ||
4234 	    (verbose >= QDF_TRACE_LEVEL_MAX)) {
4235 		verbose_enabled = false;
4236 	} else if (verbose == QDF_TRACE_LEVEL_ALL) {
4237 		if (print_ctrl_obj[idx].cat_info[category]
4238 					.category_verbose_mask == 0xFFFF)
4239 			verbose_enabled = true;
4240 	} else {
4241 		verbose_enabled =
4242 		(print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
4243 		 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) ? true : false;
4244 	}
4245 
4246 	return verbose_enabled;
4247 }
4248 qdf_export_symbol(qdf_print_is_verbose_enabled);
4249 
4250 #ifdef DBG_LVL_MAC_FILTERING
4251 
4252 QDF_STATUS qdf_print_set_node_flag(unsigned int idx, uint8_t enable)
4253 {
4254 	/* Check if index passed is valid */
4255 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4256 		pr_info("%s: Invalid index - %d\n", __func__, idx);
4257 		return QDF_STATUS_E_FAILURE;
4258 	}
4259 
4260 	/* Check if print control object is in use */
4261 	if (!print_ctrl_obj[idx].in_use) {
4262 		pr_info("%s: Invalid print control object\n", __func__);
4263 		return QDF_STATUS_E_FAILURE;
4264 	}
4265 
4266 	if (enable > 1) {
4267 		pr_info("%s: Incorrect input: Use 1 or 0 to enable or disable\n",
4268 			__func__);
4269 		return QDF_STATUS_E_FAILURE;
4270 	}
4271 
4272 	print_ctrl_obj[idx].dbglvlmac_on = enable;
4273 	pr_info("%s: DbgLVLmac feature %s\n",
4274 		__func__,
4275 		((enable) ? "enabled" : "disabled"));
4276 
4277 	return QDF_STATUS_SUCCESS;
4278 }
4279 qdf_export_symbol(qdf_print_set_node_flag);
4280 
4281 bool qdf_print_get_node_flag(unsigned int idx)
4282 {
4283 	bool node_flag = false;
4284 
4285 	/* Check if index passed is valid */
4286 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4287 		pr_info("%s: Invalid index - %d\n", __func__, idx);
4288 		return node_flag;
4289 	}
4290 
4291 	/* Check if print control object is in use */
4292 	if (!print_ctrl_obj[idx].in_use) {
4293 		pr_info("%s: Invalid print control object\n", __func__);
4294 		return node_flag;
4295 	}
4296 
4297 	if (print_ctrl_obj[idx].dbglvlmac_on)
4298 		node_flag = true;
4299 
4300 	return node_flag;
4301 }
4302 qdf_export_symbol(qdf_print_get_node_flag);
4303 
4304 void qdf_print_clean_node_flag(unsigned int idx)
4305 {
4306 	/* Disable dbglvlmac_on during cleanup */
4307 	print_ctrl_obj[idx].dbglvlmac_on = 0;
4308 }
4309 
4310 #else
4311 
4312 void qdf_print_clean_node_flag(unsigned int idx)
4313 {
4314 	/* No operation in case of no support for DBG_LVL_MAC_FILTERING */
4315 	return;
4316 }
4317 #endif
4318 
4319 void QDF_PRINT_INFO(unsigned int idx, QDF_MODULE_ID module,
4320 		    QDF_TRACE_LEVEL level,
4321 		    char *str_format, ...)
4322 {
4323 	va_list args;
4324 
4325 	/* Generic wrapper API will compile qdf_vprint in order to
4326 	 * log the message. Once QDF converged debug framework is in
4327 	 * place, this will be changed to adapt to the framework, compiling
4328 	 * call to converged tracing API
4329 	 */
4330 	va_start(args, str_format);
4331 	qdf_vprint(str_format, args);
4332 	va_end(args);
4333 }
4334 qdf_export_symbol(QDF_PRINT_INFO);
4335 
4336 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4337 void qdf_logging_init(void)
4338 {
4339 	wlan_logging_sock_init_svc();
4340 	nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY);
4341 	wlan_logging_notifier_init(qdf_log_dump_at_kernel_enable);
4342 	wlan_logging_set_flush_timer(qdf_log_flush_timer_period);
4343 }
4344 
4345 void qdf_logging_exit(void)
4346 {
4347 	wlan_logging_notifier_deinit(qdf_log_dump_at_kernel_enable);
4348 	nl_srv_exit();
4349 	wlan_logging_sock_deinit_svc();
4350 }
4351 
4352 int qdf_logging_set_flush_timer(uint32_t milliseconds)
4353 {
4354 	if (wlan_logging_set_flush_timer(milliseconds) == 0)
4355 		return QDF_STATUS_SUCCESS;
4356 	else
4357 		return QDF_STATUS_E_FAILURE;
4358 }
4359 
4360 void qdf_logging_flush_logs(void)
4361 {
4362 	wlan_flush_host_logs_for_fatal();
4363 }
4364 
4365 #else
4366 void qdf_logging_init(void)
4367 {
4368 	nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY);
4369 }
4370 
4371 void qdf_logging_exit(void)
4372 {
4373 	nl_srv_exit();
4374 }
4375 
4376 int qdf_logging_set_flush_timer(uint32_t milliseconds)
4377 {
4378 	return QDF_STATUS_E_FAILURE;
4379 }
4380 
4381 void qdf_logging_flush_logs(void)
4382 {
4383 }
4384 #endif
4385 
4386 qdf_export_symbol(qdf_logging_set_flush_timer);
4387 qdf_export_symbol(qdf_logging_flush_logs);
4388 
4389 #ifdef CONFIG_KALLSYMS
4390 inline int qdf_sprint_symbol(char *buffer, void *addr)
4391 {
4392 	return sprint_symbol(buffer, (unsigned long)addr);
4393 }
4394 #else
4395 int qdf_sprint_symbol(char *buffer, void *addr)
4396 {
4397 	if (!buffer)
4398 		return 0;
4399 
4400 	buffer[0] = '\0';
4401 	return 1;
4402 }
4403 #endif
4404 qdf_export_symbol(qdf_sprint_symbol);
4405 
4406 void qdf_set_pidx(int pidx)
4407 {
4408 	qdf_pidx = pidx;
4409 }
4410 qdf_export_symbol(qdf_set_pidx);
4411 
4412 int qdf_get_pidx(void)
4413 {
4414 	return qdf_pidx;
4415 }
4416 qdf_export_symbol(qdf_get_pidx);
4417 
4418 #ifdef PANIC_ON_BUG
4419 #ifdef CONFIG_SLUB_DEBUG
4420 void __qdf_bug(void)
4421 {
4422 	BUG();
4423 }
4424 qdf_export_symbol(__qdf_bug);
4425 #endif /* CONFIG_SLUB_DEBUG */
4426 #endif /* PANIC_ON_BUG */
4427 
4428 #ifdef WLAN_QCOM_VA_MINIDUMP
4429 static bool qdf_va_md_initialized;
4430 static qdf_list_t qdf_va_md_list;
4431 static qdf_spinlock_t qdf_va_md_list_lock;
4432 #define QDF_MINIDUMP_LIST_SIZE 128
4433 
4434 struct qdf_va_md_entry {
4435 	qdf_list_node_t node;
4436 	struct va_md_entry data;
4437 };
4438 
4439 static int qdf_va_md_notif_handler(struct notifier_block *this,
4440 				   unsigned long event, void *ptr)
4441 {
4442 	struct qdf_va_md_entry *entry;
4443 	struct qdf_va_md_entry *next;
4444 
4445 	qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4446 	qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) {
4447 		qcom_va_md_add_region(&entry->data);
4448 	}
4449 
4450 	qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4451 	return NOTIFY_OK;
4452 }
4453 
4454 static struct notifier_block qdf_va_md_notif_blk = {
4455 	.notifier_call = qdf_va_md_notif_handler,
4456 	.priority = INT_MAX,
4457 };
4458 
4459 void __qdf_minidump_init(void)
4460 {
4461 	int ret;
4462 
4463 	if (qdf_va_md_initialized)
4464 		return;
4465 
4466 	qdf_spinlock_create(&qdf_va_md_list_lock);
4467 	qdf_list_create(&qdf_va_md_list, QDF_MINIDUMP_LIST_SIZE);
4468 	ret = qcom_va_md_register(qdf_trace_wlan_modname(),
4469 				  &qdf_va_md_notif_blk);
4470 	qdf_va_md_initialized = !ret;
4471 }
4472 
4473 qdf_export_symbol(__qdf_minidump_init);
4474 
4475 void __qdf_minidump_deinit(void)
4476 {
4477 	struct qdf_va_md_entry *entry;
4478 	struct qdf_va_md_entry *next;
4479 
4480 	if (!qdf_va_md_initialized)
4481 		return;
4482 
4483 	qdf_va_md_initialized = false;
4484 	qcom_va_md_unregister(qdf_trace_wlan_modname(),
4485 			      &qdf_va_md_notif_blk);
4486 	qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4487 	qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) {
4488 		qdf_list_remove_node(&qdf_va_md_list, &entry->node);
4489 		qdf_mem_free(entry);
4490 	}
4491 
4492 	qdf_list_destroy(&qdf_va_md_list);
4493 	qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4494 	qdf_spinlock_destroy(&qdf_va_md_list_lock);
4495 }
4496 
4497 qdf_export_symbol(__qdf_minidump_deinit);
4498 
4499 void __qdf_minidump_log(void *start_addr, size_t size, const char *name)
4500 {
4501 	struct qdf_va_md_entry *entry;
4502 	QDF_STATUS status;
4503 
4504 	if (!qdf_va_md_initialized)
4505 		return;
4506 
4507 	entry = qdf_mem_malloc(sizeof(*entry));
4508 	if (!entry) {
4509 		qdf_err("malloc failed for %s: %pK, %zu",
4510 			name, start_addr, size);
4511 		return;
4512 	}
4513 
4514 	qdf_str_lcopy(entry->data.owner, name, sizeof(entry->data.owner));
4515 	entry->data.vaddr = (unsigned long)start_addr;
4516 	entry->data.size = size;
4517 
4518 	qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4519 	status = qdf_list_insert_front(&qdf_va_md_list, &entry->node);
4520 	qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4521 	if (QDF_IS_STATUS_ERROR(status)) {
4522 		qdf_err("Failed to insert qdf va md entry, status %d", status);
4523 		qdf_mem_free(entry);
4524 	}
4525 }
4526 
4527 qdf_export_symbol(__qdf_minidump_log);
4528 
4529 void __qdf_minidump_remove(void *addr, size_t size, const char *name)
4530 {
4531 	struct qdf_va_md_entry *entry;
4532 	struct qdf_va_md_entry *next;
4533 
4534 	if (!qdf_va_md_initialized)
4535 		return;
4536 
4537 	qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4538 	qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) {
4539 		if (entry->data.vaddr == (unsigned long)addr &&
4540 		    entry->data.size == size &&
4541 		    !qdf_str_cmp(entry->data.owner, name)) {
4542 			qdf_list_remove_node(&qdf_va_md_list, &entry->node);
4543 			qdf_mem_free(entry);
4544 			break;
4545 		}
4546 	}
4547 
4548 	qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4549 }
4550 
4551 qdf_export_symbol(__qdf_minidump_remove);
4552 #endif
4553