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