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