xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/qdf_trace.c (revision 8cfe6b10058a04cafb17eed051f2ddf11bee8931)
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 	default:
1259 		return "invalid";
1260 	}
1261 }
1262 
1263 /**
1264  * qdf_dp_enable_check() - check if dptrace, TX/RX tracing is enabled
1265  * @nbuf: nbuf
1266  * @code: dptrace code
1267  * @dir: TX or RX direction
1268  *
1269  * Return: true/false
1270  */
1271 static bool qdf_dp_enable_check(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
1272 				enum qdf_proto_dir dir)
1273 {
1274 	/* Return when Dp trace is not enabled */
1275 	if (!g_qdf_dp_trace_data.enable)
1276 		return false;
1277 
1278 	if (qdf_dp_trace_verbosity_check(code) == false)
1279 		return false;
1280 
1281 	if (nbuf && (dir == QDF_TX && ((QDF_NBUF_CB_TX_DP_TRACE(nbuf) == 0) ||
1282 				       (QDF_NBUF_CB_TX_PACKET_TRACK(nbuf) !=
1283 					QDF_NBUF_TX_PKT_DATA_TRACK))))
1284 		return false;
1285 
1286 	if (nbuf && (dir == QDF_RX && (QDF_NBUF_CB_RX_DP_TRACE(nbuf) == 0)))
1287 		return false;
1288 
1289 	/*
1290 	 * Special packets called with NULL nbuf and this API is expected to
1291 	 * return true
1292 	 */
1293 	return true;
1294 }
1295 
1296 /**
1297  * qdf_dp_trace_fill_meta_str() - fill up a common meta string
1298  * @prepend_str: pointer to string
1299  * @size: size of prepend_str
1300  * @rec_index: index of record
1301  * @info: info related to the record
1302  * @record: pointer to the record
1303  *
1304  * Return: ret value from scnprintf
1305  */
1306 static inline
1307 int qdf_dp_trace_fill_meta_str(char *prepend_str, int size,
1308 			       int rec_index, uint8_t info,
1309 			       struct qdf_dp_trace_record_s *record)
1310 {
1311 	char buffer[20];
1312 	int ret = 0;
1313 	bool live = info & QDF_DP_TRACE_RECORD_INFO_LIVE ? true : false;
1314 	bool throttled = info & QDF_DP_TRACE_RECORD_INFO_THROTTLED ?
1315 								true : false;
1316 
1317 	scnprintf(buffer, sizeof(buffer), "%llu", record->time);
1318 	ret = scnprintf(prepend_str, size,
1319 			"%s DPT: %04d:%02d%s %s",
1320 			throttled ? "*" : "",
1321 			rec_index,
1322 			record->pdev_id,
1323 			live ? "" : buffer,
1324 			qdf_dp_code_to_string(record->code));
1325 
1326 	return ret;
1327 }
1328 
1329 /**
1330  * qdf_dp_fill_record_data() - fill meta data and data into the record
1331  * @rec: pointer to record data
1332  * @data: pointer to data
1333  * @data_size: size of the data
1334  * @meta_data: pointer to metadata
1335  * @metadata_size: size of metadata
1336  *
1337  * Should be called from within a spin_lock for the qdf record.
1338  * Fills up rec->data with |metadata|data|
1339  *
1340  * Return: none
1341  */
1342 static void qdf_dp_fill_record_data
1343 	(struct qdf_dp_trace_record_s *rec,
1344 	uint8_t *data, uint8_t data_size,
1345 	uint8_t *meta_data, uint8_t metadata_size)
1346 {
1347 	int32_t available = QDF_DP_TRACE_RECORD_SIZE;
1348 	uint8_t *rec_data = rec->data;
1349 	uint8_t data_to_copy = 0;
1350 
1351 	qdf_mem_zero(rec_data, QDF_DP_TRACE_RECORD_SIZE);
1352 
1353 	/* copy meta data */
1354 	if (meta_data) {
1355 		if (metadata_size > available) {
1356 			QDF_TRACE_WARN(QDF_MODULE_ID_QDF,
1357 				       "%s: meta data does not fit into the record",
1358 				       __func__);
1359 			goto end;
1360 		}
1361 		qdf_mem_copy(rec_data, meta_data, metadata_size);
1362 		available = available - metadata_size;
1363 	} else {
1364 		metadata_size = 0;
1365 	}
1366 
1367 	/* copy data */
1368 	if (data && (data_size > 0) && (available > 0)) {
1369 		data_to_copy = data_size;
1370 		if (data_size > available)
1371 			data_to_copy = available;
1372 		qdf_mem_copy(&rec_data[metadata_size], data, data_to_copy);
1373 	}
1374 end:
1375 	rec->size = data_to_copy;
1376 }
1377 
1378 /**
1379  * qdf_dp_add_record() - add dp trace record
1380  * @code: dptrace code
1381  * @pdev_id: pdev_id
1382  * @print: true to print it in kmsg
1383  * @data: data pointer
1384  * @data_size: size of data to be copied
1385  * @meta_data: meta data to be prepended to data
1386  * @metadata_size: sizeof meta data
1387  * @print: whether to print record
1388  *
1389  * Return: none
1390  */
1391 static void qdf_dp_add_record(enum QDF_DP_TRACE_ID code, uint8_t pdev_id,
1392 			      uint8_t *data, uint8_t data_size,
1393 			      uint8_t *meta_data, uint8_t metadata_size,
1394 			      bool print)
1395 
1396 {
1397 	struct qdf_dp_trace_record_s *rec = NULL;
1398 	int index;
1399 	bool print_this_record = false;
1400 	u8 info = 0;
1401 
1402 	if (code >= QDF_DP_TRACE_MAX) {
1403 		QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
1404 				"invalid record code %u, max code %u",
1405 				code, QDF_DP_TRACE_MAX);
1406 		return;
1407 	}
1408 
1409 	spin_lock_bh(&l_dp_trace_lock);
1410 
1411 	if (print || g_qdf_dp_trace_data.force_live_mode) {
1412 		print_this_record = true;
1413 	} else if (g_qdf_dp_trace_data.live_mode == 1) {
1414 		print_this_record = true;
1415 		g_qdf_dp_trace_data.print_pkt_cnt++;
1416 		if (g_qdf_dp_trace_data.print_pkt_cnt >
1417 				g_qdf_dp_trace_data.high_tput_thresh) {
1418 			g_qdf_dp_trace_data.live_mode = 0;
1419 			g_qdf_dp_trace_data.verbosity =
1420 					QDF_DP_TRACE_VERBOSITY_ULTRA_LOW;
1421 			info |= QDF_DP_TRACE_RECORD_INFO_THROTTLED;
1422 		}
1423 	}
1424 
1425 	g_qdf_dp_trace_data.num++;
1426 
1427 	if (g_qdf_dp_trace_data.num > MAX_QDF_DP_TRACE_RECORDS)
1428 		g_qdf_dp_trace_data.num = MAX_QDF_DP_TRACE_RECORDS;
1429 
1430 	if (INVALID_QDF_DP_TRACE_ADDR == g_qdf_dp_trace_data.head) {
1431 		/* first record */
1432 		g_qdf_dp_trace_data.head = 0;
1433 		g_qdf_dp_trace_data.tail = 0;
1434 	} else {
1435 		/* queue is not empty */
1436 		g_qdf_dp_trace_data.tail++;
1437 
1438 		if (MAX_QDF_DP_TRACE_RECORDS == g_qdf_dp_trace_data.tail)
1439 			g_qdf_dp_trace_data.tail = 0;
1440 
1441 		if (g_qdf_dp_trace_data.head == g_qdf_dp_trace_data.tail) {
1442 			/* full */
1443 			if (MAX_QDF_DP_TRACE_RECORDS ==
1444 				++g_qdf_dp_trace_data.head)
1445 				g_qdf_dp_trace_data.head = 0;
1446 		}
1447 	}
1448 
1449 	rec = &g_qdf_dp_trace_tbl[g_qdf_dp_trace_data.tail];
1450 	index = g_qdf_dp_trace_data.tail;
1451 	rec->code = code;
1452 	rec->pdev_id = pdev_id;
1453 	rec->size = 0;
1454 	qdf_dp_fill_record_data(rec, data, data_size,
1455 				meta_data, metadata_size);
1456 	rec->time = qdf_get_log_timestamp();
1457 	rec->pid = (in_interrupt() ? 0 : current->pid);
1458 
1459 	if (rec->code >= QDF_DP_TRACE_MAX) {
1460 		QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
1461 				"invalid record code %u, max code %u",
1462 				rec->code, QDF_DP_TRACE_MAX);
1463 		return;
1464 	}
1465 
1466 	spin_unlock_bh(&l_dp_trace_lock);
1467 
1468 	info |= QDF_DP_TRACE_RECORD_INFO_LIVE;
1469 	if (print_this_record)
1470 		qdf_dp_trace_cb_table[rec->code] (rec, index,
1471 					QDF_TRACE_DEFAULT_PDEV_ID, info);
1472 }
1473 
1474 /**
1475  * qdf_get_rate_limit_by_type() - Get the rate limit by pkt type
1476  * @type: packet type
1477  *
1478  * Return: Rate limit value for a particular packet type
1479  */
1480 static inline
1481 uint8_t qdf_get_rate_limit_by_type(uint8_t type)
1482 {
1483 	switch (type) {
1484 	case QDF_PROTO_TYPE_DHCP:
1485 		return QDF_MAX_DHCP_PKTS_PER_SEC;
1486 	case QDF_PROTO_TYPE_EAPOL:
1487 		return QDF_MAX_EAPOL_PKTS_PER_SEC;
1488 	case QDF_PROTO_TYPE_ARP:
1489 		return QDF_MAX_ARP_PKTS_PER_SEC;
1490 	case QDF_PROTO_TYPE_DNS:
1491 		return QDF_MAX_DNS_PKTS_PER_SEC;
1492 	default:
1493 		return QDF_MAX_OTHER_PKTS_PER_SEC;
1494 	}
1495 }
1496 
1497 /**
1498  * qdf_get_pkt_type_string() - Get the string based on pkt type
1499  * @type: packet type
1500  * @subtype: packet subtype
1501  *
1502  * Return: String based on pkt type
1503  */
1504 static
1505 uint8_t *qdf_get_pkt_type_string(uint8_t type, uint8_t subtype)
1506 {
1507 	switch (subtype) {
1508 	case QDF_PROTO_EAPOL_M1:
1509 		return "EAPOL-1";
1510 	case QDF_PROTO_EAPOL_M2:
1511 		return "EAPOL-2";
1512 	case QDF_PROTO_EAPOL_M3:
1513 		return "EAPOL-3";
1514 	case QDF_PROTO_EAPOL_M4:
1515 		return "EAPOL-4";
1516 	case QDF_PROTO_DHCP_DISCOVER:
1517 		return "DHCP-D";
1518 	case QDF_PROTO_DHCP_REQUEST:
1519 		return "DHCP-R";
1520 	case QDF_PROTO_DHCP_OFFER:
1521 		return "DHCP-O";
1522 	case QDF_PROTO_DHCP_ACK:
1523 		return "DHCP-A";
1524 	case QDF_PROTO_DHCP_NACK:
1525 		return "DHCP-NA";
1526 	case QDF_PROTO_DHCP_RELEASE:
1527 		return "DHCP-REL";
1528 	case QDF_PROTO_DHCP_INFORM:
1529 		return "DHCP-IN";
1530 	case QDF_PROTO_DHCP_DECLINE:
1531 		return "DHCP-DEC";
1532 	case QDF_PROTO_ARP_REQ:
1533 		return "ARP-RQ";
1534 	case QDF_PROTO_ARP_RES:
1535 		return "ARP-RS";
1536 	case QDF_PROTO_DNS_QUERY:
1537 		return "DNS_Q";
1538 	case QDF_PROTO_DNS_RES:
1539 		return "DNS_RS";
1540 	case QDF_PROTO_EAP_REQUEST:
1541 		return "EAP_REQ";
1542 	case QDF_PROTO_EAP_RESPONSE:
1543 		return "EAP-RSP";
1544 	case QDF_PROTO_EAP_SUCCESS:
1545 		return "EAP-SUCCESS";
1546 	case QDF_PROTO_EAP_FAILURE:
1547 		return "EAP-FAIL";
1548 	case QDF_PROTO_EAP_INITIATE:
1549 		return "EAP-INIT";
1550 	case QDF_PROTO_EAP_FINISH:
1551 		return "EAP-FINISH";
1552 	case QDF_PROTO_EAPOL_START:
1553 		return "EAPOL-START";
1554 	case QDF_PROTO_EAPOL_LOGOFF:
1555 		return "EAPOL-LOGOFF";
1556 	case QDF_PROTO_EAPOL_ASF:
1557 		return "EAPOL-ASF";
1558 	default:
1559 		switch (type) {
1560 		case QDF_PROTO_TYPE_EAPOL:
1561 			return "EAP";
1562 		case QDF_PROTO_TYPE_DHCP:
1563 			return "DHCP";
1564 		case QDF_PROTO_TYPE_ARP:
1565 			return "ARP";
1566 		case QDF_PROTO_TYPE_DNS:
1567 			return "DNS";
1568 		default:
1569 			return "UNKNOWN";
1570 		}
1571 	}
1572 }
1573 
1574 /**
1575  * qdf_get_pkt_status_string() - Get the string based on pkt status
1576  * @status: packet status
1577  *
1578  * Return: String based on pkt status
1579  */
1580 static
1581 uint8_t *qdf_get_pkt_status_string(uint8_t status)
1582 {
1583 	switch (status) {
1584 	case QDF_TX_RX_STATUS_INVALID:
1585 		return "inv";
1586 	case QDF_TX_RX_STATUS_OK:
1587 		return "succ";
1588 	case QDF_TX_RX_STATUS_FW_DISCARD:
1589 		return "disc";
1590 	case QDF_TX_RX_STATUS_NO_ACK:
1591 		return "nack";
1592 	case QDF_TX_RX_STATUS_DROP:
1593 		return "drop";
1594 	default:
1595 		return "unknown";
1596 	}
1597 }
1598 
1599 /**
1600  * qdf_dp_log_proto_pkt_info() - Send diag log with pkt info
1601  * @sa: Source MAC address
1602  * @da: Destination MAC address
1603  * @type: packet type
1604  * @subtype: packet subtype
1605  * @dir: tx or rx
1606  * @msdu_id: MSDU id
1607  * @status: status code
1608  *
1609  * Return: none
1610  */
1611 void qdf_dp_log_proto_pkt_info(uint8_t *sa, uint8_t *da, uint8_t type,
1612 			       uint8_t subtype, uint8_t dir, uint16_t msdu_id,
1613 			       uint8_t status)
1614 {
1615 	uint8_t pkt_rate_limit;
1616 	static ulong last_ticks_tx[QDF_PROTO_SUBTYPE_MAX] = {0};
1617 	static ulong last_ticks_rx[QDF_PROTO_SUBTYPE_MAX] = {0};
1618 	ulong curr_ticks = jiffies;
1619 
1620 	pkt_rate_limit = qdf_get_rate_limit_by_type(type);
1621 
1622 	if ((dir == QDF_TX &&
1623 	     !time_after(curr_ticks,
1624 			 last_ticks_tx[subtype] + HZ / pkt_rate_limit)) ||
1625 	    (dir == QDF_RX &&
1626 	     !time_after(curr_ticks,
1627 			 last_ticks_rx[subtype] + HZ / pkt_rate_limit)))
1628 		return;
1629 
1630 	if (dir == QDF_TX)
1631 		last_ticks_tx[subtype] = curr_ticks;
1632 	else
1633 		last_ticks_rx[subtype] = curr_ticks;
1634 
1635 	if (status == QDF_TX_RX_STATUS_INVALID)
1636 		qdf_nofl_info("%s %s: SA:" QDF_MAC_ADDR_FMT " DA:" QDF_MAC_ADDR_FMT,
1637 			      qdf_get_pkt_type_string(type, subtype),
1638 			      dir ? "RX" : "TX", QDF_MAC_ADDR_REF(sa),
1639 			      QDF_MAC_ADDR_REF(da));
1640 	else
1641 		qdf_nofl_info("%s %s: SA:" QDF_MAC_ADDR_FMT " DA:" QDF_MAC_ADDR_FMT " msdu_id:%d status: %s",
1642 			      qdf_get_pkt_type_string(type, subtype),
1643 			      dir ? "RX" : "TX", QDF_MAC_ADDR_REF(sa),
1644 			      QDF_MAC_ADDR_REF(da), msdu_id,
1645 			      qdf_get_pkt_status_string(status));
1646 }
1647 
1648 qdf_export_symbol(qdf_dp_log_proto_pkt_info);
1649 
1650 /**
1651  * qdf_log_icmpv6_pkt() - log ICMPv6 packet
1652  * @vdev_id: ID of the vdev
1653  * @skb: skb pointer
1654  * @dir: direction
1655  * @pdev_id: ID of the pdev
1656  *
1657  * Return: true/false
1658  */
1659 static bool qdf_log_icmpv6_pkt(uint8_t vdev_id, struct sk_buff *skb,
1660 			       enum qdf_proto_dir dir, uint8_t pdev_id)
1661 {
1662 	enum qdf_proto_subtype subtype;
1663 
1664 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMPv6) &&
1665 		((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ICMPv6 ==
1666 			QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1667 		 (dir == QDF_RX && qdf_nbuf_is_icmpv6_pkt(skb) == true))) {
1668 
1669 		subtype = qdf_nbuf_get_icmpv6_subtype(skb);
1670 
1671 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false;
1672 		if (dir == QDF_TX)
1673 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1674 		else if (dir == QDF_RX)
1675 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1676 
1677 		DPTRACE(qdf_dp_trace_proto_pkt(
1678 			QDF_DP_TRACE_ICMPv6_PACKET_RECORD,
1679 			vdev_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
1680 			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
1681 			QDF_PROTO_TYPE_ICMPv6, subtype, dir, pdev_id, false, 0));
1682 
1683 		switch (subtype) {
1684 		case QDF_PROTO_ICMPV6_REQ:
1685 			g_qdf_dp_trace_data.icmpv6_req++;
1686 			break;
1687 		case QDF_PROTO_ICMPV6_RES:
1688 			g_qdf_dp_trace_data.icmpv6_resp++;
1689 			break;
1690 		case QDF_PROTO_ICMPV6_RS:
1691 			g_qdf_dp_trace_data.icmpv6_rs++;
1692 			break;
1693 		case QDF_PROTO_ICMPV6_RA:
1694 			g_qdf_dp_trace_data.icmpv6_ra++;
1695 			break;
1696 		case QDF_PROTO_ICMPV6_NS:
1697 			g_qdf_dp_trace_data.icmpv6_ns++;
1698 			break;
1699 		case QDF_PROTO_ICMPV6_NA:
1700 			g_qdf_dp_trace_data.icmpv6_na++;
1701 			break;
1702 		default:
1703 			break;
1704 		}
1705 		return true;
1706 	}
1707 
1708 	return false;
1709 }
1710 
1711 /**
1712  * qdf_log_icmp_pkt() - log ICMP packet
1713  * @vdev_id: ID of the vdev
1714  * @skb: skb pointer
1715  * @dir: direction
1716  * @pdev_id: ID of the pdev
1717  *
1718  * Return: true/false
1719  */
1720 static bool qdf_log_icmp_pkt(uint8_t vdev_id, struct sk_buff *skb,
1721 			     enum qdf_proto_dir dir, uint8_t pdev_id)
1722 {
1723 	enum qdf_proto_subtype proto_subtype;
1724 	uint8_t *data = NULL;
1725 	uint16_t seq_num = 0;
1726 	uint16_t icmp_id = 0;
1727 	uint32_t proto_priv_data = 0;
1728 
1729 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMP) &&
1730 	    (qdf_nbuf_is_icmp_pkt(skb) == true)) {
1731 
1732 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false;
1733 		proto_subtype = qdf_nbuf_get_icmp_subtype(skb);
1734 
1735 		data = qdf_nbuf_data(skb);
1736 		icmp_id = qdf_cpu_to_be16(*(uint16_t *)(data + ICMP_ID_OFFSET));
1737 		seq_num = qdf_cpu_to_be16(*(uint16_t *)(data + ICMP_SEQ_NUM_OFFSET));
1738 
1739 		proto_priv_data |= ((proto_priv_data | ((uint32_t)icmp_id)) << 16);
1740 		proto_priv_data |= (uint32_t)seq_num;
1741 
1742 		if (QDF_TX == dir)
1743 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1744 		else if (QDF_RX == dir)
1745 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1746 
1747 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ICMP_PACKET_RECORD,
1748 					       vdev_id,
1749 					       skb->data +
1750 					       QDF_NBUF_SRC_MAC_OFFSET,
1751 					       skb->data +
1752 					       QDF_NBUF_DEST_MAC_OFFSET,
1753 					       QDF_PROTO_TYPE_ICMP,
1754 					       proto_subtype, dir, pdev_id,
1755 					       false, proto_priv_data));
1756 
1757 		if (proto_subtype == QDF_PROTO_ICMP_REQ)
1758 			g_qdf_dp_trace_data.icmp_req++;
1759 		else
1760 			g_qdf_dp_trace_data.icmp_resp++;
1761 
1762 		return true;
1763 	}
1764 	return false;
1765 }
1766 
1767 #ifdef CONNECTIVITY_DIAG_EVENT
1768 enum diag_tx_status wlan_get_diag_tx_status(enum qdf_dp_tx_rx_status tx_status)
1769 {
1770 	switch (tx_status) {
1771 	case DIAG_TX_RX_STATUS_FW_DISCARD:
1772 	case DIAG_TX_RX_STATUS_INVALID:
1773 	case DIAG_TX_RX_STATUS_DROP:
1774 	case DIAG_TX_RX_STATUS_DOWNLOAD_SUCC:
1775 	case DIAG_TX_RX_STATUS_DEFAULT:
1776 	default:
1777 		return DIAG_TX_STATUS_FAIL;
1778 	case DIAG_TX_RX_STATUS_NO_ACK:
1779 		return DIAG_TX_STATUS_NO_ACK;
1780 	case DIAG_TX_RX_STATUS_OK:
1781 		return DIAG_TX_STATUS_ACK;
1782 	}
1783 
1784 	return DIAG_TX_STATUS_FAIL;
1785 }
1786 
1787 /**
1788  * qdf_subtype_to_wlan_main_tag() - Convert qdf subtype to wlan main tag
1789  * @subtype: EAPoL key subtype
1790  *
1791  * Return: Wlan main tag subtype
1792  */
1793 static int qdf_subtype_to_wlan_main_tag(enum qdf_proto_subtype subtype)
1794 {
1795 	switch (subtype) {
1796 	case QDF_PROTO_DHCP_DISCOVER:
1797 		return WLAN_CONN_DIAG_DHCP_DISC_EVENT;
1798 	case QDF_PROTO_DHCP_REQUEST:
1799 		return WLAN_CONN_DIAG_DHCP_REQUEST_EVENT;
1800 	case QDF_PROTO_DHCP_OFFER:
1801 		return WLAN_CONN_DIAG_DHCP_OFFER_EVENT;
1802 	case QDF_PROTO_DHCP_ACK:
1803 		return WLAN_CONN_DIAG_DHCP_ACK_EVENT;
1804 	case QDF_PROTO_DHCP_NACK:
1805 		return WLAN_CONN_DIAG_DHCP_NACK_EVENT;
1806 	case QDF_PROTO_EAPOL_M1:
1807 		return WLAN_CONN_DIAG_EAPOL_M1_EVENT;
1808 	case QDF_PROTO_EAPOL_M2:
1809 		return WLAN_CONN_DIAG_EAPOL_M2_EVENT;
1810 	case QDF_PROTO_EAPOL_M3:
1811 		return WLAN_CONN_DIAG_EAPOL_M3_EVENT;
1812 	case QDF_PROTO_EAPOL_M4:
1813 		return WLAN_CONN_DIAG_EAPOL_M4_EVENT;
1814 	case QDF_PROTO_EAP_REQUEST:
1815 		return WLAN_CONN_DIAG_EAP_REQ_EVENT;
1816 	case QDF_PROTO_EAP_RESPONSE:
1817 		return WLAN_CONN_DIAG_EAP_RESP_EVENT;
1818 	case QDF_PROTO_EAP_SUCCESS:
1819 		return WLAN_CONN_DIAG_EAP_SUCC_EVENT;
1820 	case QDF_PROTO_EAP_FAILURE:
1821 		return WLAN_CONN_DIAG_EAP_FAIL_EVENT;
1822 	case QDF_PROTO_EAPOL_START:
1823 		return WLAN_CONN_DIAG_EAP_START_EVENT;
1824 	default:
1825 		return WLAN_CONN_DIAG_MAX;
1826 	}
1827 }
1828 
1829 /**
1830  * qdf_get_wlan_eap_code() - Get EAP code
1831  * @data: skb data pointer
1832  *
1833  * Return: EAP code value
1834  */
1835 static int qdf_get_wlan_eap_code(uint8_t *data)
1836 {
1837 	uint8_t code = *(data + EAP_CODE_OFFSET);
1838 
1839 	switch (code) {
1840 	case QDF_EAP_REQUEST:
1841 		return WLAN_CONN_DIAG_EAP_REQ_EVENT;
1842 	case QDF_EAP_RESPONSE:
1843 		return WLAN_CONN_DIAG_EAP_RESP_EVENT;
1844 	case QDF_EAP_SUCCESS:
1845 		return WLAN_CONN_DIAG_EAP_SUCC_EVENT;
1846 	case QDF_EAP_FAILURE:
1847 		return WLAN_CONN_DIAG_EAP_FAIL_EVENT;
1848 	default:
1849 		return WLAN_CONN_DIAG_MAX;
1850 	}
1851 }
1852 
1853 /**
1854  * qdf_eapol_get_key_type() - Get EAPOL key type
1855  * @data: skb data pointer
1856  * @subtype: EAPoL key subtype
1857  *
1858  * Return: EAPOL key type
1859  */
1860 static
1861 uint8_t qdf_eapol_get_key_type(uint8_t *data, enum qdf_proto_subtype subtype)
1862 {
1863 	uint16_t key_info = *(uint16_t *)(data + EAPOL_KEY_INFO_OFFSET);
1864 
1865 	/* If key type is PTK, key type will be set in EAPOL Key info */
1866 	if (key_info & EAPOL_KEY_TYPE_MASK)
1867 		return qdf_subtype_to_wlan_main_tag(subtype);
1868 	else if (key_info & EAPOL_KEY_ENCRYPTED_MASK)
1869 		return WLAN_CONN_DIAG_GTK_M1_EVENT;
1870 	else
1871 		return WLAN_CONN_DIAG_GTK_M2_EVENT;
1872 }
1873 
1874 /**
1875  * qdf_skip_wlan_connectivity_log() - Check if connectivity log need to skip
1876  * @type: Protocol type
1877  * @subtype: Protocol subtype
1878  * @dir: Rx or Tx
1879  *
1880  * Return: true or false
1881  */
1882 static inline
1883 bool qdf_skip_wlan_connectivity_log(enum qdf_proto_type type,
1884 				    enum qdf_proto_subtype subtype,
1885 				    enum qdf_proto_dir dir)
1886 {
1887 	if (dir == QDF_RX && type == QDF_PROTO_TYPE_DHCP &&
1888 	    (subtype == QDF_PROTO_DHCP_DISCOVER ||
1889 	     subtype == QDF_PROTO_DHCP_REQUEST))
1890 		return true;
1891 	return false;
1892 }
1893 
1894 /**
1895  * qdf_fill_wlan_connectivity_log() - Fill and queue protocol packet to logging
1896  * the logging queue
1897  * @type: Protocol type
1898  * @subtype: Protocol subtype
1899  * @dir: Rx or Tx
1900  * @qdf_tx_status: Tx completion status
1901  * @vdev_id: DP vdev ID
1902  * @data: skb data pointer
1903  *
1904  * Return: None
1905  */
1906 static
1907 void qdf_fill_wlan_connectivity_log(enum qdf_proto_type type,
1908 				    enum qdf_proto_subtype subtype,
1909 				    enum qdf_proto_dir dir,
1910 				    enum qdf_dp_tx_rx_status qdf_tx_status,
1911 				    uint8_t vdev_id, uint8_t *data)
1912 {
1913 	uint8_t pkt_type;
1914 
1915 	WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_packet_info);
1916 
1917 	if (qdf_skip_wlan_connectivity_log(type, subtype, dir))
1918 		return;
1919 
1920 	qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
1921 
1922 	wlan_diag_event.diag_cmn.timestamp_us =
1923 					qdf_get_time_of_the_day_ms() * 1000;
1924 	wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get());
1925 	wlan_diag_event.diag_cmn.vdev_id = vdev_id;
1926 
1927 	wlan_diag_event.version = DIAG_MGMT_VERSION;
1928 
1929 	if (type == QDF_PROTO_TYPE_DHCP) {
1930 		wlan_diag_event.subtype =
1931 					qdf_subtype_to_wlan_main_tag(subtype);
1932 	} else if (type == QDF_PROTO_TYPE_EAPOL) {
1933 		pkt_type = *(data + EAPOL_PACKET_TYPE_OFFSET);
1934 		if (pkt_type == EAPOL_PACKET_TYPE_EAP) {
1935 			wlan_diag_event.subtype =
1936 						qdf_get_wlan_eap_code(data);
1937 			wlan_diag_event.eap_type =
1938 						*(data + EAP_TYPE_OFFSET);
1939 			wlan_diag_event.eap_len =
1940 			   qdf_ntohs(*(uint16_t *)(data + EAP_LENGTH_OFFSET));
1941 		} else if (pkt_type == EAPOL_PACKET_TYPE_KEY) {
1942 			wlan_diag_event.subtype =
1943 					qdf_eapol_get_key_type(data, subtype);
1944 		} else if (pkt_type == EAPOL_PACKET_TYPE_START) {
1945 			wlan_diag_event.subtype =
1946 					WLAN_CONN_DIAG_EAP_START_EVENT;
1947 			wlan_diag_event.eap_len =
1948 			    qdf_ntohs(*(uint16_t *)(data + EAPOL_PKT_LEN_OFFSET));
1949 		} else {
1950 			return;
1951 		}
1952 	} else {
1953 		return;
1954 	}
1955 
1956 	/*Tx completion status needs to be logged*/
1957 	if (dir == QDF_TX)
1958 		wlan_diag_event.tx_status =
1959 					wlan_get_diag_tx_status(qdf_tx_status);
1960 
1961 	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_CONN_DP);
1962 }
1963 
1964 #elif defined(WLAN_FEATURE_CONNECTIVITY_LOGGING)
1965 /**
1966  * qdf_subtype_to_wlan_main_tag() - Convert qdf subtype to wlan main tag
1967  * @subtype: EAPoL key subtype
1968  *
1969  * Return: Wlan main tag subtype
1970  */
1971 static int qdf_subtype_to_wlan_main_tag(enum qdf_proto_subtype subtype)
1972 {
1973 	switch (subtype) {
1974 	case QDF_PROTO_DHCP_DISCOVER:
1975 		return WLAN_DHCP_DISCOVER;
1976 	case QDF_PROTO_DHCP_REQUEST:
1977 		return WLAN_DHCP_REQUEST;
1978 	case QDF_PROTO_DHCP_OFFER:
1979 		return WLAN_DHCP_OFFER;
1980 	case QDF_PROTO_DHCP_ACK:
1981 		return WLAN_DHCP_ACK;
1982 	case QDF_PROTO_DHCP_NACK:
1983 		return WLAN_DHCP_NACK;
1984 	case QDF_PROTO_EAPOL_M1:
1985 		return WLAN_EAPOL_M1;
1986 	case QDF_PROTO_EAPOL_M2:
1987 		return WLAN_EAPOL_M2;
1988 	case QDF_PROTO_EAPOL_M3:
1989 		return WLAN_EAPOL_M3;
1990 	case QDF_PROTO_EAPOL_M4:
1991 		return WLAN_EAPOL_M4;
1992 	default:
1993 		return WLAN_TAG_MAX;
1994 	}
1995 }
1996 
1997 /**
1998  * qdf_get_wlan_eap_code() - Get EAP code
1999  * @data: skb data pointer
2000  *
2001  * Return: EAP code value
2002  */
2003 static int qdf_get_wlan_eap_code(uint8_t *data)
2004 {
2005 	uint8_t code = *(data + EAP_CODE_OFFSET);
2006 
2007 	switch (code) {
2008 	case QDF_EAP_REQUEST:
2009 		return WLAN_EAP_REQUEST;
2010 	case QDF_EAP_RESPONSE:
2011 		return WLAN_EAP_RESPONSE;
2012 	case QDF_EAP_SUCCESS:
2013 		return WLAN_EAP_SUCCESS;
2014 	case QDF_EAP_FAILURE:
2015 		return WLAN_EAP_FAILURE;
2016 	default:
2017 		return WLAN_TAG_MAX;
2018 	}
2019 }
2020 
2021 /**
2022  * qdf_eapol_get_key_type() - Get EAPOL key type
2023  * @data: skb data pointer
2024  * @subtype: EAPoL key subtype
2025  *
2026  * Return: EAPOL key type
2027  */
2028 static
2029 uint8_t qdf_eapol_get_key_type(uint8_t *data, enum qdf_proto_subtype subtype)
2030 {
2031 	uint16_t key_info = *(uint16_t *)(data + EAPOL_KEY_INFO_OFFSET);
2032 
2033 	/* If key type is PTK, key type will be set in EAPOL Key info */
2034 	if (key_info & EAPOL_KEY_TYPE_MASK)
2035 		return qdf_subtype_to_wlan_main_tag(subtype);
2036 	else if (key_info & EAPOL_KEY_ENCRYPTED_MASK)
2037 		return WLAN_GTK_M1;
2038 	else
2039 		return WLAN_GTK_M2;
2040 }
2041 
2042 /**
2043  * qdf_skip_wlan_connectivity_log() - Check if connectivity log need to skip
2044  * @type: Protocol type
2045  * @subtype: Protocol subtype
2046  * @dir: Rx or Tx
2047  *
2048  * Return: true or false
2049  */
2050 static inline
2051 bool qdf_skip_wlan_connectivity_log(enum qdf_proto_type type,
2052 				    enum qdf_proto_subtype subtype,
2053 				    enum qdf_proto_dir dir)
2054 {
2055 	if ((dir == QDF_RX) && (type == QDF_PROTO_TYPE_DHCP) &&
2056 	    ((subtype == QDF_PROTO_DHCP_DISCOVER) ||
2057 	     (subtype == QDF_PROTO_DHCP_REQUEST)))
2058 		return true;
2059 	return false;
2060 }
2061 
2062 static
2063 void qdf_fill_wlan_connectivity_log(enum qdf_proto_type type,
2064 				    enum qdf_proto_subtype subtype,
2065 				    enum qdf_proto_dir dir,
2066 				    enum qdf_dp_tx_rx_status qdf_tx_status,
2067 				    uint8_t vdev_id, uint8_t *data)
2068 {
2069 	struct wlan_log_record log_buf = {0};
2070 	uint8_t pkt_type;
2071 
2072 	if (qdf_skip_wlan_connectivity_log(type, subtype, dir))
2073 		return;
2074 
2075 	log_buf.timestamp_us = qdf_get_time_of_the_day_ms() * 1000;
2076 	log_buf.ktime_us = qdf_ktime_to_us(qdf_ktime_get());
2077 	log_buf.vdev_id = vdev_id;
2078 	if (type == QDF_PROTO_TYPE_DHCP) {
2079 		log_buf.log_subtype = qdf_subtype_to_wlan_main_tag(subtype);
2080 	} else if (type == QDF_PROTO_TYPE_EAPOL) {
2081 		pkt_type = *(data + EAPOL_PACKET_TYPE_OFFSET);
2082 		if (pkt_type == EAPOL_PACKET_TYPE_EAP) {
2083 			log_buf.log_subtype = qdf_get_wlan_eap_code(data);
2084 			log_buf.pkt_info.eap_type = *(data + EAP_TYPE_OFFSET);
2085 			log_buf.pkt_info.eap_len =
2086 			   qdf_ntohs(*(uint16_t *)(data + EAP_LENGTH_OFFSET));
2087 		} else if (pkt_type == EAPOL_PACKET_TYPE_KEY) {
2088 			log_buf.log_subtype = qdf_eapol_get_key_type(data,
2089 								     subtype);
2090 		} else {
2091 			return;
2092 		}
2093 	} else {
2094 		return;
2095 	}
2096 
2097 	/*Tx completion status needs to be logged*/
2098 	if (dir == QDF_TX)
2099 		log_buf.pkt_info.tx_status = qdf_tx_status;
2100 
2101 	wlan_connectivity_log_enqueue(&log_buf);
2102 }
2103 
2104 #else
2105 static inline
2106 void qdf_fill_wlan_connectivity_log(enum qdf_proto_type type,
2107 				    enum qdf_proto_subtype subtype,
2108 				    enum qdf_proto_dir dir,
2109 				    enum qdf_dp_tx_rx_status qdf_tx_status,
2110 				    uint8_t vdev_id, uint8_t *data)
2111 {
2112 }
2113 #endif
2114 
2115 /**
2116  * qdf_log_eapol_pkt() - log EAPOL packet
2117  * @vdev_id: ID of the vdev
2118  * @skb: skb pointer
2119  * @dir: direction
2120  * @pdev_id: ID of the pdev
2121  *
2122  * Return: true/false
2123  */
2124 static bool qdf_log_eapol_pkt(uint8_t vdev_id, struct sk_buff *skb,
2125 			      enum qdf_proto_dir dir, uint8_t pdev_id)
2126 {
2127 	enum qdf_proto_subtype subtype;
2128 	uint32_t dp_eap_trace;
2129 	uint32_t dp_eap_event;
2130 
2131 	dp_eap_trace = qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
2132 	dp_eap_event = qdf_dp_get_proto_event_bitmap() &
2133 				QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
2134 
2135 	if (!dp_eap_trace && !dp_eap_event)
2136 		return false;
2137 
2138 	if (!((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_EAPOL ==
2139 	       QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
2140 	      (dir == QDF_RX && qdf_nbuf_is_ipv4_eapol_pkt(skb) == true)))
2141 		return false;
2142 
2143 	subtype = qdf_nbuf_get_eapol_subtype(skb);
2144 
2145 	if (dp_eap_event && dir == QDF_RX) {
2146 		qdf_dp_log_proto_pkt_info(skb->data + QDF_NBUF_SRC_MAC_OFFSET,
2147 					  skb->data + QDF_NBUF_DEST_MAC_OFFSET,
2148 					  QDF_PROTO_TYPE_EAPOL, subtype, dir,
2149 					  QDF_TRACE_DEFAULT_MSDU_ID,
2150 					  QDF_TX_RX_STATUS_INVALID);
2151 		qdf_fill_wlan_connectivity_log(QDF_PROTO_TYPE_EAPOL, subtype,
2152 					       QDF_RX, 0, vdev_id, skb->data);
2153 	}
2154 
2155 	if (dp_eap_trace) {
2156 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
2157 		if (QDF_TX == dir)
2158 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
2159 		else if (QDF_RX == dir)
2160 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
2161 
2162 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_EAPOL_PACKET_RECORD,
2163 					       vdev_id,
2164 					       skb->data +
2165 					       QDF_NBUF_SRC_MAC_OFFSET,
2166 					       skb->data +
2167 					       QDF_NBUF_DEST_MAC_OFFSET,
2168 					       QDF_PROTO_TYPE_EAPOL, subtype,
2169 					       dir, pdev_id, true, 0));
2170 
2171 		switch (subtype) {
2172 		case QDF_PROTO_EAPOL_M1:
2173 			g_qdf_dp_trace_data.eapol_m1++;
2174 			break;
2175 		case QDF_PROTO_EAPOL_M2:
2176 			g_qdf_dp_trace_data.eapol_m2++;
2177 			break;
2178 		case QDF_PROTO_EAPOL_M3:
2179 			g_qdf_dp_trace_data.eapol_m3++;
2180 			break;
2181 		case QDF_PROTO_EAPOL_M4:
2182 			g_qdf_dp_trace_data.eapol_m4++;
2183 			break;
2184 		default:
2185 			g_qdf_dp_trace_data.eapol_others++;
2186 			break;
2187 		}
2188 	}
2189 
2190 	return true;
2191 }
2192 
2193 /**
2194  * qdf_log_dhcp_pkt() - log DHCP packet
2195  * @vdev_id: ID of the vdev
2196  * @skb: skb pointer
2197  * @dir: direction
2198  * @pdev_id: ID of the pdev
2199  *
2200  * Return: true/false
2201  */
2202 static bool qdf_log_dhcp_pkt(uint8_t vdev_id, struct sk_buff *skb,
2203 			     enum qdf_proto_dir dir, uint8_t pdev_id)
2204 {
2205 	enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
2206 	uint32_t dp_dhcp_trace;
2207 	uint32_t dp_dhcp_event;
2208 
2209 	dp_dhcp_trace = qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_DHCP;
2210 	dp_dhcp_event = qdf_dp_get_proto_event_bitmap() &
2211 				QDF_NBUF_PKT_TRAC_TYPE_DHCP;
2212 
2213 	if (!dp_dhcp_trace && !dp_dhcp_event)
2214 		return false;
2215 
2216 	if (!((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_DHCP ==
2217 	       QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
2218 	      (dir == QDF_RX && qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true)))
2219 		return false;
2220 
2221 	subtype = qdf_nbuf_get_dhcp_subtype(skb);
2222 
2223 	if (dp_dhcp_event && dir == QDF_RX) {
2224 		qdf_dp_log_proto_pkt_info(skb->data + QDF_NBUF_SRC_MAC_OFFSET,
2225 					  skb->data + QDF_NBUF_DEST_MAC_OFFSET,
2226 					  QDF_PROTO_TYPE_DHCP, subtype, dir,
2227 					  QDF_TRACE_DEFAULT_MSDU_ID,
2228 					  QDF_TX_RX_STATUS_INVALID);
2229 		qdf_fill_wlan_connectivity_log(QDF_PROTO_TYPE_DHCP, subtype,
2230 					       QDF_RX, 0, vdev_id, 0);
2231 	}
2232 
2233 	if (dp_dhcp_trace) {
2234 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
2235 		if (QDF_TX == dir)
2236 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
2237 		else if (QDF_RX == dir)
2238 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
2239 
2240 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_DHCP_PACKET_RECORD,
2241 					       vdev_id,
2242 					       skb->data +
2243 					       QDF_NBUF_SRC_MAC_OFFSET,
2244 					       skb->data +
2245 					       QDF_NBUF_DEST_MAC_OFFSET,
2246 					       QDF_PROTO_TYPE_DHCP, subtype,
2247 					       dir, pdev_id, true, 0));
2248 
2249 		switch (subtype) {
2250 		case QDF_PROTO_DHCP_DISCOVER:
2251 			g_qdf_dp_trace_data.dhcp_disc++;
2252 			break;
2253 		case QDF_PROTO_DHCP_OFFER:
2254 			g_qdf_dp_trace_data.dhcp_off++;
2255 			break;
2256 		case QDF_PROTO_DHCP_REQUEST:
2257 			g_qdf_dp_trace_data.dhcp_req++;
2258 			break;
2259 		case QDF_PROTO_DHCP_ACK:
2260 			g_qdf_dp_trace_data.dhcp_ack++;
2261 			break;
2262 		case QDF_PROTO_DHCP_NACK:
2263 			g_qdf_dp_trace_data.dhcp_nack++;
2264 			break;
2265 		default:
2266 			g_qdf_dp_trace_data.eapol_others++;
2267 			break;
2268 		}
2269 	}
2270 
2271 	return true;
2272 }
2273 
2274 /**
2275  * qdf_log_arp_pkt() - log ARP packet
2276  * @vdev_id: ID of the vdev
2277  * @skb: skb pointer
2278  * @dir: direction
2279  * @pdev_id: ID of the pdev
2280  *
2281  * Return: true/false
2282  */
2283 static bool qdf_log_arp_pkt(uint8_t vdev_id, struct sk_buff *skb,
2284 			    enum qdf_proto_dir dir, uint8_t pdev_id)
2285 {
2286 	enum qdf_proto_subtype proto_subtype;
2287 
2288 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ARP) &&
2289 		((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ARP ==
2290 			QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
2291 		 (dir == QDF_RX && qdf_nbuf_is_ipv4_arp_pkt(skb) == true))) {
2292 
2293 		proto_subtype = qdf_nbuf_get_arp_subtype(skb);
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_ARP_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_ARP,
2307 					       proto_subtype, dir, pdev_id,
2308 					       true, 0));
2309 
2310 		if (QDF_PROTO_ARP_REQ == proto_subtype)
2311 			g_qdf_dp_trace_data.arp_req++;
2312 		else
2313 			g_qdf_dp_trace_data.arp_resp++;
2314 
2315 		return true;
2316 	}
2317 	return false;
2318 }
2319 
2320 
2321 bool qdf_dp_trace_log_pkt(uint8_t vdev_id, struct sk_buff *skb,
2322 			  enum qdf_proto_dir dir, uint8_t pdev_id)
2323 {
2324 	if (!qdf_dp_get_proto_bitmap() && !qdf_dp_get_proto_event_bitmap())
2325 		return false;
2326 	if (qdf_log_arp_pkt(vdev_id, skb, dir, pdev_id))
2327 		return true;
2328 	if (qdf_log_dhcp_pkt(vdev_id, skb, dir, pdev_id))
2329 		return true;
2330 	if (qdf_log_eapol_pkt(vdev_id, skb, dir, pdev_id))
2331 		return true;
2332 	if (qdf_log_icmp_pkt(vdev_id, skb, dir, pdev_id))
2333 		return true;
2334 	if (qdf_log_icmpv6_pkt(vdev_id, skb, dir, pdev_id))
2335 		return true;
2336 	return false;
2337 }
2338 qdf_export_symbol(qdf_dp_trace_log_pkt);
2339 
2340 void qdf_dp_display_mgmt_pkt(struct qdf_dp_trace_record_s *record,
2341 			      uint16_t index, uint8_t pdev_id, uint8_t info)
2342 {
2343 	int loc;
2344 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2345 	struct qdf_dp_trace_mgmt_buf *buf =
2346 		(struct qdf_dp_trace_mgmt_buf *)record->data;
2347 
2348 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2349 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2350 					 index, info, record);
2351 
2352 	DPTRACE_PRINT("%s [%d] [%s %s]",
2353 		      prepend_str,
2354 		      buf->vdev_id,
2355 		      qdf_dp_type_to_str(buf->type),
2356 		      qdf_dp_subtype_to_str(buf->subtype));
2357 }
2358 qdf_export_symbol(qdf_dp_display_mgmt_pkt);
2359 
2360 
2361 void qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
2362 		uint8_t pdev_id, enum qdf_proto_type type,
2363 		enum qdf_proto_subtype subtype)
2364 {
2365 	struct qdf_dp_trace_mgmt_buf buf;
2366 	int buf_size = sizeof(struct qdf_dp_trace_mgmt_buf);
2367 
2368 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
2369 		return;
2370 
2371 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2372 		QDF_BUG(0);
2373 
2374 	buf.type = type;
2375 	buf.subtype = subtype;
2376 	buf.vdev_id = vdev_id;
2377 	qdf_dp_add_record(code, pdev_id, (uint8_t *)&buf, buf_size,
2378 			  NULL, 0, true);
2379 }
2380 qdf_export_symbol(qdf_dp_trace_mgmt_pkt);
2381 
2382 static void
2383 qdf_dpt_display_credit_record_debugfs(qdf_debugfs_file_t file,
2384 				      struct qdf_dp_trace_record_s *record,
2385 				      uint32_t index)
2386 {
2387 	int loc;
2388 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2389 	struct qdf_dp_trace_credit_record *buf =
2390 		(struct qdf_dp_trace_credit_record *)record->data;
2391 
2392 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2393 					 index, 0, record);
2394 	if (buf->operation == QDF_OP_NA)
2395 		qdf_debugfs_printf(file, "%s [%s] [T: %d G0: %d G1: %d]\n",
2396 				   prepend_str,
2397 				   qdf_dp_credit_source_to_str(buf->source),
2398 				   buf->total_credits, buf->g0_credit,
2399 				   buf->g1_credit);
2400 	else
2401 		qdf_debugfs_printf(file,
2402 				   "%s [%s] [T: %d G0: %d G1: %d] [%s %d]\n",
2403 				   prepend_str,
2404 				   qdf_dp_credit_source_to_str(buf->source),
2405 				   buf->total_credits, buf->g0_credit,
2406 				   buf->g1_credit,
2407 				   qdf_dp_operation_to_str(buf->operation),
2408 				   buf->delta);
2409 }
2410 
2411 void qdf_dp_display_credit_record(struct qdf_dp_trace_record_s *record,
2412 				  uint16_t index, uint8_t pdev_id, uint8_t info)
2413 {
2414 	int loc;
2415 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2416 	struct qdf_dp_trace_credit_record *buf =
2417 		(struct qdf_dp_trace_credit_record *)record->data;
2418 
2419 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2420 					 index, info, record);
2421 	if (buf->operation == QDF_OP_NA)
2422 		DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d]",
2423 			      prepend_str,
2424 			      qdf_dp_credit_source_to_str(buf->source),
2425 			      buf->total_credits, buf->g0_credit,
2426 			      buf->g1_credit);
2427 	else
2428 		DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d] [%s %d]",
2429 			      prepend_str,
2430 			      qdf_dp_credit_source_to_str(buf->source),
2431 			      buf->total_credits, buf->g0_credit,
2432 			      buf->g1_credit,
2433 			      qdf_dp_operation_to_str(buf->operation),
2434 			      buf->delta);
2435 }
2436 
2437 void qdf_dp_trace_credit_record(enum QDF_CREDIT_UPDATE_SOURCE source,
2438 				enum QDF_CREDIT_OPERATION operation,
2439 				int delta, int total_credits,
2440 				int g0_credit, int g1_credit)
2441 {
2442 	struct qdf_dp_trace_credit_record buf;
2443 	int buf_size = sizeof(struct qdf_dp_trace_credit_record);
2444 	enum QDF_DP_TRACE_ID code = QDF_DP_TRACE_TX_CREDIT_RECORD;
2445 
2446 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
2447 		return;
2448 
2449 	if (!(qdf_dp_get_proto_bitmap() & QDF_HL_CREDIT_TRACKING))
2450 		return;
2451 
2452 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2453 		QDF_BUG(0);
2454 
2455 	buf.source = source;
2456 	buf.operation = operation;
2457 	buf.delta = delta;
2458 	buf.total_credits = total_credits;
2459 	buf.g0_credit = g0_credit;
2460 	buf.g1_credit = g1_credit;
2461 
2462 	qdf_dp_add_record(code, QDF_TRACE_DEFAULT_PDEV_ID, (uint8_t *)&buf,
2463 			  buf_size, NULL, 0, false);
2464 }
2465 qdf_export_symbol(qdf_dp_trace_credit_record);
2466 
2467 void qdf_dp_display_event_record(struct qdf_dp_trace_record_s *record,
2468 			      uint16_t index, uint8_t pdev_id, uint8_t info)
2469 {
2470 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2471 	struct qdf_dp_trace_event_buf *buf =
2472 		(struct qdf_dp_trace_event_buf *)record->data;
2473 
2474 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2475 	qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2476 				   index, info, record);
2477 
2478 	DPTRACE_PRINT("%s [%d] [%s %s]",
2479 		      prepend_str,
2480 		      buf->vdev_id,
2481 		      qdf_dp_type_to_str(buf->type),
2482 		      qdf_dp_subtype_to_str(buf->subtype));
2483 }
2484 qdf_export_symbol(qdf_dp_display_event_record);
2485 
2486 /**
2487  * qdf_dp_trace_record_event() - record events
2488  * @code: dptrace code
2489  * @vdev_id: vdev id
2490  * @pdev_id: pdev_id
2491  * @type: proto type
2492  * @subtype: proto subtype
2493  *
2494  * Return: none
2495  */
2496 void qdf_dp_trace_record_event(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
2497 		uint8_t pdev_id, enum qdf_proto_type type,
2498 		enum qdf_proto_subtype subtype)
2499 {
2500 	struct qdf_dp_trace_event_buf buf;
2501 	int buf_size = sizeof(struct qdf_dp_trace_event_buf);
2502 
2503 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
2504 		return;
2505 
2506 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2507 		QDF_BUG(0);
2508 
2509 	buf.type = type;
2510 	buf.subtype = subtype;
2511 	buf.vdev_id = vdev_id;
2512 	qdf_dp_add_record(code, pdev_id,
2513 			  (uint8_t *)&buf, buf_size, NULL, 0, true);
2514 }
2515 qdf_export_symbol(qdf_dp_trace_record_event);
2516 
2517 
2518 void qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s *record,
2519 			      uint16_t index, uint8_t pdev_id, uint8_t info)
2520 {
2521 	int loc;
2522 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2523 	struct qdf_dp_trace_proto_buf *buf =
2524 		(struct qdf_dp_trace_proto_buf *)record->data;
2525 
2526 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2527 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2528 					 index, info, record);
2529 	DPTRACE_PRINT("%s [%d] [%s] SA: "
2530 		      QDF_MAC_ADDR_FMT " %s DA:"
2531 		      QDF_MAC_ADDR_FMT " proto priv data = %08x",
2532 		      prepend_str,
2533 		      buf->vdev_id,
2534 		      qdf_dp_subtype_to_str(buf->subtype),
2535 		      QDF_MAC_ADDR_REF(buf->sa.bytes),
2536 		      qdf_dp_dir_to_str(buf->dir),
2537 		      QDF_MAC_ADDR_REF(buf->da.bytes),
2538 		      buf->proto_priv_data);
2539 }
2540 qdf_export_symbol(qdf_dp_display_proto_pkt);
2541 
2542 void qdf_dp_trace_proto_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
2543 		uint8_t *sa, uint8_t *da, enum qdf_proto_type type,
2544 		enum qdf_proto_subtype subtype, enum qdf_proto_dir dir,
2545 		uint8_t pdev_id, bool print, uint32_t proto_priv_data)
2546 {
2547 	struct qdf_dp_trace_proto_buf buf;
2548 	int buf_size = sizeof(struct qdf_dp_trace_proto_buf);
2549 
2550 	if (qdf_dp_enable_check(NULL, code, dir) == false)
2551 		return;
2552 
2553 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2554 		QDF_BUG(0);
2555 
2556 	memcpy(&buf.sa, sa, QDF_NET_ETH_LEN);
2557 	memcpy(&buf.da, da, QDF_NET_ETH_LEN);
2558 	buf.dir = dir;
2559 	buf.type = type;
2560 	buf.subtype = subtype;
2561 	buf.vdev_id = vdev_id;
2562 	buf.proto_priv_data = proto_priv_data;
2563 	qdf_dp_add_record(code, pdev_id,
2564 			  (uint8_t *)&buf, buf_size, NULL, 0, print);
2565 }
2566 qdf_export_symbol(qdf_dp_trace_proto_pkt);
2567 
2568 void qdf_dp_display_ptr_record(struct qdf_dp_trace_record_s *record,
2569 				uint16_t index, uint8_t pdev_id, uint8_t info)
2570 {
2571 	int loc;
2572 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2573 	struct qdf_dp_trace_ptr_buf *buf =
2574 		(struct qdf_dp_trace_ptr_buf *)record->data;
2575 	bool is_free_pkt_ptr_record = false;
2576 
2577 	if ((record->code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) ||
2578 	    (record->code == QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD))
2579 		is_free_pkt_ptr_record = true;
2580 
2581 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2582 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2583 					 index, info, record);
2584 
2585 	if (loc < sizeof(prepend_str))
2586 		scnprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2587 			  "[msdu id %d %s %d]",
2588 			  buf->msdu_id,
2589 			  is_free_pkt_ptr_record ? "status" : "vdev_id",
2590 			  buf->status);
2591 
2592 	if (info & QDF_DP_TRACE_RECORD_INFO_LIVE) {
2593 		/* In live mode donot dump the contents of the cookie */
2594 		DPTRACE_PRINT("%s", prepend_str);
2595 	} else {
2596 		dump_dp_hex_trace(prepend_str, (uint8_t *)&buf->cookie,
2597 			sizeof(buf->cookie));
2598 	}
2599 }
2600 qdf_export_symbol(qdf_dp_display_ptr_record);
2601 
2602 static
2603 enum qdf_proto_type qdf_dp_get_pkt_proto_type(qdf_nbuf_t nbuf)
2604 {
2605 	uint8_t pkt_type;
2606 
2607 	if (!nbuf)
2608 		return QDF_PROTO_TYPE_MAX;
2609 
2610 	if (qdf_nbuf_data_is_dns_query(nbuf) ||
2611 	    qdf_nbuf_data_is_dns_response(nbuf))
2612 		return QDF_PROTO_TYPE_DNS;
2613 
2614 	pkt_type = QDF_NBUF_CB_GET_PACKET_TYPE(nbuf);
2615 
2616 	switch (pkt_type) {
2617 	case QDF_NBUF_CB_PACKET_TYPE_EAPOL:
2618 		return QDF_PROTO_TYPE_EAPOL;
2619 	case QDF_NBUF_CB_PACKET_TYPE_ARP:
2620 		return QDF_PROTO_TYPE_ARP;
2621 	case QDF_NBUF_CB_PACKET_TYPE_DHCP:
2622 		return QDF_PROTO_TYPE_DHCP;
2623 	default:
2624 		return QDF_PROTO_TYPE_MAX;
2625 	}
2626 }
2627 
2628 static
2629 enum qdf_proto_subtype qdf_dp_get_pkt_subtype(qdf_nbuf_t nbuf,
2630 					      enum qdf_proto_type pkt_type)
2631 {
2632 	switch (pkt_type) {
2633 	case QDF_PROTO_TYPE_EAPOL:
2634 		return qdf_nbuf_get_eapol_subtype(nbuf);
2635 	case QDF_PROTO_TYPE_ARP:
2636 		return qdf_nbuf_get_arp_subtype(nbuf);
2637 	case QDF_PROTO_TYPE_DHCP:
2638 		return qdf_nbuf_get_dhcp_subtype(nbuf);
2639 	case QDF_PROTO_TYPE_DNS:
2640 		return (qdf_nbuf_data_is_dns_query(nbuf)) ?
2641 				QDF_PROTO_DNS_QUERY : QDF_PROTO_DNS_RES;
2642 	default:
2643 		return QDF_PROTO_INVALID;
2644 	}
2645 }
2646 
2647 static
2648 bool qdf_dp_proto_log_enable_check(enum qdf_proto_type pkt_type,
2649 				   uint16_t status)
2650 {
2651 	if (pkt_type == QDF_PROTO_TYPE_MAX)
2652 		return false;
2653 
2654 	switch (pkt_type) {
2655 	case QDF_PROTO_TYPE_EAPOL:
2656 		return qdf_dp_get_proto_event_bitmap() &
2657 				QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
2658 	case QDF_PROTO_TYPE_DHCP:
2659 		return qdf_dp_get_proto_event_bitmap() &
2660 				QDF_NBUF_PKT_TRAC_TYPE_DHCP;
2661 	case QDF_PROTO_TYPE_ARP:
2662 		if (status == QDF_TX_RX_STATUS_OK)
2663 			return false;
2664 		else
2665 			return qdf_dp_get_proto_event_bitmap() &
2666 					QDF_NBUF_PKT_TRAC_TYPE_ARP;
2667 	case QDF_PROTO_TYPE_DNS:
2668 		if (status == QDF_TX_RX_STATUS_OK)
2669 			return false;
2670 		else
2671 			return qdf_dp_get_proto_event_bitmap() &
2672 					QDF_NBUF_PKT_TRAC_TYPE_DNS;
2673 	default:
2674 		return false;
2675 	}
2676 }
2677 
2678 void qdf_dp_track_noack_check(qdf_nbuf_t nbuf, enum qdf_proto_subtype *subtype)
2679 {
2680 	enum qdf_proto_type pkt_type = qdf_dp_get_pkt_proto_type(nbuf);
2681 	uint16_t dp_track = 0;
2682 
2683 	switch (pkt_type) {
2684 	case QDF_PROTO_TYPE_EAPOL:
2685 		dp_track = qdf_dp_get_proto_bitmap() &
2686 				QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
2687 		break;
2688 	case QDF_PROTO_TYPE_DHCP:
2689 		dp_track = qdf_dp_get_proto_bitmap() &
2690 				QDF_NBUF_PKT_TRAC_TYPE_DHCP;
2691 		break;
2692 	case QDF_PROTO_TYPE_ARP:
2693 		dp_track = qdf_dp_get_proto_bitmap() &
2694 					QDF_NBUF_PKT_TRAC_TYPE_ARP;
2695 		break;
2696 	case QDF_PROTO_TYPE_DNS:
2697 		dp_track = qdf_dp_get_proto_bitmap() &
2698 					QDF_NBUF_PKT_TRAC_TYPE_DNS;
2699 		break;
2700 	default:
2701 		break;
2702 	}
2703 
2704 	if (!dp_track) {
2705 		*subtype = QDF_PROTO_INVALID;
2706 		return;
2707 	}
2708 
2709 	*subtype = qdf_dp_get_pkt_subtype(nbuf, pkt_type);
2710 }
2711 qdf_export_symbol(qdf_dp_track_noack_check);
2712 
2713 enum qdf_dp_tx_rx_status qdf_dp_get_status_from_a_status(uint8_t status)
2714 {
2715 	if (status == QDF_A_STATUS_ERROR)
2716 		return QDF_TX_RX_STATUS_INVALID;
2717 	else if (status == QDF_A_STATUS_OK)
2718 		return QDF_TX_RX_STATUS_OK;
2719 	else
2720 		return QDF_TX_RX_STATUS_MAX;
2721 }
2722 qdf_export_symbol(qdf_dp_get_status_from_a_status);
2723 
2724 void qdf_dp_trace_ptr(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
2725 		uint8_t pdev_id, uint8_t *data, uint8_t size,
2726 		uint16_t msdu_id, uint16_t buf_arg_status,
2727 		enum qdf_dp_tx_rx_status qdf_tx_status)
2728 {
2729 	struct qdf_dp_trace_ptr_buf buf;
2730 	int buf_size = sizeof(struct qdf_dp_trace_ptr_buf);
2731 	enum qdf_proto_type pkt_type;
2732 	enum qdf_proto_subtype subtype;
2733 
2734 	pkt_type = qdf_dp_get_pkt_proto_type(nbuf);
2735 	if ((code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD ||
2736 	     code == QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD) &&
2737 	    qdf_dp_proto_log_enable_check(pkt_type, qdf_tx_status)) {
2738 		subtype = qdf_dp_get_pkt_subtype(nbuf, pkt_type);
2739 		qdf_dp_log_proto_pkt_info(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET,
2740 					 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET,
2741 					 pkt_type, subtype,
2742 					 QDF_TX, msdu_id, qdf_tx_status);
2743 		qdf_fill_wlan_connectivity_log(pkt_type, subtype,
2744 					       QDF_TX, qdf_tx_status,
2745 					       QDF_NBUF_CB_TX_VDEV_CTX(nbuf),
2746 					       nbuf->data);
2747 	}
2748 
2749 	if (qdf_dp_enable_check(nbuf, code, QDF_TX) == false)
2750 		return;
2751 
2752 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2753 		QDF_BUG(0);
2754 
2755 	qdf_mem_copy(&buf.cookie, data, size);
2756 	buf.msdu_id = msdu_id;
2757 	buf.status = buf_arg_status;
2758 	qdf_dp_add_record(code, pdev_id, (uint8_t *)&buf, buf_size, NULL, 0,
2759 			  QDF_NBUF_CB_DP_TRACE_PRINT(nbuf));
2760 }
2761 qdf_export_symbol(qdf_dp_trace_ptr);
2762 
2763 void qdf_dp_trace_data_pkt(qdf_nbuf_t nbuf, uint8_t pdev_id,
2764 			   enum QDF_DP_TRACE_ID code, uint16_t msdu_id,
2765 			   enum qdf_proto_dir dir)
2766 {
2767 	struct qdf_dp_trace_data_buf buf;
2768 	enum qdf_proto_type pkt_type;
2769 
2770 	pkt_type = qdf_dp_get_pkt_proto_type(nbuf);
2771 	if (code == QDF_DP_TRACE_DROP_PACKET_RECORD &&
2772 	    qdf_dp_proto_log_enable_check(pkt_type, QDF_TX_RX_STATUS_DROP))
2773 		qdf_dp_log_proto_pkt_info(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET,
2774 					 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET,
2775 					 pkt_type,
2776 					 qdf_dp_get_pkt_subtype(nbuf, pkt_type),
2777 					 QDF_TX, msdu_id,
2778 					 QDF_TX_RX_STATUS_DROP);
2779 
2780 	buf.msdu_id = msdu_id;
2781 	if (!qdf_dp_enable_check(nbuf, code, dir))
2782 		return;
2783 
2784 	qdf_dp_add_record(code, pdev_id,
2785 			  nbuf ? qdf_nbuf_data(nbuf) : NULL,
2786 			  nbuf ? nbuf->len - nbuf->data_len : 0,
2787 			  (uint8_t *)&buf, sizeof(struct qdf_dp_trace_data_buf),
2788 			  (nbuf) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false);
2789 }
2790 
2791 qdf_export_symbol(qdf_dp_trace_data_pkt);
2792 
2793 void qdf_dp_display_record(struct qdf_dp_trace_record_s *record,
2794 			   uint16_t index, uint8_t pdev_id, uint8_t info)
2795 {
2796 	int loc;
2797 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2798 
2799 	if (!(pdev_id == QDF_TRACE_DEFAULT_PDEV_ID ||
2800 		pdev_id == record->pdev_id))
2801 		return;
2802 
2803 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2804 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2805 					 index, info, record);
2806 
2807 	switch (record->code) {
2808 	case  QDF_DP_TRACE_HDD_TX_TIMEOUT:
2809 		DPTRACE_PRINT(" %s: HDD TX Timeout", prepend_str);
2810 		break;
2811 	case  QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
2812 		DPTRACE_PRINT(" %s: HDD SoftAP TX Timeout", prepend_str);
2813 		break;
2814 	case  QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
2815 		DPTRACE_PRINT(" %s: CE Fast Packet Error", prepend_str);
2816 		break;
2817 	case QDF_DP_TRACE_LI_DP_NULL_RX_PACKET_RECORD:
2818 	default:
2819 		dump_dp_hex_trace(prepend_str, record->data, record->size);
2820 		break;
2821 	};
2822 }
2823 qdf_export_symbol(qdf_dp_display_record);
2824 
2825 void
2826 qdf_dp_display_data_pkt_record(struct qdf_dp_trace_record_s *record,
2827 			       uint16_t rec_index, uint8_t pdev_id,
2828 			       uint8_t info)
2829 {
2830 	int loc;
2831 	char prepend_str[DP_TRACE_META_DATA_STRLEN + 10];
2832 	struct qdf_dp_trace_data_buf *buf =
2833 		(struct qdf_dp_trace_data_buf *)record->data;
2834 
2835 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2836 
2837 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2838 					 rec_index, info, record);
2839 	if (loc < sizeof(prepend_str))
2840 		loc += snprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2841 				"[%d]", buf->msdu_id);
2842 	dump_dp_hex_trace(prepend_str,
2843 			  &record->data[sizeof(struct qdf_dp_trace_data_buf)],
2844 			  record->size);
2845 }
2846 
2847 /**
2848  * qdf_dp_trace() - Stores the data in buffer
2849  * @nbuf  : defines the netbuf
2850  * @code : defines the event
2851  * @pdev_id: pdev_id
2852  * @data : defines the data to be stored
2853  * @size : defines the size of the data record
2854  *
2855  * Return: None
2856  */
2857 void qdf_dp_trace(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code, uint8_t pdev_id,
2858 	uint8_t *data, uint8_t size, enum qdf_proto_dir dir)
2859 {
2860 
2861 	if (qdf_dp_enable_check(nbuf, code, dir) == false)
2862 		return;
2863 
2864 	qdf_dp_add_record(code, pdev_id, nbuf ? qdf_nbuf_data(nbuf) : NULL,
2865 			  size, NULL, 0,
2866 			  (nbuf) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false);
2867 }
2868 qdf_export_symbol(qdf_dp_trace);
2869 
2870 /**
2871  * qdf_dp_trace_spin_lock_init() - initializes the lock variable before use
2872  * This function will be called from cds_alloc_global_context, we will have lock
2873  * available to use ASAP
2874  *
2875  * Return: None
2876  */
2877 void qdf_dp_trace_spin_lock_init(void)
2878 {
2879 	spin_lock_init(&l_dp_trace_lock);
2880 }
2881 qdf_export_symbol(qdf_dp_trace_spin_lock_init);
2882 
2883 /**
2884  * qdf_dp_trace_disable_live_mode - disable live mode for dptrace
2885  *
2886  * Return: none
2887  */
2888 void qdf_dp_trace_disable_live_mode(void)
2889 {
2890 	g_qdf_dp_trace_data.force_live_mode = 0;
2891 }
2892 qdf_export_symbol(qdf_dp_trace_disable_live_mode);
2893 
2894 /**
2895  * qdf_dp_trace_enable_live_mode() - enable live mode for dptrace
2896  *
2897  * Return: none
2898  */
2899 void qdf_dp_trace_enable_live_mode(void)
2900 {
2901 	g_qdf_dp_trace_data.force_live_mode = 1;
2902 }
2903 qdf_export_symbol(qdf_dp_trace_enable_live_mode);
2904 
2905 /**
2906  * qdf_dp_trace_clear_buffer() - clear dp trace buffer
2907  *
2908  * Return: none
2909  */
2910 void qdf_dp_trace_clear_buffer(void)
2911 {
2912 	g_qdf_dp_trace_data.head = INVALID_QDF_DP_TRACE_ADDR;
2913 	g_qdf_dp_trace_data.tail = INVALID_QDF_DP_TRACE_ADDR;
2914 	g_qdf_dp_trace_data.num = 0;
2915 	g_qdf_dp_trace_data.dump_counter = 0;
2916 	g_qdf_dp_trace_data.num_records_to_dump = MAX_QDF_DP_TRACE_RECORDS;
2917 	if (g_qdf_dp_trace_data.enable)
2918 		memset(g_qdf_dp_trace_tbl, 0,
2919 		       MAX_QDF_DP_TRACE_RECORDS *
2920 		       sizeof(struct qdf_dp_trace_record_s));
2921 }
2922 qdf_export_symbol(qdf_dp_trace_clear_buffer);
2923 
2924 void qdf_dp_trace_dump_stats(void)
2925 {
2926 		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)",
2927 			      g_qdf_dp_trace_data.tx_count,
2928 			      g_qdf_dp_trace_data.rx_count,
2929 			      g_qdf_dp_trace_data.icmp_req,
2930 			      g_qdf_dp_trace_data.icmp_resp,
2931 			      g_qdf_dp_trace_data.arp_req,
2932 			      g_qdf_dp_trace_data.arp_resp,
2933 			      g_qdf_dp_trace_data.icmpv6_req,
2934 			      g_qdf_dp_trace_data.icmpv6_resp,
2935 			      g_qdf_dp_trace_data.icmpv6_ns,
2936 			      g_qdf_dp_trace_data.icmpv6_na,
2937 			      g_qdf_dp_trace_data.icmpv6_rs,
2938 			      g_qdf_dp_trace_data.icmpv6_ra,
2939 			      g_qdf_dp_trace_data.dhcp_disc,
2940 			      g_qdf_dp_trace_data.dhcp_off,
2941 			      g_qdf_dp_trace_data.dhcp_req,
2942 			      g_qdf_dp_trace_data.dhcp_ack,
2943 			      g_qdf_dp_trace_data.dhcp_nack,
2944 			      g_qdf_dp_trace_data.dhcp_others,
2945 			      g_qdf_dp_trace_data.eapol_m1,
2946 			      g_qdf_dp_trace_data.eapol_m2,
2947 			      g_qdf_dp_trace_data.eapol_m3,
2948 			      g_qdf_dp_trace_data.eapol_m4,
2949 			      g_qdf_dp_trace_data.eapol_others);
2950 }
2951 qdf_export_symbol(qdf_dp_trace_dump_stats);
2952 
2953 /**
2954  * qdf_dpt_dump_hex_trace_debugfs() - read data in file
2955  * @file: file to read
2956  * @str: string to prepend the hexdump with.
2957  * @buf: buffer which contains data to be written
2958  * @buf_len: defines the size of the data to be written
2959  *
2960  * Return: None
2961  */
2962 static void qdf_dpt_dump_hex_trace_debugfs(qdf_debugfs_file_t file,
2963 				char *str, uint8_t *buf, uint8_t buf_len)
2964 {
2965 	unsigned char linebuf[BUFFER_SIZE];
2966 	const u8 *ptr = buf;
2967 	int i, linelen, remaining = buf_len;
2968 
2969 	/* Dump the bytes in the last line */
2970 	for (i = 0; i < buf_len; i += ROW_SIZE) {
2971 		linelen = min(remaining, ROW_SIZE);
2972 		remaining -= ROW_SIZE;
2973 
2974 		hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1,
2975 				linebuf, sizeof(linebuf), false);
2976 
2977 		qdf_debugfs_printf(file, "%s %s\n", str, linebuf);
2978 	}
2979 }
2980 
2981 /**
2982  * qdf_dpt_display_proto_pkt_debugfs() - display proto packet
2983  * @file: file to read
2984  * @record: dptrace record
2985  * @index: index
2986  *
2987  * Return: none
2988  */
2989 static void qdf_dpt_display_proto_pkt_debugfs(qdf_debugfs_file_t file,
2990 				struct qdf_dp_trace_record_s *record,
2991 				uint32_t index)
2992 {
2993 	int loc;
2994 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2995 	struct qdf_dp_trace_proto_buf *buf =
2996 		(struct qdf_dp_trace_proto_buf *)record->data;
2997 
2998 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2999 					 index, 0, record);
3000 	qdf_debugfs_printf(file, "%s [%d] [%s] SA: "
3001 			   QDF_MAC_ADDR_FMT " %s DA: "
3002 			   QDF_MAC_ADDR_FMT,
3003 			   prepend_str,
3004 			   buf->vdev_id,
3005 			   qdf_dp_subtype_to_str(buf->subtype),
3006 			   QDF_MAC_ADDR_REF(buf->sa.bytes),
3007 			   qdf_dp_dir_to_str(buf->dir),
3008 			   QDF_MAC_ADDR_REF(buf->da.bytes));
3009 	qdf_debugfs_printf(file, "\n");
3010 }
3011 
3012 /**
3013  * qdf_dpt_display_mgmt_pkt_debugfs() - display mgmt packet
3014  * @file: file to read
3015  * @record: dptrace record
3016  * @index: index
3017  *
3018  * Return: none
3019  */
3020 static void qdf_dpt_display_mgmt_pkt_debugfs(qdf_debugfs_file_t file,
3021 				struct qdf_dp_trace_record_s *record,
3022 				uint32_t index)
3023 {
3024 
3025 	int loc;
3026 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
3027 	struct qdf_dp_trace_mgmt_buf *buf =
3028 		(struct qdf_dp_trace_mgmt_buf *)record->data;
3029 
3030 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
3031 					 index, 0, record);
3032 
3033 	qdf_debugfs_printf(file, "%s [%d] [%s %s]\n",
3034 			   prepend_str,
3035 			   buf->vdev_id,
3036 			   qdf_dp_type_to_str(buf->type),
3037 			   qdf_dp_subtype_to_str(buf->subtype));
3038 }
3039 
3040 /**
3041  * qdf_dpt_display_event_record_debugfs() - display event records
3042  * @file: file to read
3043  * @record: dptrace record
3044  * @index: index
3045  *
3046  * Return: none
3047  */
3048 static void qdf_dpt_display_event_record_debugfs(qdf_debugfs_file_t file,
3049 				struct qdf_dp_trace_record_s *record,
3050 				uint32_t index)
3051 {
3052 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
3053 	struct qdf_dp_trace_event_buf *buf =
3054 		(struct qdf_dp_trace_event_buf *)record->data;
3055 
3056 	qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
3057 				   index, 0, record);
3058 	qdf_debugfs_printf(file, "%s [%d] [%s %s]\n",
3059 			   prepend_str,
3060 			   buf->vdev_id,
3061 			   qdf_dp_type_to_str(buf->type),
3062 			   qdf_dp_subtype_to_str(buf->subtype));
3063 }
3064 
3065 /**
3066  * qdf_dpt_display_ptr_record_debugfs() - display record ptr
3067  * @file: file to read
3068  * @record: dptrace record
3069  * @index: index
3070  *
3071  * Return: none
3072  */
3073 static void qdf_dpt_display_ptr_record_debugfs(qdf_debugfs_file_t file,
3074 				struct qdf_dp_trace_record_s *record,
3075 				uint32_t index)
3076 {
3077 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
3078 	int loc;
3079 	struct qdf_dp_trace_ptr_buf *buf =
3080 		(struct qdf_dp_trace_ptr_buf *)record->data;
3081 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
3082 					 index, 0, record);
3083 
3084 	if (loc < sizeof(prepend_str))
3085 		scnprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
3086 			  "[msdu id %d %s %d]",
3087 			  buf->msdu_id,
3088 			  (record->code ==
3089 				QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) ?
3090 			  "status" : "vdev_id",
3091 			  buf->status);
3092 
3093 	qdf_dpt_dump_hex_trace_debugfs(file, prepend_str,
3094 				       (uint8_t *)&buf->cookie,
3095 				       sizeof(buf->cookie));
3096 }
3097 
3098 /**
3099  * qdf_dpt_display_ptr_record_debugfs() - display record
3100  * @file: file to read
3101  * @record: dptrace record
3102  * @index: index
3103  *
3104  * Return: none
3105  */
3106 static void qdf_dpt_display_record_debugfs(qdf_debugfs_file_t file,
3107 				struct qdf_dp_trace_record_s *record,
3108 				uint32_t index)
3109 {
3110 	int loc;
3111 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
3112 	struct qdf_dp_trace_data_buf *buf =
3113 		(struct qdf_dp_trace_data_buf *)record->data;
3114 
3115 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
3116 					 index, 0, record);
3117 	if (loc < sizeof(prepend_str))
3118 		loc += snprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
3119 				"[%d]", buf->msdu_id);
3120 	qdf_dpt_dump_hex_trace_debugfs(file, prepend_str,
3121 				       record->data, record->size);
3122 }
3123 
3124 uint32_t qdf_dpt_get_curr_pos_debugfs(qdf_debugfs_file_t file,
3125 				      enum qdf_dpt_debugfs_state state)
3126 {
3127 	uint32_t i = 0;
3128 	uint32_t tail;
3129 	uint32_t count = g_qdf_dp_trace_data.num;
3130 
3131 	if (!g_qdf_dp_trace_data.enable) {
3132 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
3133 		  "%s: Tracing Disabled", __func__);
3134 		return QDF_STATUS_E_EMPTY;
3135 	}
3136 
3137 	if (!count) {
3138 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
3139 		  "%s: no packets", __func__);
3140 		return QDF_STATUS_E_EMPTY;
3141 	}
3142 
3143 	if (state == QDF_DPT_DEBUGFS_STATE_SHOW_IN_PROGRESS)
3144 		return g_qdf_dp_trace_data.curr_pos;
3145 
3146 	qdf_debugfs_printf(file,
3147 		"DPT: config - bitmap 0x%x verb %u #rec %u rec_requested %u live_config %u thresh %u time_limit %u\n",
3148 		g_qdf_dp_trace_data.proto_bitmap,
3149 		g_qdf_dp_trace_data.verbosity,
3150 		g_qdf_dp_trace_data.no_of_record,
3151 		g_qdf_dp_trace_data.num_records_to_dump,
3152 		g_qdf_dp_trace_data.live_mode_config,
3153 		g_qdf_dp_trace_data.high_tput_thresh,
3154 		g_qdf_dp_trace_data.thresh_time_limit);
3155 
3156 	qdf_debugfs_printf(file,
3157 		"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",
3158 		g_qdf_dp_trace_data.icmp_req,
3159 		g_qdf_dp_trace_data.icmp_resp,
3160 		g_qdf_dp_trace_data.arp_req,
3161 		g_qdf_dp_trace_data.arp_resp,
3162 		g_qdf_dp_trace_data.icmpv6_req,
3163 		g_qdf_dp_trace_data.icmpv6_resp,
3164 		g_qdf_dp_trace_data.icmpv6_ns,
3165 		g_qdf_dp_trace_data.icmpv6_na,
3166 		g_qdf_dp_trace_data.icmpv6_rs,
3167 		g_qdf_dp_trace_data.icmpv6_ra,
3168 		g_qdf_dp_trace_data.dhcp_disc,
3169 		g_qdf_dp_trace_data.dhcp_off,
3170 		g_qdf_dp_trace_data.dhcp_req,
3171 		g_qdf_dp_trace_data.dhcp_ack,
3172 		g_qdf_dp_trace_data.dhcp_nack,
3173 		g_qdf_dp_trace_data.dhcp_others,
3174 		g_qdf_dp_trace_data.eapol_m1,
3175 		g_qdf_dp_trace_data.eapol_m2,
3176 		g_qdf_dp_trace_data.eapol_m3,
3177 		g_qdf_dp_trace_data.eapol_m4,
3178 		g_qdf_dp_trace_data.eapol_others);
3179 
3180 	qdf_debugfs_printf(file,
3181 		"DPT: Total Records: %d, Head: %d, Tail: %d\n",
3182 		g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head,
3183 		g_qdf_dp_trace_data.tail);
3184 
3185 	spin_lock_bh(&l_dp_trace_lock);
3186 	if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) {
3187 		i = g_qdf_dp_trace_data.head;
3188 		tail = g_qdf_dp_trace_data.tail;
3189 
3190 		if (count > g_qdf_dp_trace_data.num)
3191 			count = g_qdf_dp_trace_data.num;
3192 
3193 		if (tail >= (count - 1))
3194 			i = tail - count + 1;
3195 		else if (count != MAX_QDF_DP_TRACE_RECORDS)
3196 			i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) -
3197 						     tail);
3198 		g_qdf_dp_trace_data.curr_pos = 0;
3199 		g_qdf_dp_trace_data.saved_tail = tail;
3200 	}
3201 	spin_unlock_bh(&l_dp_trace_lock);
3202 
3203 	return g_qdf_dp_trace_data.saved_tail;
3204 }
3205 qdf_export_symbol(qdf_dpt_get_curr_pos_debugfs);
3206 
3207 QDF_STATUS qdf_dpt_dump_stats_debugfs(qdf_debugfs_file_t file,
3208 				      uint32_t curr_pos)
3209 {
3210 	struct qdf_dp_trace_record_s p_record;
3211 	uint32_t i = curr_pos;
3212 	uint16_t num_records_to_dump = g_qdf_dp_trace_data.num_records_to_dump;
3213 
3214 	if (!g_qdf_dp_trace_data.enable) {
3215 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
3216 			  "%s: Tracing Disabled", __func__);
3217 		return QDF_STATUS_E_FAILURE;
3218 	}
3219 
3220 	if (num_records_to_dump > g_qdf_dp_trace_data.num)
3221 		num_records_to_dump = g_qdf_dp_trace_data.num;
3222 
3223 	/*
3224 	 * Max dp trace record size should always be less than
3225 	 * QDF_DP_TRACE_PREPEND_STR_SIZE(100) + BUFFER_SIZE(121).
3226 	 */
3227 	if (WARN_ON(QDF_DP_TRACE_MAX_RECORD_SIZE <
3228 				QDF_DP_TRACE_PREPEND_STR_SIZE + BUFFER_SIZE))
3229 		return QDF_STATUS_E_FAILURE;
3230 
3231 	spin_lock_bh(&l_dp_trace_lock);
3232 	p_record = g_qdf_dp_trace_tbl[i];
3233 	spin_unlock_bh(&l_dp_trace_lock);
3234 
3235 	for (;; ) {
3236 		/*
3237 		 * Initially we get file as 1 page size, and
3238 		 * if remaining size in file is less than one record max size,
3239 		 * then return so that it gets an extra page.
3240 		 */
3241 		if ((file->size - file->count) < QDF_DP_TRACE_MAX_RECORD_SIZE) {
3242 			spin_lock_bh(&l_dp_trace_lock);
3243 			g_qdf_dp_trace_data.curr_pos = i;
3244 			spin_unlock_bh(&l_dp_trace_lock);
3245 			return QDF_STATUS_E_FAILURE;
3246 		}
3247 
3248 		switch (p_record.code) {
3249 		case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD:
3250 		case QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD:
3251 		case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD:
3252 			qdf_dpt_display_ptr_record_debugfs(file, &p_record, i);
3253 			break;
3254 
3255 		case QDF_DP_TRACE_EAPOL_PACKET_RECORD:
3256 		case QDF_DP_TRACE_DHCP_PACKET_RECORD:
3257 		case QDF_DP_TRACE_ARP_PACKET_RECORD:
3258 		case QDF_DP_TRACE_ICMP_PACKET_RECORD:
3259 		case QDF_DP_TRACE_ICMPv6_PACKET_RECORD:
3260 			qdf_dpt_display_proto_pkt_debugfs(file, &p_record, i);
3261 			break;
3262 
3263 		case QDF_DP_TRACE_TX_CREDIT_RECORD:
3264 			qdf_dpt_display_credit_record_debugfs(file, &p_record,
3265 							      i);
3266 			break;
3267 
3268 		case QDF_DP_TRACE_MGMT_PACKET_RECORD:
3269 			qdf_dpt_display_mgmt_pkt_debugfs(file, &p_record, i);
3270 			break;
3271 
3272 		case QDF_DP_TRACE_EVENT_RECORD:
3273 			qdf_dpt_display_event_record_debugfs(file, &p_record,
3274 							     i);
3275 			break;
3276 
3277 		case QDF_DP_TRACE_HDD_TX_TIMEOUT:
3278 			qdf_debugfs_printf(
3279 					file, "DPT: %04d: %llu %s\n",
3280 					i, p_record.time,
3281 					qdf_dp_code_to_string(p_record.code));
3282 			qdf_debugfs_printf(file, "HDD TX Timeout\n");
3283 			break;
3284 
3285 		case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
3286 			qdf_debugfs_printf(
3287 					file, "DPT: %04d: %llu %s\n",
3288 					i, p_record.time,
3289 					qdf_dp_code_to_string(p_record.code));
3290 			qdf_debugfs_printf(file, "HDD SoftAP TX Timeout\n");
3291 			break;
3292 
3293 		case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
3294 			qdf_debugfs_printf(
3295 					file, "DPT: %04d: %llu %s\n",
3296 					i, p_record.time,
3297 					qdf_dp_code_to_string(p_record.code));
3298 			qdf_debugfs_printf(file, "CE Fast Packet Error\n");
3299 			break;
3300 
3301 		case QDF_DP_TRACE_MAX:
3302 			qdf_debugfs_printf(file,
3303 				"%s: QDF_DP_TRACE_MAX event should not be generated\n",
3304 				__func__);
3305 			break;
3306 
3307 		case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
3308 		case QDF_DP_TRACE_HDD_RX_PACKET_RECORD:
3309 		case QDF_DP_TRACE_TX_PACKET_RECORD:
3310 		case QDF_DP_TRACE_RX_PACKET_RECORD:
3311 		case QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD:
3312 		case QDF_DP_TRACE_LI_DP_RX_PACKET_RECORD:
3313 
3314 		default:
3315 			qdf_dpt_display_record_debugfs(file, &p_record, i);
3316 			break;
3317 		}
3318 
3319 		if (++g_qdf_dp_trace_data.dump_counter == num_records_to_dump)
3320 			break;
3321 
3322 		spin_lock_bh(&l_dp_trace_lock);
3323 		if (i == 0)
3324 			i = MAX_QDF_DP_TRACE_RECORDS;
3325 
3326 		i -= 1;
3327 		p_record = g_qdf_dp_trace_tbl[i];
3328 		spin_unlock_bh(&l_dp_trace_lock);
3329 	}
3330 
3331 	g_qdf_dp_trace_data.dump_counter = 0;
3332 
3333 	return QDF_STATUS_SUCCESS;
3334 }
3335 qdf_export_symbol(qdf_dpt_dump_stats_debugfs);
3336 
3337 /**
3338  * qdf_dpt_set_value_debugfs() - Configure the value to control DP trace
3339  * @proto_bitmap: defines the protocol to be tracked
3340  * @no_of_records: defines the nth packet which is traced
3341  * @verbosity: defines the verbosity level
3342  *
3343  * Return: None
3344  */
3345 void qdf_dpt_set_value_debugfs(uint8_t proto_bitmap, uint8_t no_of_record,
3346 			    uint8_t verbosity, uint16_t num_records_to_dump)
3347 {
3348 	if (g_qdf_dp_trace_data.enable) {
3349 		g_qdf_dp_trace_data.proto_bitmap = proto_bitmap;
3350 		g_qdf_dp_trace_data.no_of_record = no_of_record;
3351 		g_qdf_dp_trace_data.verbosity    = verbosity;
3352 		g_qdf_dp_trace_data.num_records_to_dump = num_records_to_dump;
3353 	}
3354 }
3355 qdf_export_symbol(qdf_dpt_set_value_debugfs);
3356 
3357 
3358 /**
3359  * qdf_dp_trace_dump_all() - Dump data from ring buffer via call back functions
3360  * registered with QDF
3361  * @count: Number of lines to dump starting from tail to head
3362  * @pdev_id: pdev_id
3363  *
3364  * Return: None
3365  */
3366 void qdf_dp_trace_dump_all(uint32_t count, uint8_t pdev_id)
3367 {
3368 	struct qdf_dp_trace_record_s p_record;
3369 	int32_t i, tail;
3370 
3371 	if (!g_qdf_dp_trace_data.enable) {
3372 		DPTRACE_PRINT("Tracing Disabled");
3373 		return;
3374 	}
3375 
3376 	DPTRACE_PRINT(
3377 		"DPT: config - bitmap 0x%x verb %u #rec %u live_config %u thresh %u time_limit %u",
3378 		g_qdf_dp_trace_data.proto_bitmap,
3379 		g_qdf_dp_trace_data.verbosity,
3380 		g_qdf_dp_trace_data.no_of_record,
3381 		g_qdf_dp_trace_data.live_mode_config,
3382 		g_qdf_dp_trace_data.high_tput_thresh,
3383 		g_qdf_dp_trace_data.thresh_time_limit);
3384 
3385 	qdf_dp_trace_dump_stats();
3386 
3387 	DPTRACE_PRINT("DPT: Total Records: %d, Head: %d, Tail: %d",
3388 		      g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head,
3389 		      g_qdf_dp_trace_data.tail);
3390 
3391 	/* acquire the lock so that only one thread at a time can read
3392 	 * the ring buffer
3393 	 */
3394 	spin_lock_bh(&l_dp_trace_lock);
3395 
3396 	if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) {
3397 		i = g_qdf_dp_trace_data.head;
3398 		tail = g_qdf_dp_trace_data.tail;
3399 
3400 		if (count) {
3401 			if (count > g_qdf_dp_trace_data.num)
3402 				count = g_qdf_dp_trace_data.num;
3403 			if (tail >= (count - 1))
3404 				i = tail - count + 1;
3405 			else if (count != MAX_QDF_DP_TRACE_RECORDS)
3406 				i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) -
3407 							     tail);
3408 		}
3409 
3410 		p_record = g_qdf_dp_trace_tbl[i];
3411 		spin_unlock_bh(&l_dp_trace_lock);
3412 		for (;; ) {
3413 			qdf_dp_trace_cb_table[p_record.code](&p_record,
3414 							(uint16_t)i, pdev_id, false);
3415 			if (i == tail)
3416 				break;
3417 			i += 1;
3418 
3419 			spin_lock_bh(&l_dp_trace_lock);
3420 			if (MAX_QDF_DP_TRACE_RECORDS == i)
3421 				i = 0;
3422 
3423 			p_record = g_qdf_dp_trace_tbl[i];
3424 			spin_unlock_bh(&l_dp_trace_lock);
3425 		}
3426 	} else {
3427 		spin_unlock_bh(&l_dp_trace_lock);
3428 	}
3429 }
3430 qdf_export_symbol(qdf_dp_trace_dump_all);
3431 
3432 /**
3433  * qdf_dp_trace_throttle_live_mode() - Throttle DP Trace live mode
3434  * @high_bw_request: whether this is a high BW req or not
3435  *
3436  * The function tries to prevent excessive logging into the live buffer by
3437  * having an upper limit on number of packets that can be logged per second.
3438  *
3439  * The intention is to allow occasional pings and data packets and really low
3440  * throughput levels while suppressing bursts and higher throughput levels so
3441  * that we donot hog the live buffer.
3442  *
3443  * If the number of packets printed in a particular second exceeds the thresh,
3444  * disable printing in the next second.
3445  *
3446  * Return: None
3447  */
3448 void qdf_dp_trace_throttle_live_mode(bool high_bw_request)
3449 {
3450 	static int bw_interval_counter;
3451 
3452 	if (g_qdf_dp_trace_data.enable == false ||
3453 		g_qdf_dp_trace_data.live_mode_config == false)
3454 		return;
3455 
3456 	if (high_bw_request) {
3457 		g_qdf_dp_trace_data.live_mode = 0;
3458 		bw_interval_counter = 0;
3459 		return;
3460 	}
3461 
3462 	bw_interval_counter++;
3463 
3464 	if (0 == (bw_interval_counter %
3465 			g_qdf_dp_trace_data.thresh_time_limit)) {
3466 
3467 		spin_lock_bh(&l_dp_trace_lock);
3468 			if (g_qdf_dp_trace_data.print_pkt_cnt <=
3469 				g_qdf_dp_trace_data.high_tput_thresh)
3470 				g_qdf_dp_trace_data.live_mode = 1;
3471 
3472 		g_qdf_dp_trace_data.print_pkt_cnt = 0;
3473 		spin_unlock_bh(&l_dp_trace_lock);
3474 	}
3475 }
3476 qdf_export_symbol(qdf_dp_trace_throttle_live_mode);
3477 
3478 void qdf_dp_trace_apply_tput_policy(bool is_data_traffic)
3479 {
3480 	if (g_qdf_dp_trace_data.dynamic_verbosity_modify) {
3481 		goto check_live_mode;
3482 		return;
3483 	}
3484 
3485 	if (is_data_traffic) {
3486 		g_qdf_dp_trace_data.verbosity =
3487 					QDF_DP_TRACE_VERBOSITY_ULTRA_LOW;
3488 	} else {
3489 		g_qdf_dp_trace_data.verbosity =
3490 					g_qdf_dp_trace_data.ini_conf_verbosity;
3491 	}
3492 check_live_mode:
3493 	qdf_dp_trace_throttle_live_mode(is_data_traffic);
3494 }
3495 #endif
3496 
3497 struct qdf_print_ctrl print_ctrl_obj[MAX_PRINT_CONFIG_SUPPORTED];
3498 
3499 struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = {
3500 	[QDF_MODULE_ID_TDLS] = {"tdls"},
3501 	[QDF_MODULE_ID_ACS] = {"ACS"},
3502 	[QDF_MODULE_ID_SCAN_SM] = {"scan state machine"},
3503 	[QDF_MODULE_ID_SCANENTRY] = {"scan entry"},
3504 	[QDF_MODULE_ID_WDS] = {"WDS"},
3505 	[QDF_MODULE_ID_ACTION] = {"action"},
3506 	[QDF_MODULE_ID_ROAM] = {"STA roaming"},
3507 	[QDF_MODULE_ID_INACT] = {"inactivity"},
3508 	[QDF_MODULE_ID_DOTH] = {"11h"},
3509 	[QDF_MODULE_ID_IQUE] = {"IQUE"},
3510 	[QDF_MODULE_ID_WME] = {"WME"},
3511 	[QDF_MODULE_ID_ACL] = {"ACL"},
3512 	[QDF_MODULE_ID_WPA] = {"WPA/RSN"},
3513 	[QDF_MODULE_ID_RADKEYS] = {"dump 802.1x keys"},
3514 	[QDF_MODULE_ID_RADDUMP] = {"dump radius packet"},
3515 	[QDF_MODULE_ID_RADIUS] = {"802.1x radius client"},
3516 	[QDF_MODULE_ID_DOT1XSM] = {"802.1x state machine"},
3517 	[QDF_MODULE_ID_DOT1X] = {"802.1x authenticator"},
3518 	[QDF_MODULE_ID_POWER] = {"power save"},
3519 	[QDF_MODULE_ID_STATE] = {"state"},
3520 	[QDF_MODULE_ID_OUTPUT] = {"output"},
3521 	[QDF_MODULE_ID_SCAN] = {"scan"},
3522 	[QDF_MODULE_ID_AUTH] = {"authentication"},
3523 	[QDF_MODULE_ID_ASSOC] = {"association"},
3524 	[QDF_MODULE_ID_NODE] = {"node"},
3525 	[QDF_MODULE_ID_ELEMID] = {"element ID"},
3526 	[QDF_MODULE_ID_XRATE] = {"rate"},
3527 	[QDF_MODULE_ID_INPUT] = {"input"},
3528 	[QDF_MODULE_ID_CRYPTO] = {"crypto"},
3529 	[QDF_MODULE_ID_DUMPPKTS] = {"dump packet"},
3530 	[QDF_MODULE_ID_DEBUG] = {"debug"},
3531 	[QDF_MODULE_ID_MLME] = {"mlme"},
3532 	[QDF_MODULE_ID_RRM] = {"rrm"},
3533 	[QDF_MODULE_ID_WNM] = {"wnm"},
3534 	[QDF_MODULE_ID_P2P_PROT] = {"p2p_prot"},
3535 	[QDF_MODULE_ID_PROXYARP] = {"proxyarp"},
3536 	[QDF_MODULE_ID_L2TIF] = {"l2tif"},
3537 	[QDF_MODULE_ID_WIFIPOS] = {"wifipos"},
3538 	[QDF_MODULE_ID_WRAP] = {"wrap"},
3539 	[QDF_MODULE_ID_DFS] = {"dfs"},
3540 	[QDF_MODULE_ID_ATF] = {"atf"},
3541 	[QDF_MODULE_ID_SPLITMAC] = {"splitmac"},
3542 	[QDF_MODULE_ID_IOCTL] = {"ioctl"},
3543 	[QDF_MODULE_ID_NAC] = {"nac"},
3544 	[QDF_MODULE_ID_MESH] = {"mesh"},
3545 	[QDF_MODULE_ID_MBO] = {"mbo"},
3546 	[QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = {"extchanswitch"},
3547 	[QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = {"extchanscan"},
3548 	[QDF_MODULE_ID_TLSHIM] = {"tlshim"},
3549 	[QDF_MODULE_ID_WMI] = {"WMI"},
3550 	[QDF_MODULE_ID_HTT] = {"HTT"},
3551 	[QDF_MODULE_ID_HDD] = {"HDD"},
3552 	[QDF_MODULE_ID_SME] = {"SME"},
3553 	[QDF_MODULE_ID_PE] = {"PE"},
3554 	[QDF_MODULE_ID_WMA] = {"WMA"},
3555 	[QDF_MODULE_ID_SYS] = {"SYS"},
3556 	[QDF_MODULE_ID_QDF] = {"QDF"},
3557 	[QDF_MODULE_ID_SAP] = {"SAP"},
3558 	[QDF_MODULE_ID_HDD_SOFTAP] = {"HDD_SAP"},
3559 	[QDF_MODULE_ID_HDD_DATA] = {"DATA"},
3560 	[QDF_MODULE_ID_HDD_SAP_DATA] = {"SAP_DATA"},
3561 	[QDF_MODULE_ID_HIF] = {"HIF"},
3562 	[QDF_MODULE_ID_HTC] = {"HTC"},
3563 	[QDF_MODULE_ID_TXRX] = {"TXRX"},
3564 	[QDF_MODULE_ID_QDF_DEVICE] = {"QDF_DEV"},
3565 	[QDF_MODULE_ID_CFG] = {"CFG"},
3566 	[QDF_MODULE_ID_BMI] = {"BMI"},
3567 	[QDF_MODULE_ID_EPPING] = {"EPPING"},
3568 	[QDF_MODULE_ID_QVIT] = {"QVIT"},
3569 	[QDF_MODULE_ID_DP] = {"DP"},
3570 	[QDF_MODULE_ID_HAL] = {"HAL"},
3571 	[QDF_MODULE_ID_SOC] = {"SOC"},
3572 	[QDF_MODULE_ID_OS_IF] = {"OSIF"},
3573 	[QDF_MODULE_ID_TARGET_IF] = {"TIF"},
3574 	[QDF_MODULE_ID_SCHEDULER] = {"SCH"},
3575 	[QDF_MODULE_ID_MGMT_TXRX] = {"MGMT_TXRX"},
3576 	[QDF_MODULE_ID_PMO] = {"PMO"},
3577 	[QDF_MODULE_ID_POLICY_MGR] = {"POLICY_MGR"},
3578 	[QDF_MODULE_ID_SA_API] = {"SA_API"},
3579 	[QDF_MODULE_ID_NAN] = {"NAN"},
3580 	[QDF_MODULE_ID_SPECTRAL] = {"SPECTRAL"},
3581 	[QDF_MODULE_ID_P2P] = {"P2P"},
3582 	[QDF_MODULE_ID_OFFCHAN_TXRX] = {"OFFCHAN"},
3583 	[QDF_MODULE_ID_REGULATORY] = {"REGULATORY"},
3584 	[QDF_MODULE_ID_OBJ_MGR] = {"OBJMGR"},
3585 	[QDF_MODULE_ID_SERIALIZATION] = {"SER"},
3586 	[QDF_MODULE_ID_NSS] = {"NSS"},
3587 	[QDF_MODULE_ID_ROAM_DEBUG] = {"roam debug"},
3588 	[QDF_MODULE_ID_DIRECT_BUF_RX] = {"DIRECT_BUF_RX"},
3589 	[QDF_MODULE_ID_DISA] = {"disa"},
3590 	[QDF_MODULE_ID_GREEN_AP] = {"GREEN_AP"},
3591 	[QDF_MODULE_ID_FD] = {"FILS discovery"},
3592 	[QDF_MODULE_ID_FTM] = {"FTM"},
3593 	[QDF_MODULE_ID_OCB] = {"OCB"},
3594 	[QDF_MODULE_ID_CONFIG] = {"CONFIG"},
3595 	[QDF_MODULE_ID_IPA] = {"IPA"},
3596 	[QDF_MODULE_ID_CP_STATS] = {"CP_STATS"},
3597 	[QDF_MODULE_ID_DCS] = {"DCS"},
3598 	[QDF_MODULE_ID_ACTION_OUI] = {"action_oui"},
3599 	[QDF_MODULE_ID_TARGET] = {"TARGET"},
3600 	[QDF_MODULE_ID_MBSSIE] = {"MBSSIE"},
3601 	[QDF_MODULE_ID_FWOL] = {"fwol"},
3602 	[QDF_MODULE_ID_SM_ENGINE] = {"SM_ENG"},
3603 	[QDF_MODULE_ID_CMN_MLME] = {"CMN_MLME"},
3604 	[QDF_MODULE_ID_BSSCOLOR] = {"BSSCOLOR"},
3605 	[QDF_MODULE_ID_CFR] = {"CFR"},
3606 	[QDF_MODULE_ID_DP_TX_CAPTURE] = {"TX_CAPTURE_ENHANCE"},
3607 	[QDF_MODULE_ID_INTEROP_ISSUES_AP] = {"INTEROP_ISSUES_AP"},
3608 	[QDF_MODULE_ID_DENYLIST_MGR] = {"dlm"},
3609 	[QDF_MODULE_ID_QLD] = {"QLD"},
3610 	[QDF_MODULE_ID_DYNAMIC_MODE_CHG] = {"Dynamic Mode Change"},
3611 	[QDF_MODULE_ID_COEX] = {"COEX"},
3612 	[QDF_MODULE_ID_MON_FILTER] = {"Monitor Filter"},
3613 	[QDF_MODULE_ID_PKT_CAPTURE] = {"pkt_capture"},
3614 	[QDF_MODULE_ID_RPTR] = {"RPTR"},
3615 	[QDF_MODULE_ID_6GHZ] = {"6GHZ"},
3616 	[QDF_MODULE_ID_IOT_SIM] = {"IOT_SIM"},
3617 	[QDF_MODULE_ID_MSCS] = {"MSCS"},
3618 	[QDF_MODULE_ID_GPIO] = {"GPIO_CFG"},
3619 	[QDF_MODULE_ID_IFMGR] = {"IF_MGR"},
3620 	[QDF_MODULE_ID_DIAG] = {"DIAG"},
3621 	[QDF_MODULE_ID_DP_INIT] = {"DP_INIT"},
3622 	[QDF_MODULE_ID_DP_TX] = {"DP_TX"},
3623 	[QDF_MODULE_ID_DP_RX] = {"DP_RX"},
3624 	[QDF_MODULE_ID_DP_STATS] = {"DP_STATS"},
3625 	[QDF_MODULE_ID_DP_HTT] = {"DP_HTT"},
3626 	[QDF_MODULE_ID_DP_PEER] = {"DP_PEER"},
3627 	[QDF_MODULE_ID_DP_RX_ERROR] = {"DP_RX_ERROR"},
3628 	[QDF_MODULE_ID_DP_HTT_TX_STATS] = {"DP_HTT_TX_STATS"},
3629 	[QDF_MODULE_ID_DP_RX_MON_STATUS] = {"DP_RX_MON_STATUS"},
3630 	[QDF_MODULE_ID_DP_RX_MON_DEST] = {"DP_RX_MON_DEST"},
3631 	[QDF_MODULE_ID_DP_REO] = {"DP_REO"},
3632 	[QDF_MODULE_ID_DP_TX_COMP] = {"DP_TX_COMP"},
3633 	[QDF_MODULE_ID_DP_VDEV] = {"DP_VDEV"},
3634 	[QDF_MODULE_ID_DP_CDP] = {"DP_CDP"},
3635 	[QDF_MODULE_ID_TSO] = {"TSO"},
3636 	[QDF_MODULE_ID_ME] = {"ME"},
3637 	[QDF_MODULE_ID_QWRAP] = {"QWRAP"},
3638 	[QDF_MODULE_ID_DBDC_REP] = {"DBDC_REP"},
3639 	[QDF_MODULE_ID_EXT_AP] = {"EXT_AP"},
3640 	[QDF_MODULE_ID_MLO] = {"MLO_MGR"},
3641 	[QDF_MODULE_ID_MGMT_RX_REO] = {"MGMT_RX_REO"},
3642 	[QDF_MODULE_ID_MLOIE] = {"MLOIE"},
3643 	[QDF_MODULE_ID_MBSS] = {"MBSS"},
3644 	[QDF_MODULE_ID_MON] = {"MONITOR"},
3645 	[QDF_MODULE_ID_AFC] = {"AFC"},
3646 	[QDF_MODULE_ID_TWT] = {"TWT"},
3647 	[QDF_MODULE_ID_SON] = {"SON"},
3648 	[QDF_MODULE_ID_WLAN_PRE_CAC] = {"PRE_CAC"},
3649 	[QDF_MODULE_ID_T2LM] = {"T2LM"},
3650 	[QDF_MODULE_ID_DP_SAWF] = {"DP_SAWF"},
3651 	[QDF_MODULE_ID_SCS] = {"SCS"},
3652 	[QDF_MODULE_ID_DP_UMAC_RESET] = {"UMAC_HW_RESET"},
3653 	[QDF_MODULE_ID_COAP] = {"COAP"},
3654 	[QDF_MODULE_ID_FTM_TIME_SYNC] = {"Time Sync"},
3655 	[QDF_MODULE_ID_WIFI_RADAR] = {"WIFI RADAR"},
3656 	[QDF_MODULE_ID_CDP] =  {"CDP"},
3657 	[QDF_MODULE_ID_QMI] = {"QMI"},
3658 	[QDF_MODULE_ID_ANY] = {"ANY"},
3659 };
3660 qdf_export_symbol(g_qdf_category_name);
3661 
3662 /**
3663  * qdf_trace_display() - Display trace
3664  *
3665  * Return:  None
3666  */
3667 void qdf_trace_display(void)
3668 {
3669 	QDF_MODULE_ID module_id;
3670 
3671 	pr_err("     1)FATAL  2)ERROR  3)WARN  4)INFO  5)INFO_H  6)INFO_M  7)INFO_L 8)DEBUG\n");
3672 	for (module_id = 0; module_id < QDF_MODULE_ID_MAX; ++module_id) {
3673 		pr_err("%2d)%s    %s        %s       %s       %s        %s         %s         %s        %s\n",
3674 		       (int)module_id,
3675 		       g_qdf_category_name[module_id].category_name_str,
3676 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3677 			       QDF_TRACE_LEVEL_FATAL) ? "X" : " ",
3678 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3679 			       QDF_TRACE_LEVEL_ERROR) ? "X" : " ",
3680 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3681 			       QDF_TRACE_LEVEL_WARN) ? "X" : " ",
3682 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3683 			       QDF_TRACE_LEVEL_INFO) ? "X" : " ",
3684 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3685 			       QDF_TRACE_LEVEL_INFO_HIGH) ? "X" : " ",
3686 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3687 			       QDF_TRACE_LEVEL_INFO_MED) ? "X" : " ",
3688 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3689 			       QDF_TRACE_LEVEL_INFO_LOW) ? "X" : " ",
3690 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3691 			       QDF_TRACE_LEVEL_DEBUG) ? "X" : " ");
3692 	}
3693 }
3694 qdf_export_symbol(qdf_trace_display);
3695 
3696 #ifdef WLAN_MAX_LOGS_PER_SEC
3697 static qdf_time_t __log_window_end;
3698 static qdf_atomic_t __log_window_count;
3699 uint32_t qdf_rl_print_count = WLAN_MAX_LOGS_PER_SEC;
3700 uint32_t qdf_rl_print_time = 1;
3701 uint32_t qdf_rl_print_suppressed;
3702 
3703 /**
3704  * qdf_detected_excessive_logging() - Excessive logging detected
3705  *
3706  * Track logging count using a quasi-tumbling window.
3707  * If the max logging count for a given window is exceeded,
3708  * return true else fails.
3709  *
3710  * Return: true/false
3711  */
3712 bool qdf_detected_excessive_logging(void)
3713 {
3714 	qdf_time_t now = qdf_system_ticks();
3715 	bool excessive_prints = false;
3716 
3717 	/*
3718 	 * If 'now' is more recent than the end of the window, reset.
3719 	 *
3720 	 * Note: This is not thread safe, and can result in more than one reset.
3721 	 * For our purposes, this is fine.
3722 	 */
3723 	if (!qdf_atomic_read(&__log_window_count)) {
3724 		__log_window_end = now + (qdf_system_ticks_per_sec * qdf_rl_print_time);
3725 	} else if (qdf_system_time_after(now, __log_window_end)) {
3726 		__log_window_end = now + (qdf_system_ticks_per_sec * qdf_rl_print_time);
3727 		qdf_atomic_set(&__log_window_count, 0);
3728 	}
3729 
3730 	if (qdf_atomic_inc_return(&__log_window_count) > qdf_rl_print_count)
3731 		excessive_prints = true;
3732 
3733 	return excessive_prints;
3734 }
3735 
3736 void qdf_rl_print_count_set(uint32_t rl_print_count)
3737 {
3738 	qdf_rl_print_count = rl_print_count;
3739 }
3740 
3741 qdf_export_symbol(qdf_rl_print_count_set);
3742 
3743 void qdf_rl_print_time_set(uint32_t rl_print_time)
3744 {
3745 	qdf_rl_print_time = rl_print_time;
3746 }
3747 
3748 qdf_export_symbol(qdf_rl_print_time_set);
3749 
3750 void qdf_rl_print_suppressed_log(void)
3751 {
3752 	if (qdf_rl_print_suppressed) {
3753 		pr_err("QDF Ratelimiting: %d prints suppressed",
3754 		       qdf_rl_print_suppressed);
3755 		qdf_rl_print_suppressed = 0;
3756 	}
3757 }
3758 
3759 void qdf_rl_print_suppressed_inc(void)
3760 {
3761 	qdf_rl_print_suppressed++;
3762 }
3763 #else
3764 #define qdf_rl_print_suppressed_log()
3765 #define qdf_rl_print_suppressed_inc()
3766 #endif /* WLAN_MAX_LOGS_PER_SEC */
3767 
3768 #ifdef QDF_TRACE_PRINT_ENABLE
3769 static inline void print_to_console(char *str_buffer)
3770 {
3771 	if (qdf_in_interrupt() && qdf_detected_excessive_logging()) {
3772 		qdf_rl_print_suppressed_inc();
3773 		return;
3774 	}
3775 	qdf_rl_print_suppressed_log();
3776 	pr_err("%s\n", str_buffer);
3777 }
3778 #else
3779 
3780 #define print_to_console(str)
3781 #endif
3782 
3783 #ifdef MULTI_IF_NAME
3784 static const char *qdf_trace_wlan_modname(void)
3785 {
3786 	return MULTI_IF_NAME;
3787 }
3788 #else
3789 static const char *qdf_trace_wlan_modname(void)
3790 {
3791 	return "wlan";
3792 }
3793 #endif
3794 
3795 void qdf_trace_msg_cmn(unsigned int idx,
3796 			QDF_MODULE_ID category,
3797 			QDF_TRACE_LEVEL verbose,
3798 			const char *str_format, va_list val)
3799 {
3800 	char str_buffer[QDF_TRACE_BUFFER_SIZE];
3801 	int n;
3802 
3803 	/* Check if index passed is valid */
3804 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3805 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3806 		return;
3807 	}
3808 
3809 	/* Check if print control object is in use */
3810 	if (!print_ctrl_obj[idx].in_use) {
3811 		pr_info("%s: Invalid print control object\n", __func__);
3812 		return;
3813 	}
3814 
3815 	/* Check if category passed is valid */
3816 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
3817 		vscnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, str_format, val);
3818 		pr_info("%s: Invalid category: %d, log: %s\n",
3819 			__func__, category, str_buffer);
3820 		return;
3821 	}
3822 
3823 	/* Check if verbose mask is valid */
3824 	if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
3825 		vscnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, str_format, val);
3826 		pr_info("%s: Invalid verbose level %d, log: %s\n",
3827 			__func__, verbose, str_buffer);
3828 		return;
3829 	}
3830 
3831 	/*
3832 	 * Print the trace message when the desired verbose level is set in
3833 	 * the desired category for the print control object
3834 	 */
3835 	if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
3836 	    QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
3837 		static const char * const VERBOSE_STR[] = {
3838 			[QDF_TRACE_LEVEL_NONE] = "",
3839 			[QDF_TRACE_LEVEL_FATAL] = "F",
3840 			[QDF_TRACE_LEVEL_ERROR] = "E",
3841 			[QDF_TRACE_LEVEL_WARN] = "W",
3842 			[QDF_TRACE_LEVEL_INFO] = "I",
3843 			[QDF_TRACE_LEVEL_INFO_HIGH] = "IH",
3844 			[QDF_TRACE_LEVEL_INFO_MED] = "IM",
3845 			[QDF_TRACE_LEVEL_INFO_LOW] = "IL",
3846 			[QDF_TRACE_LEVEL_DEBUG] = "D",
3847 			[QDF_TRACE_LEVEL_TRACE] = "T",
3848 			[QDF_TRACE_LEVEL_ALL] = "" };
3849 
3850 		/* print the prefix string into the string buffer... */
3851 		n = scnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE,
3852 			     "%s: [%d:%s:%s] ", qdf_trace_wlan_modname(),
3853 			     in_interrupt() ? 0 : current->pid,
3854 			     VERBOSE_STR[verbose],
3855 			     g_qdf_category_name[category].category_name_str);
3856 
3857 		/* print the formatted log message after the prefix string */
3858 		vscnprintf(str_buffer + n, QDF_TRACE_BUFFER_SIZE - n,
3859 			   str_format, val);
3860 #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE)
3861 		wlan_log_to_user(verbose, (char *)str_buffer,
3862 				 strlen(str_buffer));
3863 		if (qdf_unlikely(qdf_log_dump_at_kernel_enable))
3864 			print_to_console(str_buffer);
3865 #else
3866 		pr_err("%s\n", str_buffer);
3867 #endif
3868 	}
3869 }
3870 qdf_export_symbol(qdf_trace_msg_cmn);
3871 
3872 QDF_STATUS qdf_print_setup(void)
3873 {
3874 	int i;
3875 
3876 	/* Loop through all print ctrl objects */
3877 	for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
3878 		if (qdf_print_ctrl_cleanup(i))
3879 			return QDF_STATUS_E_FAILURE;
3880 	}
3881 	return QDF_STATUS_SUCCESS;
3882 }
3883 qdf_export_symbol(qdf_print_setup);
3884 
3885 QDF_STATUS qdf_print_ctrl_cleanup(unsigned int idx)
3886 {
3887 	int i = 0;
3888 
3889 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3890 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3891 		return QDF_STATUS_E_FAILURE;
3892 	}
3893 
3894 	/* Clean up the print control object corresponding to that index
3895 	 * If success, callee to change print control index to -1
3896 	 */
3897 
3898 	for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3899 		print_ctrl_obj[idx].cat_info[i].category_verbose_mask =
3900 							QDF_TRACE_LEVEL_NONE;
3901 	}
3902 	print_ctrl_obj[idx].custom_print = NULL;
3903 	print_ctrl_obj[idx].custom_ctxt = NULL;
3904 	qdf_print_clean_node_flag(idx);
3905 	print_ctrl_obj[idx].in_use = false;
3906 
3907 	return QDF_STATUS_SUCCESS;
3908 }
3909 qdf_export_symbol(qdf_print_ctrl_cleanup);
3910 
3911 int qdf_print_ctrl_register(const struct category_info *cinfo,
3912 			    void *custom_print_handler,
3913 			    void *custom_ctx,
3914 			    const char *pctrl_name)
3915 {
3916 	int idx = -1;
3917 	int i = 0;
3918 
3919 	for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
3920 		if (!print_ctrl_obj[i].in_use) {
3921 			idx = i;
3922 			break;
3923 		}
3924 	}
3925 
3926 	/* Callee to handle idx -1 appropriately */
3927 	if (idx == -1) {
3928 		pr_info("%s: Allocation failed! No print control object free\n",
3929 			__func__);
3930 		return idx;
3931 	}
3932 
3933 	print_ctrl_obj[idx].in_use = true;
3934 
3935 	/*
3936 	 * In case callee does not pass category info,
3937 	 * custom print handler, custom context and print control name,
3938 	 * we do not set any value here. Clean up for the print control
3939 	 * getting allocated would have taken care of initializing
3940 	 * default values.
3941 	 *
3942 	 * We need to only set in_use to 1 in such a case
3943 	 */
3944 
3945 	if (pctrl_name) {
3946 		qdf_str_lcopy(print_ctrl_obj[idx].name, pctrl_name,
3947 			      sizeof(print_ctrl_obj[idx].name));
3948 	}
3949 
3950 	if (custom_print_handler)
3951 		print_ctrl_obj[idx].custom_print = custom_print_handler;
3952 
3953 	if (custom_ctx)
3954 		print_ctrl_obj[idx].custom_ctxt = custom_ctx;
3955 
3956 	if (cinfo) {
3957 		for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3958 			if (cinfo[i].category_verbose_mask ==
3959 			    QDF_TRACE_LEVEL_ALL) {
3960 				print_ctrl_obj[idx].cat_info[i]
3961 				.category_verbose_mask = 0xFFFF;
3962 			} else if ((cinfo[i].category_verbose_mask ==
3963 				   QDF_TRACE_LEVEL_NONE) ||
3964 				   (cinfo[i].category_verbose_mask ==
3965 				   QDF_TRACE_LEVEL_TO_MODULE_BITMASK(
3966 				   QDF_TRACE_LEVEL_NONE))) {
3967 				print_ctrl_obj[idx].cat_info[i]
3968 				.category_verbose_mask = 0;
3969 			} else {
3970 				print_ctrl_obj[idx].cat_info[i]
3971 				.category_verbose_mask =
3972 				cinfo[i].category_verbose_mask;
3973 			}
3974 		}
3975 	}
3976 
3977 	return idx;
3978 }
3979 qdf_export_symbol(qdf_print_ctrl_register);
3980 
3981 #ifdef QDF_TRACE_PRINT_ENABLE
3982 void qdf_shared_print_ctrl_cleanup(void)
3983 {
3984 	qdf_print_ctrl_cleanup(qdf_pidx);
3985 }
3986 qdf_export_symbol(qdf_shared_print_ctrl_cleanup);
3987 
3988 /*
3989  * Set this to invalid value to differentiate with user-provided
3990  * value.
3991  */
3992 int qdf_dbg_mask = QDF_TRACE_LEVEL_MAX;
3993 qdf_export_symbol(qdf_dbg_mask);
3994 qdf_declare_param(qdf_dbg_mask, int);
3995 
3996 /*
3997  * QDF can be passed parameters which indicate the
3998  * debug level for each module.
3999  * an array of string values are passed, each string hold the following form
4000  *
4001  * <module name string>=<integer debug level value>
4002  *
4003  * The array qdf_dbg_arr will hold these module-string=value strings
4004  * The variable qdf_dbg_arr_cnt will have the count of how many such
4005  * string values were passed.
4006  */
4007 static char *qdf_dbg_arr[QDF_MODULE_ID_MAX];
4008 static int qdf_dbg_arr_cnt;
4009 qdf_declare_param_array(qdf_dbg_arr, charp, &qdf_dbg_arr_cnt);
4010 
4011 static uint16_t set_cumulative_verbose_mask(QDF_TRACE_LEVEL max_level)
4012 {
4013 	uint16_t category_verbose_mask = 0;
4014 	QDF_TRACE_LEVEL level;
4015 
4016 	for (level = QDF_TRACE_LEVEL_FATAL; level <= max_level; level++) {
4017 		category_verbose_mask |=
4018 			QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level);
4019 	}
4020 	return category_verbose_mask;
4021 }
4022 
4023 static QDF_MODULE_ID find_qdf_module_from_string(char *str)
4024 {
4025 	QDF_MODULE_ID mod_id;
4026 
4027 	for (mod_id = 0; mod_id < QDF_MODULE_ID_MAX; mod_id++) {
4028 		if (strcasecmp(str,
4029 				g_qdf_category_name[mod_id].category_name_str)
4030 				== 0) {
4031 			break;
4032 		}
4033 	}
4034 	return mod_id;
4035 }
4036 
4037 static void process_qdf_dbg_arr_param(struct category_info *cinfo,
4038 					int array_index)
4039 {
4040 	char *mod_val_str, *mod_str, *val_str;
4041 	unsigned long dbg_level;
4042 	QDF_MODULE_ID mod_id;
4043 
4044 	mod_val_str = qdf_dbg_arr[array_index];
4045 	mod_str = strsep(&mod_val_str, "=");
4046 	val_str = mod_val_str;
4047 	if (!val_str) {
4048 		pr_info("qdf_dbg_arr: %s not in the <mod>=<val> form\n",
4049 				mod_str);
4050 		return;
4051 	}
4052 
4053 	mod_id = find_qdf_module_from_string(mod_str);
4054 	if (mod_id >= QDF_MODULE_ID_MAX) {
4055 		pr_info("ERROR!!Module name %s not in the list of modules\n",
4056 				mod_str);
4057 		return;
4058 	}
4059 
4060 	if (kstrtol(val_str, 10, &dbg_level) < 0) {
4061 		pr_info("ERROR!!Invalid debug level for module: %s\n",
4062 				mod_str);
4063 		return;
4064 	}
4065 
4066 	if (dbg_level >= QDF_TRACE_LEVEL_MAX) {
4067 		pr_info("ERROR!!Debug level for %s too high", mod_str);
4068 		pr_info("max: %d given %lu\n", QDF_TRACE_LEVEL_MAX,
4069 				dbg_level);
4070 		return;
4071 	}
4072 
4073 	pr_info("User passed setting module %s(%d) to level %lu\n",
4074 			mod_str,
4075 			mod_id,
4076 			dbg_level);
4077 	cinfo[mod_id].category_verbose_mask =
4078 		set_cumulative_verbose_mask((QDF_TRACE_LEVEL)dbg_level);
4079 }
4080 
4081 static void set_default_trace_levels(struct category_info *cinfo)
4082 {
4083 	int i;
4084 	static QDF_TRACE_LEVEL module_trace_default_level[QDF_MODULE_ID_MAX] = {
4085 		[QDF_MODULE_ID_TDLS] = QDF_TRACE_LEVEL_NONE,
4086 		[QDF_MODULE_ID_ACS] = QDF_TRACE_LEVEL_NONE,
4087 		[QDF_MODULE_ID_SCAN_SM] = QDF_TRACE_LEVEL_NONE,
4088 		[QDF_MODULE_ID_SCANENTRY] = QDF_TRACE_LEVEL_NONE,
4089 		[QDF_MODULE_ID_WDS] = QDF_TRACE_LEVEL_NONE,
4090 		[QDF_MODULE_ID_ACTION] = QDF_TRACE_LEVEL_NONE,
4091 		[QDF_MODULE_ID_ROAM] = QDF_TRACE_LEVEL_NONE,
4092 		[QDF_MODULE_ID_INACT] = QDF_TRACE_LEVEL_NONE,
4093 		[QDF_MODULE_ID_DOTH] = QDF_TRACE_LEVEL_NONE,
4094 		[QDF_MODULE_ID_IQUE] = QDF_TRACE_LEVEL_NONE,
4095 		[QDF_MODULE_ID_WME] = QDF_TRACE_LEVEL_NONE,
4096 		[QDF_MODULE_ID_ACL] = QDF_TRACE_LEVEL_NONE,
4097 		[QDF_MODULE_ID_WPA] = QDF_TRACE_LEVEL_NONE,
4098 		[QDF_MODULE_ID_RADKEYS] = QDF_TRACE_LEVEL_NONE,
4099 		[QDF_MODULE_ID_RADDUMP] = QDF_TRACE_LEVEL_NONE,
4100 		[QDF_MODULE_ID_RADIUS] = QDF_TRACE_LEVEL_NONE,
4101 		[QDF_MODULE_ID_DOT1XSM] = QDF_TRACE_LEVEL_NONE,
4102 		[QDF_MODULE_ID_DOT1X] = QDF_TRACE_LEVEL_NONE,
4103 		[QDF_MODULE_ID_POWER] = QDF_TRACE_LEVEL_NONE,
4104 		[QDF_MODULE_ID_STATE] = QDF_TRACE_LEVEL_NONE,
4105 		[QDF_MODULE_ID_OUTPUT] = QDF_TRACE_LEVEL_NONE,
4106 		[QDF_MODULE_ID_SCAN] = QDF_TRACE_LEVEL_ERROR,
4107 		[QDF_MODULE_ID_AUTH] = QDF_TRACE_LEVEL_NONE,
4108 		[QDF_MODULE_ID_ASSOC] = QDF_TRACE_LEVEL_NONE,
4109 		[QDF_MODULE_ID_NODE] = QDF_TRACE_LEVEL_NONE,
4110 		[QDF_MODULE_ID_ELEMID] = QDF_TRACE_LEVEL_NONE,
4111 		[QDF_MODULE_ID_XRATE] = QDF_TRACE_LEVEL_NONE,
4112 		[QDF_MODULE_ID_INPUT] = QDF_TRACE_LEVEL_NONE,
4113 		[QDF_MODULE_ID_CRYPTO] = QDF_TRACE_LEVEL_NONE,
4114 		[QDF_MODULE_ID_DUMPPKTS] = QDF_TRACE_LEVEL_NONE,
4115 		[QDF_MODULE_ID_DEBUG] = QDF_TRACE_LEVEL_NONE,
4116 		[QDF_MODULE_ID_MLME] = QDF_TRACE_LEVEL_ERROR,
4117 		[QDF_MODULE_ID_RRM] = QDF_TRACE_LEVEL_NONE,
4118 		[QDF_MODULE_ID_WNM] = QDF_TRACE_LEVEL_NONE,
4119 		[QDF_MODULE_ID_P2P_PROT] = QDF_TRACE_LEVEL_NONE,
4120 		[QDF_MODULE_ID_PROXYARP] = QDF_TRACE_LEVEL_NONE,
4121 		[QDF_MODULE_ID_L2TIF] = QDF_TRACE_LEVEL_NONE,
4122 		[QDF_MODULE_ID_WIFIPOS] = QDF_TRACE_LEVEL_NONE,
4123 		[QDF_MODULE_ID_WRAP] = QDF_TRACE_LEVEL_NONE,
4124 		[QDF_MODULE_ID_DFS] = QDF_TRACE_LEVEL_NONE,
4125 		[QDF_MODULE_ID_ATF] = QDF_TRACE_LEVEL_ERROR,
4126 		[QDF_MODULE_ID_SPLITMAC] = QDF_TRACE_LEVEL_NONE,
4127 		[QDF_MODULE_ID_IOCTL] = QDF_TRACE_LEVEL_NONE,
4128 		[QDF_MODULE_ID_NAC] = QDF_TRACE_LEVEL_NONE,
4129 		[QDF_MODULE_ID_MESH] = QDF_TRACE_LEVEL_NONE,
4130 		[QDF_MODULE_ID_MBO] = QDF_TRACE_LEVEL_NONE,
4131 		[QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = QDF_TRACE_LEVEL_NONE,
4132 		[QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = QDF_TRACE_LEVEL_NONE,
4133 		[QDF_MODULE_ID_TLSHIM] = QDF_TRACE_LEVEL_NONE,
4134 		[QDF_MODULE_ID_WMI] = QDF_TRACE_LEVEL_ERROR,
4135 		[QDF_MODULE_ID_HTT] = QDF_TRACE_LEVEL_NONE,
4136 		[QDF_MODULE_ID_HDD] = QDF_TRACE_LEVEL_NONE,
4137 		[QDF_MODULE_ID_SME] = QDF_TRACE_LEVEL_NONE,
4138 		[QDF_MODULE_ID_PE] = QDF_TRACE_LEVEL_NONE,
4139 		[QDF_MODULE_ID_WMA] = QDF_TRACE_LEVEL_NONE,
4140 		[QDF_MODULE_ID_SYS] = QDF_TRACE_LEVEL_NONE,
4141 		[QDF_MODULE_ID_QDF] = QDF_TRACE_LEVEL_ERROR,
4142 		[QDF_MODULE_ID_SAP] = QDF_TRACE_LEVEL_NONE,
4143 		[QDF_MODULE_ID_HDD_SOFTAP] = QDF_TRACE_LEVEL_NONE,
4144 		[QDF_MODULE_ID_HDD_DATA] = QDF_TRACE_LEVEL_NONE,
4145 		[QDF_MODULE_ID_HDD_SAP_DATA] = QDF_TRACE_LEVEL_NONE,
4146 		[QDF_MODULE_ID_HIF] = QDF_TRACE_LEVEL_ERROR,
4147 		[QDF_MODULE_ID_HTC] = QDF_TRACE_LEVEL_NONE,
4148 		[QDF_MODULE_ID_TXRX] = QDF_TRACE_LEVEL_NONE,
4149 		[QDF_MODULE_ID_QDF_DEVICE] = QDF_TRACE_LEVEL_NONE,
4150 		[QDF_MODULE_ID_CFG] = QDF_TRACE_LEVEL_NONE,
4151 		[QDF_MODULE_ID_BMI] = QDF_TRACE_LEVEL_NONE,
4152 		[QDF_MODULE_ID_EPPING] = QDF_TRACE_LEVEL_NONE,
4153 		[QDF_MODULE_ID_QVIT] = QDF_TRACE_LEVEL_NONE,
4154 		[QDF_MODULE_ID_DP] = QDF_TRACE_LEVEL_FATAL,
4155 		[QDF_MODULE_ID_HAL] = QDF_TRACE_LEVEL_NONE,
4156 		[QDF_MODULE_ID_SOC] = QDF_TRACE_LEVEL_NONE,
4157 		[QDF_MODULE_ID_OS_IF] = QDF_TRACE_LEVEL_NONE,
4158 		[QDF_MODULE_ID_TARGET_IF] = QDF_TRACE_LEVEL_INFO,
4159 		[QDF_MODULE_ID_SCHEDULER] = QDF_TRACE_LEVEL_FATAL,
4160 		[QDF_MODULE_ID_MGMT_TXRX] = QDF_TRACE_LEVEL_NONE,
4161 		[QDF_MODULE_ID_SERIALIZATION] = QDF_TRACE_LEVEL_ERROR,
4162 		[QDF_MODULE_ID_PMO] = QDF_TRACE_LEVEL_NONE,
4163 		[QDF_MODULE_ID_P2P] = QDF_TRACE_LEVEL_NONE,
4164 		[QDF_MODULE_ID_POLICY_MGR] = QDF_TRACE_LEVEL_NONE,
4165 		[QDF_MODULE_ID_CONFIG] = QDF_TRACE_LEVEL_ERROR,
4166 		[QDF_MODULE_ID_REGULATORY] = QDF_TRACE_LEVEL_NONE,
4167 		[QDF_MODULE_ID_SA_API] = QDF_TRACE_LEVEL_NONE,
4168 		[QDF_MODULE_ID_NAN] = QDF_TRACE_LEVEL_NONE,
4169 		[QDF_MODULE_ID_OFFCHAN_TXRX] = QDF_TRACE_LEVEL_NONE,
4170 		[QDF_MODULE_ID_SON] = QDF_TRACE_LEVEL_NONE,
4171 		[QDF_MODULE_ID_SPECTRAL] = QDF_TRACE_LEVEL_ERROR,
4172 		[QDF_MODULE_ID_OBJ_MGR] = QDF_TRACE_LEVEL_FATAL,
4173 		[QDF_MODULE_ID_NSS] = QDF_TRACE_LEVEL_ERROR,
4174 		[QDF_MODULE_ID_ROAM_DEBUG] = QDF_TRACE_LEVEL_ERROR,
4175 		[QDF_MODULE_ID_CDP] = QDF_TRACE_LEVEL_NONE,
4176 		[QDF_MODULE_ID_DIRECT_BUF_RX] = QDF_TRACE_LEVEL_ERROR,
4177 		[QDF_MODULE_ID_DISA] = QDF_TRACE_LEVEL_NONE,
4178 		[QDF_MODULE_ID_GREEN_AP] = QDF_TRACE_LEVEL_ERROR,
4179 		[QDF_MODULE_ID_FTM] = QDF_TRACE_LEVEL_ERROR,
4180 		[QDF_MODULE_ID_FD] = QDF_TRACE_LEVEL_ERROR,
4181 		[QDF_MODULE_ID_OCB] = QDF_TRACE_LEVEL_ERROR,
4182 		[QDF_MODULE_ID_IPA] = QDF_TRACE_LEVEL_NONE,
4183 		[QDF_MODULE_ID_ACTION_OUI] = QDF_TRACE_LEVEL_NONE,
4184 		[QDF_MODULE_ID_CP_STATS] = QDF_TRACE_LEVEL_ERROR,
4185 		[QDF_MODULE_ID_DCS] = QDF_TRACE_LEVEL_ERROR,
4186 		[QDF_MODULE_ID_MBSSIE] = QDF_TRACE_LEVEL_INFO,
4187 		[QDF_MODULE_ID_FWOL] = QDF_TRACE_LEVEL_NONE,
4188 		[QDF_MODULE_ID_SM_ENGINE] = QDF_TRACE_LEVEL_ERROR,
4189 		[QDF_MODULE_ID_CMN_MLME] = QDF_TRACE_LEVEL_INFO,
4190 		[QDF_MODULE_ID_BSSCOLOR] = QDF_TRACE_LEVEL_ERROR,
4191 		[QDF_MODULE_ID_CFR] = QDF_TRACE_LEVEL_ERROR,
4192 		[QDF_MODULE_ID_DP_TX_CAPTURE] = QDF_TRACE_LEVEL_FATAL,
4193 		[QDF_MODULE_ID_INTEROP_ISSUES_AP] = QDF_TRACE_LEVEL_NONE,
4194 		[QDF_MODULE_ID_DENYLIST_MGR] = QDF_TRACE_LEVEL_NONE,
4195 		[QDF_MODULE_ID_QLD] = QDF_TRACE_LEVEL_ERROR,
4196 		[QDF_MODULE_ID_DYNAMIC_MODE_CHG] = QDF_TRACE_LEVEL_INFO,
4197 		[QDF_MODULE_ID_COEX] = QDF_TRACE_LEVEL_ERROR,
4198 		[QDF_MODULE_ID_MON_FILTER] = QDF_TRACE_LEVEL_INFO,
4199 		[QDF_MODULE_ID_PKT_CAPTURE] = QDF_TRACE_LEVEL_NONE,
4200 		[QDF_MODULE_ID_RPTR] = QDF_TRACE_LEVEL_INFO,
4201 		[QDF_MODULE_ID_6GHZ] = QDF_TRACE_LEVEL_ERROR,
4202 		[QDF_MODULE_ID_IOT_SIM] = QDF_TRACE_LEVEL_ERROR,
4203 		[QDF_MODULE_ID_MSCS] = QDF_TRACE_LEVEL_INFO,
4204 		[QDF_MODULE_ID_GPIO] = QDF_TRACE_LEVEL_NONE,
4205 		[QDF_MODULE_ID_IFMGR] = QDF_TRACE_LEVEL_ERROR,
4206 		[QDF_MODULE_ID_DIAG] = QDF_TRACE_LEVEL_ERROR,
4207 		[QDF_MODULE_ID_DP_INIT] = QDF_TRACE_LEVEL_FATAL,
4208 		[QDF_MODULE_ID_DP_TX] = QDF_TRACE_LEVEL_FATAL,
4209 		[QDF_MODULE_ID_DP_RX] = QDF_TRACE_LEVEL_FATAL,
4210 		[QDF_MODULE_ID_DP_STATS] = QDF_TRACE_LEVEL_FATAL,
4211 		[QDF_MODULE_ID_DP_HTT] = QDF_TRACE_LEVEL_FATAL,
4212 		[QDF_MODULE_ID_DP_PEER] = QDF_TRACE_LEVEL_FATAL,
4213 		[QDF_MODULE_ID_DP_RX_ERROR] = QDF_TRACE_LEVEL_FATAL,
4214 		[QDF_MODULE_ID_DP_HTT_TX_STATS] = QDF_TRACE_LEVEL_FATAL,
4215 		[QDF_MODULE_ID_DP_RX_MON_STATUS] = QDF_TRACE_LEVEL_FATAL,
4216 		[QDF_MODULE_ID_DP_RX_MON_DEST] = QDF_TRACE_LEVEL_FATAL,
4217 		[QDF_MODULE_ID_DP_REO] = QDF_TRACE_LEVEL_FATAL,
4218 		[QDF_MODULE_ID_DP_TX_COMP] = QDF_TRACE_LEVEL_FATAL,
4219 		[QDF_MODULE_ID_DP_VDEV] = QDF_TRACE_LEVEL_FATAL,
4220 		[QDF_MODULE_ID_DP_CDP] = QDF_TRACE_LEVEL_FATAL,
4221 		[QDF_MODULE_ID_TSO] = QDF_TRACE_LEVEL_FATAL,
4222 		[QDF_MODULE_ID_ME] = QDF_TRACE_LEVEL_INFO,
4223 		[QDF_MODULE_ID_QWRAP] = QDF_TRACE_LEVEL_FATAL,
4224 		[QDF_MODULE_ID_DBDC_REP] = QDF_TRACE_LEVEL_FATAL,
4225 		[QDF_MODULE_ID_EXT_AP] = QDF_TRACE_LEVEL_NONE,
4226 		[QDF_MODULE_ID_MLO] = QDF_TRACE_LEVEL_INFO,
4227 		[QDF_MODULE_ID_MLOIE] = QDF_TRACE_LEVEL_INFO,
4228 		[QDF_MODULE_ID_MBSS] = QDF_TRACE_LEVEL_ERROR,
4229 		[QDF_MODULE_ID_MON] = QDF_TRACE_LEVEL_ERROR,
4230 		[QDF_MODULE_ID_MGMT_RX_REO] = QDF_TRACE_LEVEL_ERROR,
4231 		[QDF_MODULE_ID_TWT] = QDF_TRACE_LEVEL_ERROR,
4232 		[QDF_MODULE_ID_WLAN_PRE_CAC] = QDF_TRACE_LEVEL_ERROR,
4233 		[QDF_MODULE_ID_T2LM] = QDF_TRACE_LEVEL_ERROR,
4234 		[QDF_MODULE_ID_DP_SAWF] = QDF_TRACE_LEVEL_ERROR,
4235 		[QDF_MODULE_ID_SCS] = QDF_TRACE_LEVEL_ERROR,
4236 		[QDF_MODULE_ID_DP_UMAC_RESET] = QDF_TRACE_LEVEL_ERROR,
4237 		[QDF_MODULE_ID_COAP] = QDF_TRACE_LEVEL_ERROR,
4238 		[QDF_MODULE_ID_FTM_TIME_SYNC] = QDF_TRACE_LEVEL_NONE,
4239 		[QDF_MODULE_ID_AFC] = QDF_TRACE_LEVEL_NONE,
4240 		[QDF_MODULE_ID_WIFI_RADAR] = QDF_TRACE_LEVEL_NONE,
4241 		[QDF_MODULE_ID_TARGET] = QDF_TRACE_LEVEL_NONE,
4242 		[QDF_MODULE_ID_QMI] = QDF_TRACE_LEVEL_ERROR,
4243 		[QDF_MODULE_ID_ANY] = QDF_TRACE_LEVEL_INFO,
4244 	};
4245 
4246 	for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
4247 		cinfo[i].category_verbose_mask = set_cumulative_verbose_mask(
4248 				module_trace_default_level[i]);
4249 	}
4250 }
4251 
4252 void qdf_shared_print_ctrl_init(void)
4253 {
4254 	int i;
4255 	struct category_info cinfo[MAX_SUPPORTED_CATEGORY];
4256 
4257 	set_default_trace_levels(cinfo);
4258 
4259 	/*
4260 	 * User specified across-module single debug level
4261 	 */
4262 	if ((qdf_dbg_mask >= 0) && (qdf_dbg_mask < QDF_TRACE_LEVEL_MAX)) {
4263 		pr_info("User specified module debug level of %d\n",
4264 			qdf_dbg_mask);
4265 		for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
4266 			cinfo[i].category_verbose_mask =
4267 			set_cumulative_verbose_mask(qdf_dbg_mask);
4268 		}
4269 	} else if (qdf_dbg_mask != QDF_TRACE_LEVEL_MAX) {
4270 		pr_info("qdf_dbg_mask value is invalid\n");
4271 		pr_info("Using the default module debug levels instead\n");
4272 	}
4273 
4274 	/*
4275 	 * Module ID-Level specified as array during module load
4276 	 */
4277 	for (i = 0; i < qdf_dbg_arr_cnt; i++) {
4278 		process_qdf_dbg_arr_param(cinfo, i);
4279 	}
4280 	qdf_pidx = qdf_print_ctrl_register(cinfo, NULL, NULL,
4281 			"LOG_SHARED_OBJ");
4282 }
4283 qdf_export_symbol(qdf_shared_print_ctrl_init);
4284 #endif
4285 
4286 #ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI
4287 QDF_STATUS qdf_module_param_handler(void *context, const char *str_param,
4288 				    const char *str)
4289 {
4290 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
4291 	uint16_t param = 0;
4292 	uint32_t flush_tmr_prd;
4293 	bool dump_flag;
4294 
4295 	while (param < QDF_PARAM_MAX) {
4296 		if (qdf_str_eq(qdf_module_param[param], str_param)) {
4297 			switch (param) {
4298 			case MEM_DEBUG_DISABLED:
4299 				status = qdf_mem_debug_disabled_config_set(str);
4300 				break;
4301 			case QDF_DBG_MASK:
4302 				status = qdf_int32_parse(str, &qdf_dbg_mask);
4303 				break;
4304 			case PREALLOC_DISABLED:
4305 				status = qdf_prealloc_disabled_config_set(str);
4306 				break;
4307 			case QDF_LOG_DUMP_AT_KERNEL_ENABLE:
4308 				status = qdf_bool_parse(str, &dump_flag);
4309 				qdf_log_dump_at_kernel_enable = dump_flag;
4310 				break;
4311 			case QDF_DBG_ARR:
4312 				qdf_dbg_arr[0] = (char *)str;
4313 				status = QDF_STATUS_SUCCESS;
4314 				break;
4315 			case QDF_LOG_FLUSH_TIMER_PERIOD:
4316 				status = qdf_uint32_parse(str, &flush_tmr_prd);
4317 				qdf_log_flush_timer_period = flush_tmr_prd;
4318 				break;
4319 			default:
4320 				break;
4321 			}
4322 			return status;
4323 		}
4324 		param++;
4325 	}
4326 
4327 	return QDF_STATUS_SUCCESS;
4328 }
4329 
4330 void qdf_initialize_module_param_from_ini(void)
4331 {
4332 	QDF_STATUS status;
4333 	char *path = QDF_WIFI_MODULE_PARAMS_FILE;
4334 
4335 	status = qdf_ini_parse(path, NULL, qdf_module_param_handler, NULL);
4336 	if (QDF_IS_STATUS_ERROR(status)) {
4337 		QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
4338 				"Failed to parse *.ini file @ %s; status:%d",
4339 				path, status);
4340 		return;
4341 	}
4342 }
4343 #endif
4344 
4345 QDF_STATUS qdf_print_set_category_verbose(unsigned int idx,
4346 						QDF_MODULE_ID category,
4347 						QDF_TRACE_LEVEL verbose,
4348 						bool is_set)
4349 {
4350 	/* Check if index passed is valid */
4351 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4352 		pr_err("%s: Invalid index - %d\n", __func__, idx);
4353 		return QDF_STATUS_E_FAILURE;
4354 	}
4355 
4356 	/* Check if print control object is in use */
4357 	if (!print_ctrl_obj[idx].in_use) {
4358 		pr_err("%s: Invalid print control object\n", __func__);
4359 		return QDF_STATUS_E_FAILURE;
4360 	}
4361 
4362 	/* Check if category passed is valid */
4363 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
4364 		pr_err("%s: Invalid category: %d\n", __func__, category);
4365 		return QDF_STATUS_E_FAILURE;
4366 	}
4367 
4368 	/* Check if verbose mask is valid */
4369 	if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
4370 		pr_err("%s: Invalid verbose level %d\n", __func__, verbose);
4371 		return QDF_STATUS_E_FAILURE;
4372 	}
4373 
4374 	if (verbose == QDF_TRACE_LEVEL_ALL) {
4375 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
4376 				0xFFFF;
4377 		return QDF_STATUS_SUCCESS;
4378 	}
4379 
4380 	if (verbose == QDF_TRACE_LEVEL_NONE) {
4381 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
4382 				QDF_TRACE_LEVEL_NONE;
4383 		return QDF_STATUS_SUCCESS;
4384 	}
4385 
4386 	if (!is_set) {
4387 		if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask
4388 		    & QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
4389 			print_ctrl_obj[idx].cat_info[category]
4390 				.category_verbose_mask &=
4391 				~QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
4392 		}
4393 	} else {
4394 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask |=
4395 				QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
4396 	}
4397 
4398 	pr_debug("%s: Print control object %d, Category %d, Verbose level %d\n",
4399 		__func__,
4400 		idx,
4401 		category,
4402 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask);
4403 
4404 	return QDF_STATUS_SUCCESS;
4405 }
4406 qdf_export_symbol(qdf_print_set_category_verbose);
4407 
4408 void qdf_log_dump_at_kernel_level(bool enable)
4409 {
4410 	if (qdf_log_dump_at_kernel_enable == enable) {
4411 		QDF_TRACE_INFO(QDF_MODULE_ID_QDF,
4412 			       "qdf_log_dump_at_kernel_enable is already %d\n",
4413 			       enable);
4414 	}
4415 	qdf_log_dump_at_kernel_enable = enable;
4416 }
4417 
4418 qdf_export_symbol(qdf_log_dump_at_kernel_level);
4419 
4420 bool qdf_print_is_category_enabled(unsigned int idx, QDF_MODULE_ID category)
4421 {
4422 	QDF_TRACE_LEVEL verbose_mask;
4423 
4424 	/* Check if index passed is valid */
4425 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4426 		pr_info("%s: Invalid index - %d\n", __func__, idx);
4427 		return false;
4428 	}
4429 
4430 	/* Check if print control object is in use */
4431 	if (!print_ctrl_obj[idx].in_use) {
4432 		pr_info("%s: Invalid print control object\n", __func__);
4433 		return false;
4434 	}
4435 
4436 	/* Check if category passed is valid */
4437 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
4438 		pr_info("%s: Invalid category: %d\n", __func__, category);
4439 		return false;
4440 	}
4441 
4442 	verbose_mask =
4443 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask;
4444 
4445 	if (verbose_mask == QDF_TRACE_LEVEL_NONE)
4446 		return false;
4447 	else
4448 		return true;
4449 }
4450 qdf_export_symbol(qdf_print_is_category_enabled);
4451 
4452 bool qdf_print_is_verbose_enabled(unsigned int idx, QDF_MODULE_ID category,
4453 				  QDF_TRACE_LEVEL verbose)
4454 {
4455 	bool verbose_enabled = false;
4456 
4457 	/* Check if index passed is valid */
4458 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4459 		pr_info("%s: Invalid index - %d\n", __func__, idx);
4460 		return verbose_enabled;
4461 	}
4462 
4463 	/* Check if print control object is in use */
4464 	if (!print_ctrl_obj[idx].in_use) {
4465 		pr_info("%s: Invalid print control object\n", __func__);
4466 		return verbose_enabled;
4467 	}
4468 
4469 	/* Check if category passed is valid */
4470 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
4471 		pr_info("%s: Invalid category: %d\n", __func__, category);
4472 		return verbose_enabled;
4473 	}
4474 
4475 	if ((verbose == QDF_TRACE_LEVEL_NONE) ||
4476 	    (verbose >= QDF_TRACE_LEVEL_MAX)) {
4477 		verbose_enabled = false;
4478 	} else if (verbose == QDF_TRACE_LEVEL_ALL) {
4479 		if (print_ctrl_obj[idx].cat_info[category]
4480 					.category_verbose_mask == 0xFFFF)
4481 			verbose_enabled = true;
4482 	} else {
4483 		verbose_enabled =
4484 		(print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
4485 		 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) ? true : false;
4486 	}
4487 
4488 	return verbose_enabled;
4489 }
4490 qdf_export_symbol(qdf_print_is_verbose_enabled);
4491 
4492 #ifdef DBG_LVL_MAC_FILTERING
4493 
4494 QDF_STATUS qdf_print_set_node_flag(unsigned int idx, uint8_t enable)
4495 {
4496 	/* Check if index passed is valid */
4497 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4498 		pr_info("%s: Invalid index - %d\n", __func__, idx);
4499 		return QDF_STATUS_E_FAILURE;
4500 	}
4501 
4502 	/* Check if print control object is in use */
4503 	if (!print_ctrl_obj[idx].in_use) {
4504 		pr_info("%s: Invalid print control object\n", __func__);
4505 		return QDF_STATUS_E_FAILURE;
4506 	}
4507 
4508 	if (enable > 1) {
4509 		pr_info("%s: Incorrect input: Use 1 or 0 to enable or disable\n",
4510 			__func__);
4511 		return QDF_STATUS_E_FAILURE;
4512 	}
4513 
4514 	print_ctrl_obj[idx].dbglvlmac_on = enable;
4515 	pr_info("%s: DbgLVLmac feature %s\n",
4516 		__func__,
4517 		((enable) ? "enabled" : "disabled"));
4518 
4519 	return QDF_STATUS_SUCCESS;
4520 }
4521 qdf_export_symbol(qdf_print_set_node_flag);
4522 
4523 bool qdf_print_get_node_flag(unsigned int idx)
4524 {
4525 	bool node_flag = false;
4526 
4527 	/* Check if index passed is valid */
4528 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4529 		pr_info("%s: Invalid index - %d\n", __func__, idx);
4530 		return node_flag;
4531 	}
4532 
4533 	/* Check if print control object is in use */
4534 	if (!print_ctrl_obj[idx].in_use) {
4535 		pr_info("%s: Invalid print control object\n", __func__);
4536 		return node_flag;
4537 	}
4538 
4539 	if (print_ctrl_obj[idx].dbglvlmac_on)
4540 		node_flag = true;
4541 
4542 	return node_flag;
4543 }
4544 qdf_export_symbol(qdf_print_get_node_flag);
4545 
4546 void qdf_print_clean_node_flag(unsigned int idx)
4547 {
4548 	/* Disable dbglvlmac_on during cleanup */
4549 	print_ctrl_obj[idx].dbglvlmac_on = 0;
4550 }
4551 
4552 #else
4553 
4554 void qdf_print_clean_node_flag(unsigned int idx)
4555 {
4556 	/* No operation in case of no support for DBG_LVL_MAC_FILTERING */
4557 	return;
4558 }
4559 #endif
4560 
4561 void QDF_PRINT_INFO(unsigned int idx, QDF_MODULE_ID module,
4562 		    QDF_TRACE_LEVEL level,
4563 		    char *str_format, ...)
4564 {
4565 	va_list args;
4566 
4567 	/* Generic wrapper API will compile qdf_vprint in order to
4568 	 * log the message. Once QDF converged debug framework is in
4569 	 * place, this will be changed to adapt to the framework, compiling
4570 	 * call to converged tracing API
4571 	 */
4572 	va_start(args, str_format);
4573 	qdf_vprint(str_format, args);
4574 	va_end(args);
4575 }
4576 qdf_export_symbol(QDF_PRINT_INFO);
4577 
4578 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4579 void qdf_logging_init(void)
4580 {
4581 	wlan_logging_sock_init_svc();
4582 	nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY);
4583 	wlan_logging_notifier_init(qdf_log_dump_at_kernel_enable);
4584 	wlan_logging_set_flush_timer(qdf_log_flush_timer_period);
4585 }
4586 
4587 void qdf_logging_exit(void)
4588 {
4589 	wlan_logging_notifier_deinit(qdf_log_dump_at_kernel_enable);
4590 	nl_srv_exit();
4591 	wlan_logging_sock_deinit_svc();
4592 }
4593 
4594 int qdf_logging_set_flush_timer(uint32_t milliseconds)
4595 {
4596 	if (wlan_logging_set_flush_timer(milliseconds) == 0)
4597 		return QDF_STATUS_SUCCESS;
4598 	else
4599 		return QDF_STATUS_E_FAILURE;
4600 }
4601 
4602 void qdf_logging_flush_logs(void)
4603 {
4604 	wlan_flush_host_logs_for_fatal();
4605 }
4606 
4607 #else
4608 void qdf_logging_init(void)
4609 {
4610 	nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY);
4611 }
4612 
4613 void qdf_logging_exit(void)
4614 {
4615 	nl_srv_exit();
4616 }
4617 
4618 int qdf_logging_set_flush_timer(uint32_t milliseconds)
4619 {
4620 	return QDF_STATUS_E_FAILURE;
4621 }
4622 
4623 void qdf_logging_flush_logs(void)
4624 {
4625 }
4626 #endif
4627 
4628 qdf_export_symbol(qdf_logging_set_flush_timer);
4629 qdf_export_symbol(qdf_logging_flush_logs);
4630 
4631 #ifdef CONFIG_KALLSYMS
4632 inline int qdf_sprint_symbol(char *buffer, void *addr)
4633 {
4634 	return sprint_symbol(buffer, (unsigned long)addr);
4635 }
4636 #else
4637 int qdf_sprint_symbol(char *buffer, void *addr)
4638 {
4639 	if (!buffer)
4640 		return 0;
4641 
4642 	buffer[0] = '\0';
4643 	return 1;
4644 }
4645 #endif
4646 qdf_export_symbol(qdf_sprint_symbol);
4647 
4648 void qdf_set_pidx(int pidx)
4649 {
4650 	qdf_pidx = pidx;
4651 }
4652 qdf_export_symbol(qdf_set_pidx);
4653 
4654 int qdf_get_pidx(void)
4655 {
4656 	return qdf_pidx;
4657 }
4658 qdf_export_symbol(qdf_get_pidx);
4659 
4660 #ifdef PANIC_ON_BUG
4661 #ifdef CONFIG_SLUB_DEBUG
4662 void __qdf_bug(void)
4663 {
4664 	BUG();
4665 }
4666 qdf_export_symbol(__qdf_bug);
4667 #endif /* CONFIG_SLUB_DEBUG */
4668 #endif /* PANIC_ON_BUG */
4669 
4670 #ifdef WLAN_QCOM_VA_MINIDUMP
4671 static bool qdf_va_md_initialized;
4672 static qdf_list_t qdf_va_md_list;
4673 static qdf_spinlock_t qdf_va_md_list_lock;
4674 #define QDF_MINIDUMP_LIST_SIZE 128
4675 
4676 struct qdf_va_md_entry {
4677 	qdf_list_node_t node;
4678 	struct va_md_entry data;
4679 };
4680 
4681 static int qdf_va_md_notif_handler(struct notifier_block *this,
4682 				   unsigned long event, void *ptr)
4683 {
4684 	struct qdf_va_md_entry *entry;
4685 	struct qdf_va_md_entry *next;
4686 
4687 	qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4688 	qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) {
4689 		qcom_va_md_add_region(&entry->data);
4690 	}
4691 
4692 	qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4693 	return NOTIFY_OK;
4694 }
4695 
4696 static struct notifier_block qdf_va_md_notif_blk = {
4697 	.notifier_call = qdf_va_md_notif_handler,
4698 	.priority = INT_MAX,
4699 };
4700 
4701 void __qdf_minidump_init(void)
4702 {
4703 	int ret;
4704 
4705 	if (qdf_va_md_initialized)
4706 		return;
4707 
4708 	qdf_spinlock_create(&qdf_va_md_list_lock);
4709 	qdf_list_create(&qdf_va_md_list, QDF_MINIDUMP_LIST_SIZE);
4710 	ret = qcom_va_md_register(qdf_trace_wlan_modname(),
4711 				  &qdf_va_md_notif_blk);
4712 	qdf_va_md_initialized = !ret;
4713 }
4714 
4715 qdf_export_symbol(__qdf_minidump_init);
4716 
4717 void __qdf_minidump_deinit(void)
4718 {
4719 	struct qdf_va_md_entry *entry;
4720 	struct qdf_va_md_entry *next;
4721 
4722 	if (!qdf_va_md_initialized)
4723 		return;
4724 
4725 	qdf_va_md_initialized = false;
4726 	qcom_va_md_unregister(qdf_trace_wlan_modname(),
4727 			      &qdf_va_md_notif_blk);
4728 	qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4729 	qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) {
4730 		qdf_list_remove_node(&qdf_va_md_list, &entry->node);
4731 		qdf_mem_free(entry);
4732 	}
4733 
4734 	qdf_list_destroy(&qdf_va_md_list);
4735 	qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4736 	qdf_spinlock_destroy(&qdf_va_md_list_lock);
4737 }
4738 
4739 qdf_export_symbol(__qdf_minidump_deinit);
4740 
4741 void __qdf_minidump_log(void *start_addr, size_t size, const char *name)
4742 {
4743 	struct qdf_va_md_entry *entry;
4744 	QDF_STATUS status;
4745 
4746 	if (!qdf_va_md_initialized)
4747 		return;
4748 
4749 	entry = qdf_mem_malloc(sizeof(*entry));
4750 	if (!entry) {
4751 		qdf_err("malloc failed for %s: %pK, %zu",
4752 			name, start_addr, size);
4753 		return;
4754 	}
4755 
4756 	qdf_str_lcopy(entry->data.owner, name, sizeof(entry->data.owner));
4757 	entry->data.vaddr = (unsigned long)start_addr;
4758 	entry->data.size = size;
4759 
4760 	qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4761 	status = qdf_list_insert_front(&qdf_va_md_list, &entry->node);
4762 	qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4763 	if (QDF_IS_STATUS_ERROR(status)) {
4764 		qdf_err("Failed to insert qdf va md entry, status %d", status);
4765 		qdf_mem_free(entry);
4766 	}
4767 }
4768 
4769 qdf_export_symbol(__qdf_minidump_log);
4770 
4771 void __qdf_minidump_remove(void *addr, size_t size, const char *name)
4772 {
4773 	struct qdf_va_md_entry *entry;
4774 	struct qdf_va_md_entry *next;
4775 
4776 	if (!qdf_va_md_initialized)
4777 		return;
4778 
4779 	qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4780 	qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) {
4781 		if (entry->data.vaddr == (unsigned long)addr &&
4782 		    entry->data.size == size &&
4783 		    !qdf_str_cmp(entry->data.owner, name)) {
4784 			qdf_list_remove_node(&qdf_va_md_list, &entry->node);
4785 			qdf_mem_free(entry);
4786 			break;
4787 		}
4788 	}
4789 
4790 	qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4791 }
4792 
4793 qdf_export_symbol(__qdf_minidump_remove);
4794 #endif
4795