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