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