xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/qdf_trace.c (revision a86b23ee68a2491aede2e03991f3fb37046f4e41)
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, uint8_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(file, "DPT: %04d: %s %s\n",
2856 				i, p_record.time,
2857 				qdf_dp_code_to_string(p_record.code));
2858 			qdf_debugfs_printf(file, "%s: HDD TX Timeout\n");
2859 			break;
2860 
2861 		case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
2862 			qdf_debugfs_printf(file, "%04d: %s %s\n",
2863 				i, p_record.time,
2864 				qdf_dp_code_to_string(p_record.code));
2865 			qdf_debugfs_printf(file,
2866 					   "%s: HDD  SoftAP TX Timeout\n");
2867 			break;
2868 
2869 		case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
2870 			qdf_debugfs_printf(file, "DPT: %04d: %s %s\n",
2871 				i, p_record.time,
2872 				qdf_dp_code_to_string(p_record.code));
2873 			qdf_debugfs_printf(file,
2874 					   "%s: CE Fast Packet Error\n");
2875 			break;
2876 
2877 		case QDF_DP_TRACE_MAX:
2878 			qdf_debugfs_printf(file,
2879 				"%s: QDF_DP_TRACE_MAX event should not be generated\n",
2880 				__func__);
2881 			break;
2882 
2883 		case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
2884 		case QDF_DP_TRACE_HDD_RX_PACKET_RECORD:
2885 		case QDF_DP_TRACE_TX_PACKET_RECORD:
2886 		case QDF_DP_TRACE_RX_PACKET_RECORD:
2887 		case QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD:
2888 		case QDF_DP_TRACE_LI_DP_RX_PACKET_RECORD:
2889 
2890 		default:
2891 			qdf_dpt_display_record_debugfs(file, &p_record, i);
2892 			break;
2893 		}
2894 
2895 		if (++g_qdf_dp_trace_data.dump_counter == num_records_to_dump)
2896 			break;
2897 
2898 		spin_lock_bh(&l_dp_trace_lock);
2899 		if (i == 0)
2900 			i = MAX_QDF_DP_TRACE_RECORDS;
2901 
2902 		i -= 1;
2903 		p_record = g_qdf_dp_trace_tbl[i];
2904 		spin_unlock_bh(&l_dp_trace_lock);
2905 	}
2906 
2907 	g_qdf_dp_trace_data.dump_counter = 0;
2908 
2909 	return QDF_STATUS_SUCCESS;
2910 }
2911 qdf_export_symbol(qdf_dpt_dump_stats_debugfs);
2912 
2913 /**
2914  * qdf_dpt_set_value_debugfs() - Configure the value to control DP trace
2915  * @proto_bitmap: defines the protocol to be tracked
2916  * @no_of_records: defines the nth packet which is traced
2917  * @verbosity: defines the verbosity level
2918  *
2919  * Return: None
2920  */
2921 void qdf_dpt_set_value_debugfs(uint8_t proto_bitmap, uint8_t no_of_record,
2922 			    uint8_t verbosity, uint16_t num_records_to_dump)
2923 {
2924 	if (g_qdf_dp_trace_data.enable) {
2925 		g_qdf_dp_trace_data.proto_bitmap = proto_bitmap;
2926 		g_qdf_dp_trace_data.no_of_record = no_of_record;
2927 		g_qdf_dp_trace_data.verbosity    = verbosity;
2928 		g_qdf_dp_trace_data.num_records_to_dump = num_records_to_dump;
2929 	}
2930 }
2931 qdf_export_symbol(qdf_dpt_set_value_debugfs);
2932 
2933 
2934 /**
2935  * qdf_dp_trace_dump_all() - Dump data from ring buffer via call back functions
2936  * registered with QDF
2937  * @count: Number of lines to dump starting from tail to head
2938  * @pdev_id: pdev_id
2939  *
2940  * Return: None
2941  */
2942 void qdf_dp_trace_dump_all(uint32_t count, uint8_t pdev_id)
2943 {
2944 	struct qdf_dp_trace_record_s p_record;
2945 	int32_t i, tail;
2946 
2947 	if (!g_qdf_dp_trace_data.enable) {
2948 		DPTRACE_PRINT("Tracing Disabled");
2949 		return;
2950 	}
2951 
2952 	DPTRACE_PRINT(
2953 		"DPT: config - bitmap 0x%x verb %u #rec %u live_config %u thresh %u time_limit %u",
2954 		g_qdf_dp_trace_data.proto_bitmap,
2955 		g_qdf_dp_trace_data.verbosity,
2956 		g_qdf_dp_trace_data.no_of_record,
2957 		g_qdf_dp_trace_data.live_mode_config,
2958 		g_qdf_dp_trace_data.high_tput_thresh,
2959 		g_qdf_dp_trace_data.thresh_time_limit);
2960 
2961 	qdf_dp_trace_dump_stats();
2962 
2963 	DPTRACE_PRINT("DPT: Total Records: %d, Head: %d, Tail: %d",
2964 		      g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head,
2965 		      g_qdf_dp_trace_data.tail);
2966 
2967 	/* aquire the lock so that only one thread at a time can read
2968 	 * the ring buffer
2969 	 */
2970 	spin_lock_bh(&l_dp_trace_lock);
2971 
2972 	if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) {
2973 		i = g_qdf_dp_trace_data.head;
2974 		tail = g_qdf_dp_trace_data.tail;
2975 
2976 		if (count) {
2977 			if (count > g_qdf_dp_trace_data.num)
2978 				count = g_qdf_dp_trace_data.num;
2979 			if (tail >= (count - 1))
2980 				i = tail - count + 1;
2981 			else if (count != MAX_QDF_DP_TRACE_RECORDS)
2982 				i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) -
2983 							     tail);
2984 		}
2985 
2986 		p_record = g_qdf_dp_trace_tbl[i];
2987 		spin_unlock_bh(&l_dp_trace_lock);
2988 		for (;; ) {
2989 			qdf_dp_trace_cb_table[p_record.code](&p_record,
2990 							(uint16_t)i, pdev_id, false);
2991 			if (i == tail)
2992 				break;
2993 			i += 1;
2994 
2995 			spin_lock_bh(&l_dp_trace_lock);
2996 			if (MAX_QDF_DP_TRACE_RECORDS == i)
2997 				i = 0;
2998 
2999 			p_record = g_qdf_dp_trace_tbl[i];
3000 			spin_unlock_bh(&l_dp_trace_lock);
3001 		}
3002 	} else {
3003 		spin_unlock_bh(&l_dp_trace_lock);
3004 	}
3005 }
3006 qdf_export_symbol(qdf_dp_trace_dump_all);
3007 
3008 /**
3009  * qdf_dp_trace_throttle_live_mode() - Throttle DP Trace live mode
3010  * @high_bw_request: whether this is a high BW req or not
3011  *
3012  * The function tries to prevent excessive logging into the live buffer by
3013  * having an upper limit on number of packets that can be logged per second.
3014  *
3015  * The intention is to allow occasional pings and data packets and really low
3016  * throughput levels while suppressing bursts and higher throughput levels so
3017  * that we donot hog the live buffer.
3018  *
3019  * If the number of packets printed in a particular second exceeds the thresh,
3020  * disable printing in the next second.
3021  *
3022  * Return: None
3023  */
3024 void qdf_dp_trace_throttle_live_mode(bool high_bw_request)
3025 {
3026 	static int bw_interval_counter;
3027 
3028 	if (g_qdf_dp_trace_data.enable == false ||
3029 		g_qdf_dp_trace_data.live_mode_config == false)
3030 		return;
3031 
3032 	if (high_bw_request) {
3033 		g_qdf_dp_trace_data.live_mode = 0;
3034 		bw_interval_counter = 0;
3035 		return;
3036 	}
3037 
3038 	bw_interval_counter++;
3039 
3040 	if (0 == (bw_interval_counter %
3041 			g_qdf_dp_trace_data.thresh_time_limit)) {
3042 
3043 		spin_lock_bh(&l_dp_trace_lock);
3044 			if (g_qdf_dp_trace_data.print_pkt_cnt <=
3045 				g_qdf_dp_trace_data.high_tput_thresh)
3046 				g_qdf_dp_trace_data.live_mode = 1;
3047 
3048 		g_qdf_dp_trace_data.print_pkt_cnt = 0;
3049 		spin_unlock_bh(&l_dp_trace_lock);
3050 	}
3051 }
3052 qdf_export_symbol(qdf_dp_trace_throttle_live_mode);
3053 
3054 void qdf_dp_trace_apply_tput_policy(bool is_data_traffic)
3055 {
3056 	if (g_qdf_dp_trace_data.dynamic_verbosity_modify) {
3057 		goto check_live_mode;
3058 		return;
3059 	}
3060 
3061 	if (is_data_traffic) {
3062 		g_qdf_dp_trace_data.verbosity =
3063 					QDF_DP_TRACE_VERBOSITY_ULTRA_LOW;
3064 	} else {
3065 		g_qdf_dp_trace_data.verbosity =
3066 					g_qdf_dp_trace_data.ini_conf_verbosity;
3067 	}
3068 check_live_mode:
3069 	qdf_dp_trace_throttle_live_mode(is_data_traffic);
3070 }
3071 #endif
3072 
3073 struct qdf_print_ctrl print_ctrl_obj[MAX_PRINT_CONFIG_SUPPORTED];
3074 
3075 struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = {
3076 	[QDF_MODULE_ID_TDLS] = {"tdls"},
3077 	[QDF_MODULE_ID_ACS] = {"ACS"},
3078 	[QDF_MODULE_ID_SCAN_SM] = {"scan state machine"},
3079 	[QDF_MODULE_ID_SCANENTRY] = {"scan entry"},
3080 	[QDF_MODULE_ID_WDS] = {"WDS"},
3081 	[QDF_MODULE_ID_ACTION] = {"action"},
3082 	[QDF_MODULE_ID_ROAM] = {"STA roaming"},
3083 	[QDF_MODULE_ID_INACT] = {"inactivity"},
3084 	[QDF_MODULE_ID_DOTH] = {"11h"},
3085 	[QDF_MODULE_ID_IQUE] = {"IQUE"},
3086 	[QDF_MODULE_ID_WME] = {"WME"},
3087 	[QDF_MODULE_ID_ACL] = {"ACL"},
3088 	[QDF_MODULE_ID_WPA] = {"WPA/RSN"},
3089 	[QDF_MODULE_ID_RADKEYS] = {"dump 802.1x keys"},
3090 	[QDF_MODULE_ID_RADDUMP] = {"dump radius packet"},
3091 	[QDF_MODULE_ID_RADIUS] = {"802.1x radius client"},
3092 	[QDF_MODULE_ID_DOT1XSM] = {"802.1x state machine"},
3093 	[QDF_MODULE_ID_DOT1X] = {"802.1x authenticator"},
3094 	[QDF_MODULE_ID_POWER] = {"power save"},
3095 	[QDF_MODULE_ID_STATE] = {"state"},
3096 	[QDF_MODULE_ID_OUTPUT] = {"output"},
3097 	[QDF_MODULE_ID_SCAN] = {"scan"},
3098 	[QDF_MODULE_ID_AUTH] = {"authentication"},
3099 	[QDF_MODULE_ID_ASSOC] = {"association"},
3100 	[QDF_MODULE_ID_NODE] = {"node"},
3101 	[QDF_MODULE_ID_ELEMID] = {"element ID"},
3102 	[QDF_MODULE_ID_XRATE] = {"rate"},
3103 	[QDF_MODULE_ID_INPUT] = {"input"},
3104 	[QDF_MODULE_ID_CRYPTO] = {"crypto"},
3105 	[QDF_MODULE_ID_DUMPPKTS] = {"dump packet"},
3106 	[QDF_MODULE_ID_DEBUG] = {"debug"},
3107 	[QDF_MODULE_ID_MLME] = {"mlme"},
3108 	[QDF_MODULE_ID_RRM] = {"rrm"},
3109 	[QDF_MODULE_ID_WNM] = {"wnm"},
3110 	[QDF_MODULE_ID_P2P_PROT] = {"p2p_prot"},
3111 	[QDF_MODULE_ID_PROXYARP] = {"proxyarp"},
3112 	[QDF_MODULE_ID_L2TIF] = {"l2tif"},
3113 	[QDF_MODULE_ID_WIFIPOS] = {"wifipos"},
3114 	[QDF_MODULE_ID_WRAP] = {"wrap"},
3115 	[QDF_MODULE_ID_DFS] = {"dfs"},
3116 	[QDF_MODULE_ID_ATF] = {"atf"},
3117 	[QDF_MODULE_ID_SPLITMAC] = {"splitmac"},
3118 	[QDF_MODULE_ID_IOCTL] = {"ioctl"},
3119 	[QDF_MODULE_ID_NAC] = {"nac"},
3120 	[QDF_MODULE_ID_MESH] = {"mesh"},
3121 	[QDF_MODULE_ID_MBO] = {"mbo"},
3122 	[QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = {"extchanswitch"},
3123 	[QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = {"extchanscan"},
3124 	[QDF_MODULE_ID_TLSHIM] = {"tlshim"},
3125 	[QDF_MODULE_ID_WMI] = {"WMI"},
3126 	[QDF_MODULE_ID_HTT] = {"HTT"},
3127 	[QDF_MODULE_ID_HDD] = {"HDD"},
3128 	[QDF_MODULE_ID_SME] = {"SME"},
3129 	[QDF_MODULE_ID_PE] = {"PE"},
3130 	[QDF_MODULE_ID_WMA] = {"WMA"},
3131 	[QDF_MODULE_ID_SYS] = {"SYS"},
3132 	[QDF_MODULE_ID_QDF] = {"QDF"},
3133 	[QDF_MODULE_ID_SAP] = {"SAP"},
3134 	[QDF_MODULE_ID_HDD_SOFTAP] = {"HDD_SAP"},
3135 	[QDF_MODULE_ID_HDD_DATA] = {"DATA"},
3136 	[QDF_MODULE_ID_HDD_SAP_DATA] = {"SAP_DATA"},
3137 	[QDF_MODULE_ID_HIF] = {"HIF"},
3138 	[QDF_MODULE_ID_HTC] = {"HTC"},
3139 	[QDF_MODULE_ID_TXRX] = {"TXRX"},
3140 	[QDF_MODULE_ID_QDF_DEVICE] = {"QDF_DEV"},
3141 	[QDF_MODULE_ID_CFG] = {"CFG"},
3142 	[QDF_MODULE_ID_BMI] = {"BMI"},
3143 	[QDF_MODULE_ID_EPPING] = {"EPPING"},
3144 	[QDF_MODULE_ID_QVIT] = {"QVIT"},
3145 	[QDF_MODULE_ID_DP] = {"DP"},
3146 	[QDF_MODULE_ID_HAL] = {"HAL"},
3147 	[QDF_MODULE_ID_SOC] = {"SOC"},
3148 	[QDF_MODULE_ID_OS_IF] = {"OSIF"},
3149 	[QDF_MODULE_ID_TARGET_IF] = {"TIF"},
3150 	[QDF_MODULE_ID_SCHEDULER] = {"SCH"},
3151 	[QDF_MODULE_ID_MGMT_TXRX] = {"MGMT_TXRX"},
3152 	[QDF_MODULE_ID_PMO] = {"PMO"},
3153 	[QDF_MODULE_ID_POLICY_MGR] = {"POLICY_MGR"},
3154 	[QDF_MODULE_ID_SA_API] = {"SA_API"},
3155 	[QDF_MODULE_ID_NAN] = {"NAN"},
3156 	[QDF_MODULE_ID_SPECTRAL] = {"SPECTRAL"},
3157 	[QDF_MODULE_ID_P2P] = {"P2P"},
3158 	[QDF_MODULE_ID_OFFCHAN_TXRX] = {"OFFCHAN"},
3159 	[QDF_MODULE_ID_REGULATORY] = {"REGULATORY"},
3160 	[QDF_MODULE_ID_OBJ_MGR] = {"OBJMGR"},
3161 	[QDF_MODULE_ID_SERIALIZATION] = {"SER"},
3162 	[QDF_MODULE_ID_NSS] = {"NSS"},
3163 	[QDF_MODULE_ID_ROAM_DEBUG] = {"roam debug"},
3164 	[QDF_MODULE_ID_DIRECT_BUF_RX] = {"DIRECT_BUF_RX"},
3165 	[QDF_MODULE_ID_DISA] = {"disa"},
3166 	[QDF_MODULE_ID_GREEN_AP] = {"GREEN_AP"},
3167 	[QDF_MODULE_ID_EXTAP] = {"EXTAP"},
3168 	[QDF_MODULE_ID_FD] = {"FILS discovery"},
3169 	[QDF_MODULE_ID_FTM] = {"FTM"},
3170 	[QDF_MODULE_ID_OCB] = {"OCB"},
3171 	[QDF_MODULE_ID_CONFIG] = {"CONFIG"},
3172 	[QDF_MODULE_ID_IPA] = {"IPA"},
3173 	[QDF_MODULE_ID_CP_STATS] = {"CP_STATS"},
3174 	[QDF_MODULE_ID_DCS] = {"DCS"},
3175 	[QDF_MODULE_ID_ACTION_OUI] = {"action_oui"},
3176 	[QDF_MODULE_ID_TARGET] = {"TARGET"},
3177 	[QDF_MODULE_ID_MBSSIE] = {"MBSSIE"},
3178 	[QDF_MODULE_ID_FWOL] = {"fwol"},
3179 	[QDF_MODULE_ID_SM_ENGINE] = {"SM_ENG"},
3180 	[QDF_MODULE_ID_CMN_MLME] = {"CMN_MLME"},
3181 	[QDF_MODULE_ID_BSSCOLOR] = {"BSSCOLOR"},
3182 	[QDF_MODULE_ID_CFR] = {"CFR"},
3183 	[QDF_MODULE_ID_TX_CAPTURE] = {"TX_CAPTURE_ENHANCE"},
3184 	[QDF_MODULE_ID_INTEROP_ISSUES_AP] = {"INTEROP_ISSUES_AP"},
3185 	[QDF_MODULE_ID_BLACKLIST_MGR] = {"blm"},
3186 	[QDF_MODULE_ID_QLD] = {"QLD"},
3187 	[QDF_MODULE_ID_DYNAMIC_MODE_CHG] = {"Dynamic Mode Change"},
3188 	[QDF_MODULE_ID_COEX] = {"COEX"},
3189 	[QDF_MODULE_ID_MON_FILTER] = {"Monitor Filter"},
3190 	[QDF_MODULE_ID_ANY] = {"ANY"},
3191 	[QDF_MODULE_ID_PKT_CAPTURE] = {"pkt_capture"},
3192 	[QDF_MODULE_ID_RPTR] = {"RPTR"},
3193 	[QDF_MODULE_ID_6GHZ] = {"6GHZ"},
3194 	[QDF_MODULE_ID_IOT_SIM] = {"IOT_SIM"},
3195 };
3196 qdf_export_symbol(g_qdf_category_name);
3197 
3198 /**
3199  * qdf_trace_display() - Display trace
3200  *
3201  * Return:  None
3202  */
3203 void qdf_trace_display(void)
3204 {
3205 	QDF_MODULE_ID module_id;
3206 
3207 	pr_err("     1)FATAL  2)ERROR  3)WARN  4)INFO  5)INFO_H  6)INFO_M  7)INFO_L 8)DEBUG\n");
3208 	for (module_id = 0; module_id < QDF_MODULE_ID_MAX; ++module_id) {
3209 		pr_err("%2d)%s    %s        %s       %s       %s        %s         %s         %s        %s\n",
3210 		       (int)module_id,
3211 		       g_qdf_category_name[module_id].category_name_str,
3212 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3213 			       QDF_TRACE_LEVEL_FATAL) ? "X" : " ",
3214 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3215 			       QDF_TRACE_LEVEL_ERROR) ? "X" : " ",
3216 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3217 			       QDF_TRACE_LEVEL_WARN) ? "X" : " ",
3218 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3219 			       QDF_TRACE_LEVEL_INFO) ? "X" : " ",
3220 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3221 			       QDF_TRACE_LEVEL_INFO_HIGH) ? "X" : " ",
3222 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3223 			       QDF_TRACE_LEVEL_INFO_MED) ? "X" : " ",
3224 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3225 			       QDF_TRACE_LEVEL_INFO_LOW) ? "X" : " ",
3226 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3227 			       QDF_TRACE_LEVEL_DEBUG) ? "X" : " ");
3228 	}
3229 }
3230 qdf_export_symbol(qdf_trace_display);
3231 
3232 #ifdef QDF_TRACE_PRINT_ENABLE
3233 static inline void print_to_console(char *str_buffer)
3234 {
3235 	pr_err("%s\n", str_buffer);
3236 }
3237 #else
3238 
3239 #define print_to_console(str)
3240 #endif
3241 
3242 #ifdef MULTI_IF_NAME
3243 static const char *qdf_trace_wlan_modname(void)
3244 {
3245 	return MULTI_IF_NAME;
3246 }
3247 #else
3248 static const char *qdf_trace_wlan_modname(void)
3249 {
3250 	return "wlan";
3251 }
3252 #endif
3253 
3254 void qdf_trace_msg_cmn(unsigned int idx,
3255 			QDF_MODULE_ID category,
3256 			QDF_TRACE_LEVEL verbose,
3257 			const char *str_format, va_list val)
3258 {
3259 	char str_buffer[QDF_TRACE_BUFFER_SIZE];
3260 	int n;
3261 
3262 	/* Check if index passed is valid */
3263 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3264 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3265 		return;
3266 	}
3267 
3268 	/* Check if print control object is in use */
3269 	if (!print_ctrl_obj[idx].in_use) {
3270 		pr_info("%s: Invalid print control object\n", __func__);
3271 		return;
3272 	}
3273 
3274 	/* Check if category passed is valid */
3275 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
3276 		pr_info("%s: Invalid category: %d\n", __func__, category);
3277 		return;
3278 	}
3279 
3280 	/* Check if verbose mask is valid */
3281 	if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
3282 		pr_info("%s: Invalid verbose level %d\n", __func__, verbose);
3283 		return;
3284 	}
3285 
3286 	/*
3287 	 * Print the trace message when the desired verbose level is set in
3288 	 * the desired category for the print control object
3289 	 */
3290 	if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
3291 	    QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
3292 		static const char * const VERBOSE_STR[] = {
3293 			[QDF_TRACE_LEVEL_NONE] = "",
3294 			[QDF_TRACE_LEVEL_FATAL] = "F",
3295 			[QDF_TRACE_LEVEL_ERROR] = "E",
3296 			[QDF_TRACE_LEVEL_WARN] = "W",
3297 			[QDF_TRACE_LEVEL_INFO] = "I",
3298 			[QDF_TRACE_LEVEL_INFO_HIGH] = "IH",
3299 			[QDF_TRACE_LEVEL_INFO_MED] = "IM",
3300 			[QDF_TRACE_LEVEL_INFO_LOW] = "IL",
3301 			[QDF_TRACE_LEVEL_DEBUG] = "D",
3302 			[QDF_TRACE_LEVEL_TRACE] = "T",
3303 			[QDF_TRACE_LEVEL_ALL] = "" };
3304 
3305 		/* print the prefix string into the string buffer... */
3306 		n = scnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE,
3307 			     "%s: [%d:%s:%s] ", qdf_trace_wlan_modname(),
3308 			     in_interrupt() ? 0 : current->pid,
3309 			     VERBOSE_STR[verbose],
3310 			     g_qdf_category_name[category].category_name_str);
3311 
3312 		/* print the formatted log message after the prefix string */
3313 		vscnprintf(str_buffer + n, QDF_TRACE_BUFFER_SIZE - n,
3314 			   str_format, val);
3315 #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE)
3316 		wlan_log_to_user(verbose, (char *)str_buffer,
3317 				 strlen(str_buffer));
3318 		if (qdf_unlikely(qdf_log_dump_at_kernel_enable))
3319 			print_to_console(str_buffer);
3320 #else
3321 		pr_err("%s\n", str_buffer);
3322 #endif
3323 	}
3324 }
3325 qdf_export_symbol(qdf_trace_msg_cmn);
3326 
3327 QDF_STATUS qdf_print_setup(void)
3328 {
3329 	int i;
3330 
3331 	/* Loop through all print ctrl objects */
3332 	for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
3333 		if (qdf_print_ctrl_cleanup(i))
3334 			return QDF_STATUS_E_FAILURE;
3335 	}
3336 	return QDF_STATUS_SUCCESS;
3337 }
3338 qdf_export_symbol(qdf_print_setup);
3339 
3340 QDF_STATUS qdf_print_ctrl_cleanup(unsigned int idx)
3341 {
3342 	int i = 0;
3343 
3344 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3345 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3346 		return QDF_STATUS_E_FAILURE;
3347 	}
3348 
3349 	/* Clean up the print control object corresponding to that index
3350 	 * If success, callee to change print control index to -1
3351 	 */
3352 
3353 	for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3354 		print_ctrl_obj[idx].cat_info[i].category_verbose_mask =
3355 							QDF_TRACE_LEVEL_NONE;
3356 	}
3357 	print_ctrl_obj[idx].custom_print = NULL;
3358 	print_ctrl_obj[idx].custom_ctxt = NULL;
3359 	qdf_print_clean_node_flag(idx);
3360 	print_ctrl_obj[idx].in_use = false;
3361 
3362 	return QDF_STATUS_SUCCESS;
3363 }
3364 qdf_export_symbol(qdf_print_ctrl_cleanup);
3365 
3366 int qdf_print_ctrl_register(const struct category_info *cinfo,
3367 			    void *custom_print_handler,
3368 			    void *custom_ctx,
3369 			    const char *pctrl_name)
3370 {
3371 	int idx = -1;
3372 	int i = 0;
3373 
3374 	for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
3375 		if (!print_ctrl_obj[i].in_use) {
3376 			idx = i;
3377 			break;
3378 		}
3379 	}
3380 
3381 	/* Callee to handle idx -1 appropriately */
3382 	if (idx == -1) {
3383 		pr_info("%s: Allocation failed! No print control object free\n",
3384 			__func__);
3385 		return idx;
3386 	}
3387 
3388 	print_ctrl_obj[idx].in_use = true;
3389 
3390 	/*
3391 	 * In case callee does not pass category info,
3392 	 * custom print handler, custom context and print control name,
3393 	 * we do not set any value here. Clean up for the print control
3394 	 * getting allocated would have taken care of initializing
3395 	 * default values.
3396 	 *
3397 	 * We need to only set in_use to 1 in such a case
3398 	 */
3399 
3400 	if (pctrl_name) {
3401 		qdf_str_lcopy(print_ctrl_obj[idx].name, pctrl_name,
3402 			      sizeof(print_ctrl_obj[idx].name));
3403 	}
3404 
3405 	if (custom_print_handler)
3406 		print_ctrl_obj[idx].custom_print = custom_print_handler;
3407 
3408 	if (custom_ctx)
3409 		print_ctrl_obj[idx].custom_ctxt = custom_ctx;
3410 
3411 	if (cinfo) {
3412 		for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3413 			if (cinfo[i].category_verbose_mask ==
3414 			    QDF_TRACE_LEVEL_ALL) {
3415 				print_ctrl_obj[idx].cat_info[i]
3416 				.category_verbose_mask = 0xFFFF;
3417 			} else if ((cinfo[i].category_verbose_mask ==
3418 				   QDF_TRACE_LEVEL_NONE) ||
3419 				   (cinfo[i].category_verbose_mask ==
3420 				   QDF_TRACE_LEVEL_TO_MODULE_BITMASK(
3421 				   QDF_TRACE_LEVEL_NONE))) {
3422 				print_ctrl_obj[idx].cat_info[i]
3423 				.category_verbose_mask = 0;
3424 			} else {
3425 				print_ctrl_obj[idx].cat_info[i]
3426 				.category_verbose_mask =
3427 				cinfo[i].category_verbose_mask;
3428 			}
3429 		}
3430 	}
3431 
3432 	return idx;
3433 }
3434 qdf_export_symbol(qdf_print_ctrl_register);
3435 
3436 #ifdef QDF_TRACE_PRINT_ENABLE
3437 void qdf_shared_print_ctrl_cleanup(void)
3438 {
3439 	qdf_print_ctrl_cleanup(qdf_pidx);
3440 }
3441 qdf_export_symbol(qdf_shared_print_ctrl_cleanup);
3442 
3443 /*
3444  * Set this to invalid value to differentiate with user-provided
3445  * value.
3446  */
3447 int qdf_dbg_mask = QDF_TRACE_LEVEL_MAX;
3448 qdf_export_symbol(qdf_dbg_mask);
3449 qdf_declare_param(qdf_dbg_mask, int);
3450 
3451 /*
3452  * QDF can be passed parameters which indicate the
3453  * debug level for each module.
3454  * an array of string values are passed, each string hold the following form
3455  *
3456  * <module name string>=<integer debug level value>
3457  *
3458  * The array qdf_dbg_arr will hold these module-string=value strings
3459  * The variable qdf_dbg_arr_cnt will have the count of how many such
3460  * string values were passed.
3461  */
3462 static char *qdf_dbg_arr[QDF_MODULE_ID_MAX];
3463 static int qdf_dbg_arr_cnt;
3464 qdf_declare_param_array(qdf_dbg_arr, charp, &qdf_dbg_arr_cnt);
3465 
3466 static uint16_t set_cumulative_verbose_mask(QDF_TRACE_LEVEL max_level)
3467 {
3468 	uint16_t category_verbose_mask = 0;
3469 	QDF_TRACE_LEVEL level;
3470 
3471 	for (level = QDF_TRACE_LEVEL_FATAL; level <= max_level; level++) {
3472 		category_verbose_mask |=
3473 			QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level);
3474 	}
3475 	return category_verbose_mask;
3476 }
3477 
3478 static QDF_MODULE_ID find_qdf_module_from_string(char *str)
3479 {
3480 	QDF_MODULE_ID mod_id;
3481 
3482 	for (mod_id = 0; mod_id < QDF_MODULE_ID_MAX; mod_id++) {
3483 		if (strcasecmp(str,
3484 				g_qdf_category_name[mod_id].category_name_str)
3485 				== 0) {
3486 			break;
3487 		}
3488 	}
3489 	return mod_id;
3490 }
3491 
3492 static void process_qdf_dbg_arr_param(struct category_info *cinfo,
3493 					int array_index)
3494 {
3495 	char *mod_val_str, *mod_str, *val_str;
3496 	unsigned long dbg_level;
3497 	QDF_MODULE_ID mod_id;
3498 
3499 	mod_val_str = qdf_dbg_arr[array_index];
3500 	mod_str = strsep(&mod_val_str, "=");
3501 	val_str = mod_val_str;
3502 	if (!val_str) {
3503 		pr_info("qdf_dbg_arr: %s not in the <mod>=<val> form\n",
3504 				mod_str);
3505 		return;
3506 	}
3507 
3508 	mod_id = find_qdf_module_from_string(mod_str);
3509 	if (mod_id >= QDF_MODULE_ID_MAX) {
3510 		pr_info("ERROR!!Module name %s not in the list of modules\n",
3511 				mod_str);
3512 		return;
3513 	}
3514 
3515 	if (kstrtol(val_str, 10, &dbg_level) < 0) {
3516 		pr_info("ERROR!!Invalid debug level for module: %s\n",
3517 				mod_str);
3518 		return;
3519 	}
3520 
3521 	if (dbg_level >= QDF_TRACE_LEVEL_MAX) {
3522 		pr_info("ERROR!!Debug level for %s too high", mod_str);
3523 		pr_info("max: %d given %lu\n", QDF_TRACE_LEVEL_MAX,
3524 				dbg_level);
3525 		return;
3526 	}
3527 
3528 	pr_info("User passed setting module %s(%d) to level %lu\n",
3529 			mod_str,
3530 			mod_id,
3531 			dbg_level);
3532 	cinfo[mod_id].category_verbose_mask =
3533 		set_cumulative_verbose_mask((QDF_TRACE_LEVEL)dbg_level);
3534 }
3535 
3536 static void set_default_trace_levels(struct category_info *cinfo)
3537 {
3538 	int i;
3539 	static QDF_TRACE_LEVEL module_trace_default_level[QDF_MODULE_ID_MAX] = {
3540 		[QDF_MODULE_ID_TDLS] = QDF_TRACE_LEVEL_NONE,
3541 		[QDF_MODULE_ID_ACS] = QDF_TRACE_LEVEL_NONE,
3542 		[QDF_MODULE_ID_SCAN_SM] = QDF_TRACE_LEVEL_NONE,
3543 		[QDF_MODULE_ID_SCANENTRY] = QDF_TRACE_LEVEL_NONE,
3544 		[QDF_MODULE_ID_WDS] = QDF_TRACE_LEVEL_NONE,
3545 		[QDF_MODULE_ID_ACTION] = QDF_TRACE_LEVEL_NONE,
3546 		[QDF_MODULE_ID_ROAM] = QDF_TRACE_LEVEL_NONE,
3547 		[QDF_MODULE_ID_INACT] = QDF_TRACE_LEVEL_NONE,
3548 		[QDF_MODULE_ID_DOTH] = QDF_TRACE_LEVEL_NONE,
3549 		[QDF_MODULE_ID_IQUE] = QDF_TRACE_LEVEL_NONE,
3550 		[QDF_MODULE_ID_WME] = QDF_TRACE_LEVEL_NONE,
3551 		[QDF_MODULE_ID_ACL] = QDF_TRACE_LEVEL_NONE,
3552 		[QDF_MODULE_ID_WPA] = QDF_TRACE_LEVEL_NONE,
3553 		[QDF_MODULE_ID_RADKEYS] = QDF_TRACE_LEVEL_NONE,
3554 		[QDF_MODULE_ID_RADDUMP] = QDF_TRACE_LEVEL_NONE,
3555 		[QDF_MODULE_ID_RADIUS] = QDF_TRACE_LEVEL_NONE,
3556 		[QDF_MODULE_ID_DOT1XSM] = QDF_TRACE_LEVEL_NONE,
3557 		[QDF_MODULE_ID_DOT1X] = QDF_TRACE_LEVEL_NONE,
3558 		[QDF_MODULE_ID_POWER] = QDF_TRACE_LEVEL_NONE,
3559 		[QDF_MODULE_ID_STATE] = QDF_TRACE_LEVEL_NONE,
3560 		[QDF_MODULE_ID_OUTPUT] = QDF_TRACE_LEVEL_NONE,
3561 		[QDF_MODULE_ID_SCAN] = QDF_TRACE_LEVEL_ERROR,
3562 		[QDF_MODULE_ID_AUTH] = QDF_TRACE_LEVEL_NONE,
3563 		[QDF_MODULE_ID_ASSOC] = QDF_TRACE_LEVEL_NONE,
3564 		[QDF_MODULE_ID_NODE] = QDF_TRACE_LEVEL_NONE,
3565 		[QDF_MODULE_ID_ELEMID] = QDF_TRACE_LEVEL_NONE,
3566 		[QDF_MODULE_ID_XRATE] = QDF_TRACE_LEVEL_NONE,
3567 		[QDF_MODULE_ID_INPUT] = QDF_TRACE_LEVEL_NONE,
3568 		[QDF_MODULE_ID_CRYPTO] = QDF_TRACE_LEVEL_NONE,
3569 		[QDF_MODULE_ID_DUMPPKTS] = QDF_TRACE_LEVEL_NONE,
3570 		[QDF_MODULE_ID_DEBUG] = QDF_TRACE_LEVEL_NONE,
3571 		[QDF_MODULE_ID_MLME] = QDF_TRACE_LEVEL_ERROR,
3572 		[QDF_MODULE_ID_RRM] = QDF_TRACE_LEVEL_NONE,
3573 		[QDF_MODULE_ID_WNM] = QDF_TRACE_LEVEL_NONE,
3574 		[QDF_MODULE_ID_P2P_PROT] = QDF_TRACE_LEVEL_NONE,
3575 		[QDF_MODULE_ID_PROXYARP] = QDF_TRACE_LEVEL_NONE,
3576 		[QDF_MODULE_ID_L2TIF] = QDF_TRACE_LEVEL_NONE,
3577 		[QDF_MODULE_ID_WIFIPOS] = QDF_TRACE_LEVEL_NONE,
3578 		[QDF_MODULE_ID_WRAP] = QDF_TRACE_LEVEL_NONE,
3579 		[QDF_MODULE_ID_DFS] = QDF_TRACE_LEVEL_NONE,
3580 		[QDF_MODULE_ID_ATF] = QDF_TRACE_LEVEL_ERROR,
3581 		[QDF_MODULE_ID_SPLITMAC] = QDF_TRACE_LEVEL_NONE,
3582 		[QDF_MODULE_ID_IOCTL] = QDF_TRACE_LEVEL_NONE,
3583 		[QDF_MODULE_ID_NAC] = QDF_TRACE_LEVEL_NONE,
3584 		[QDF_MODULE_ID_MESH] = QDF_TRACE_LEVEL_NONE,
3585 		[QDF_MODULE_ID_MBO] = QDF_TRACE_LEVEL_NONE,
3586 		[QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = QDF_TRACE_LEVEL_NONE,
3587 		[QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = QDF_TRACE_LEVEL_NONE,
3588 		[QDF_MODULE_ID_TLSHIM] = QDF_TRACE_LEVEL_NONE,
3589 		[QDF_MODULE_ID_WMI] = QDF_TRACE_LEVEL_ERROR,
3590 		[QDF_MODULE_ID_HTT] = QDF_TRACE_LEVEL_NONE,
3591 		[QDF_MODULE_ID_HDD] = QDF_TRACE_LEVEL_NONE,
3592 		[QDF_MODULE_ID_SME] = QDF_TRACE_LEVEL_NONE,
3593 		[QDF_MODULE_ID_PE] = QDF_TRACE_LEVEL_NONE,
3594 		[QDF_MODULE_ID_WMA] = QDF_TRACE_LEVEL_NONE,
3595 		[QDF_MODULE_ID_SYS] = QDF_TRACE_LEVEL_NONE,
3596 		[QDF_MODULE_ID_QDF] = QDF_TRACE_LEVEL_ERROR,
3597 		[QDF_MODULE_ID_SAP] = QDF_TRACE_LEVEL_NONE,
3598 		[QDF_MODULE_ID_HDD_SOFTAP] = QDF_TRACE_LEVEL_NONE,
3599 		[QDF_MODULE_ID_HDD_DATA] = QDF_TRACE_LEVEL_NONE,
3600 		[QDF_MODULE_ID_HDD_SAP_DATA] = QDF_TRACE_LEVEL_NONE,
3601 		[QDF_MODULE_ID_HIF] = QDF_TRACE_LEVEL_ERROR,
3602 		[QDF_MODULE_ID_HTC] = QDF_TRACE_LEVEL_NONE,
3603 		[QDF_MODULE_ID_TXRX] = QDF_TRACE_LEVEL_NONE,
3604 		[QDF_MODULE_ID_QDF_DEVICE] = QDF_TRACE_LEVEL_NONE,
3605 		[QDF_MODULE_ID_CFG] = QDF_TRACE_LEVEL_NONE,
3606 		[QDF_MODULE_ID_BMI] = QDF_TRACE_LEVEL_NONE,
3607 		[QDF_MODULE_ID_EPPING] = QDF_TRACE_LEVEL_NONE,
3608 		[QDF_MODULE_ID_QVIT] = QDF_TRACE_LEVEL_NONE,
3609 		[QDF_MODULE_ID_DP] = QDF_TRACE_LEVEL_FATAL,
3610 		[QDF_MODULE_ID_HAL] = QDF_TRACE_LEVEL_NONE,
3611 		[QDF_MODULE_ID_SOC] = QDF_TRACE_LEVEL_NONE,
3612 		[QDF_MODULE_ID_OS_IF] = QDF_TRACE_LEVEL_NONE,
3613 		[QDF_MODULE_ID_TARGET_IF] = QDF_TRACE_LEVEL_INFO,
3614 		[QDF_MODULE_ID_SCHEDULER] = QDF_TRACE_LEVEL_FATAL,
3615 		[QDF_MODULE_ID_MGMT_TXRX] = QDF_TRACE_LEVEL_NONE,
3616 		[QDF_MODULE_ID_SERIALIZATION] = QDF_TRACE_LEVEL_ERROR,
3617 		[QDF_MODULE_ID_PMO] = QDF_TRACE_LEVEL_NONE,
3618 		[QDF_MODULE_ID_P2P] = QDF_TRACE_LEVEL_NONE,
3619 		[QDF_MODULE_ID_POLICY_MGR] = QDF_TRACE_LEVEL_NONE,
3620 		[QDF_MODULE_ID_CONFIG] = QDF_TRACE_LEVEL_ERROR,
3621 		[QDF_MODULE_ID_REGULATORY] = QDF_TRACE_LEVEL_NONE,
3622 		[QDF_MODULE_ID_SA_API] = QDF_TRACE_LEVEL_NONE,
3623 		[QDF_MODULE_ID_NAN] = QDF_TRACE_LEVEL_NONE,
3624 		[QDF_MODULE_ID_OFFCHAN_TXRX] = QDF_TRACE_LEVEL_NONE,
3625 		[QDF_MODULE_ID_SON] = QDF_TRACE_LEVEL_NONE,
3626 		[QDF_MODULE_ID_SPECTRAL] = QDF_TRACE_LEVEL_ERROR,
3627 		[QDF_MODULE_ID_OBJ_MGR] = QDF_TRACE_LEVEL_FATAL,
3628 		[QDF_MODULE_ID_NSS] = QDF_TRACE_LEVEL_ERROR,
3629 		[QDF_MODULE_ID_ROAM_DEBUG] = QDF_TRACE_LEVEL_ERROR,
3630 		[QDF_MODULE_ID_CDP] = QDF_TRACE_LEVEL_NONE,
3631 		[QDF_MODULE_ID_DIRECT_BUF_RX] = QDF_TRACE_LEVEL_ERROR,
3632 		[QDF_MODULE_ID_DISA] = QDF_TRACE_LEVEL_NONE,
3633 		[QDF_MODULE_ID_GREEN_AP] = QDF_TRACE_LEVEL_ERROR,
3634 		[QDF_MODULE_ID_FTM] = QDF_TRACE_LEVEL_ERROR,
3635 		[QDF_MODULE_ID_EXTAP] = QDF_TRACE_LEVEL_NONE,
3636 		[QDF_MODULE_ID_FD] = QDF_TRACE_LEVEL_ERROR,
3637 		[QDF_MODULE_ID_OCB] = QDF_TRACE_LEVEL_ERROR,
3638 		[QDF_MODULE_ID_IPA] = QDF_TRACE_LEVEL_NONE,
3639 		[QDF_MODULE_ID_ACTION_OUI] = QDF_TRACE_LEVEL_NONE,
3640 		[QDF_MODULE_ID_CP_STATS] = QDF_TRACE_LEVEL_ERROR,
3641 		[QDF_MODULE_ID_DCS] = QDF_TRACE_LEVEL_ERROR,
3642 		[QDF_MODULE_ID_MBSSIE] = QDF_TRACE_LEVEL_INFO,
3643 		[QDF_MODULE_ID_FWOL] = QDF_TRACE_LEVEL_NONE,
3644 		[QDF_MODULE_ID_SM_ENGINE] = QDF_TRACE_LEVEL_ERROR,
3645 		[QDF_MODULE_ID_CMN_MLME] = QDF_TRACE_LEVEL_INFO,
3646 		[QDF_MODULE_ID_BSSCOLOR] = QDF_TRACE_LEVEL_ERROR,
3647 		[QDF_MODULE_ID_CFR] = QDF_TRACE_LEVEL_ERROR,
3648 		[QDF_MODULE_ID_TX_CAPTURE] = QDF_TRACE_LEVEL_FATAL,
3649 		[QDF_MODULE_ID_INTEROP_ISSUES_AP] = QDF_TRACE_LEVEL_NONE,
3650 		[QDF_MODULE_ID_BLACKLIST_MGR] = QDF_TRACE_LEVEL_NONE,
3651 		[QDF_MODULE_ID_QLD] = QDF_TRACE_LEVEL_ERROR,
3652 		[QDF_MODULE_ID_DYNAMIC_MODE_CHG] = QDF_TRACE_LEVEL_INFO,
3653 		[QDF_MODULE_ID_COEX] = QDF_TRACE_LEVEL_ERROR,
3654 		[QDF_MODULE_ID_MON_FILTER] = QDF_TRACE_LEVEL_INFO,
3655 		[QDF_MODULE_ID_ANY] = QDF_TRACE_LEVEL_INFO,
3656 		[QDF_MODULE_ID_PKT_CAPTURE] = QDF_TRACE_LEVEL_NONE,
3657 		[QDF_MODULE_ID_RPTR] = QDF_TRACE_LEVEL_INFO,
3658 		[QDF_MODULE_ID_6GHZ] = QDF_TRACE_LEVEL_ERROR,
3659 		[QDF_MODULE_ID_IOT_SIM] = QDF_TRACE_LEVEL_ERROR,
3660 	};
3661 
3662 	for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3663 		cinfo[i].category_verbose_mask = set_cumulative_verbose_mask(
3664 				module_trace_default_level[i]);
3665 	}
3666 }
3667 
3668 void qdf_shared_print_ctrl_init(void)
3669 {
3670 	int i;
3671 	struct category_info cinfo[MAX_SUPPORTED_CATEGORY];
3672 
3673 	set_default_trace_levels(cinfo);
3674 
3675 	/*
3676 	 * User specified across-module single debug level
3677 	 */
3678 	if ((qdf_dbg_mask >= 0) && (qdf_dbg_mask < QDF_TRACE_LEVEL_MAX)) {
3679 		pr_info("User specified module debug level of %d\n",
3680 			qdf_dbg_mask);
3681 		for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3682 			cinfo[i].category_verbose_mask =
3683 			set_cumulative_verbose_mask(qdf_dbg_mask);
3684 		}
3685 	} else if (qdf_dbg_mask != QDF_TRACE_LEVEL_MAX) {
3686 		pr_info("qdf_dbg_mask value is invalid\n");
3687 		pr_info("Using the default module debug levels instead\n");
3688 	}
3689 
3690 	/*
3691 	 * Module ID-Level specified as array during module load
3692 	 */
3693 	for (i = 0; i < qdf_dbg_arr_cnt; i++) {
3694 		process_qdf_dbg_arr_param(cinfo, i);
3695 	}
3696 	qdf_pidx = qdf_print_ctrl_register(cinfo, NULL, NULL,
3697 			"LOG_SHARED_OBJ");
3698 }
3699 qdf_export_symbol(qdf_shared_print_ctrl_init);
3700 #endif
3701 
3702 QDF_STATUS qdf_print_set_category_verbose(unsigned int idx,
3703 						QDF_MODULE_ID category,
3704 						QDF_TRACE_LEVEL verbose,
3705 						bool is_set)
3706 {
3707 	/* Check if index passed is valid */
3708 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3709 		pr_err("%s: Invalid index - %d\n", __func__, idx);
3710 		return QDF_STATUS_E_FAILURE;
3711 	}
3712 
3713 	/* Check if print control object is in use */
3714 	if (!print_ctrl_obj[idx].in_use) {
3715 		pr_err("%s: Invalid print control object\n", __func__);
3716 		return QDF_STATUS_E_FAILURE;
3717 	}
3718 
3719 	/* Check if category passed is valid */
3720 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
3721 		pr_err("%s: Invalid category: %d\n", __func__, category);
3722 		return QDF_STATUS_E_FAILURE;
3723 	}
3724 
3725 	/* Check if verbose mask is valid */
3726 	if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
3727 		pr_err("%s: Invalid verbose level %d\n", __func__, verbose);
3728 		return QDF_STATUS_E_FAILURE;
3729 	}
3730 
3731 	if (verbose == QDF_TRACE_LEVEL_ALL) {
3732 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
3733 				0xFFFF;
3734 		return QDF_STATUS_SUCCESS;
3735 	}
3736 
3737 	if (verbose == QDF_TRACE_LEVEL_NONE) {
3738 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
3739 				QDF_TRACE_LEVEL_NONE;
3740 		return QDF_STATUS_SUCCESS;
3741 	}
3742 
3743 	if (!is_set) {
3744 		if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask
3745 		    & QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
3746 			print_ctrl_obj[idx].cat_info[category]
3747 				.category_verbose_mask &=
3748 				~QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
3749 		}
3750 	} else {
3751 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask |=
3752 				QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
3753 	}
3754 
3755 	pr_debug("%s: Print control object %d, Category %d, Verbose level %d\n",
3756 		__func__,
3757 		idx,
3758 		category,
3759 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask);
3760 
3761 	return QDF_STATUS_SUCCESS;
3762 }
3763 qdf_export_symbol(qdf_print_set_category_verbose);
3764 
3765 void qdf_log_dump_at_kernel_level(bool enable)
3766 {
3767 	if (qdf_log_dump_at_kernel_enable == enable) {
3768 		QDF_TRACE_INFO(QDF_MODULE_ID_QDF,
3769 			       "qdf_log_dump_at_kernel_enable is already %d\n",
3770 			       enable);
3771 	}
3772 	qdf_log_dump_at_kernel_enable = enable;
3773 }
3774 
3775 qdf_export_symbol(qdf_log_dump_at_kernel_level);
3776 
3777 bool qdf_print_is_category_enabled(unsigned int idx, QDF_MODULE_ID category)
3778 {
3779 	QDF_TRACE_LEVEL verbose_mask;
3780 
3781 	/* Check if index passed is valid */
3782 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3783 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3784 		return false;
3785 	}
3786 
3787 	/* Check if print control object is in use */
3788 	if (!print_ctrl_obj[idx].in_use) {
3789 		pr_info("%s: Invalid print control object\n", __func__);
3790 		return false;
3791 	}
3792 
3793 	/* Check if category passed is valid */
3794 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
3795 		pr_info("%s: Invalid category: %d\n", __func__, category);
3796 		return false;
3797 	}
3798 
3799 	verbose_mask =
3800 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask;
3801 
3802 	if (verbose_mask == QDF_TRACE_LEVEL_NONE)
3803 		return false;
3804 	else
3805 		return true;
3806 }
3807 qdf_export_symbol(qdf_print_is_category_enabled);
3808 
3809 bool qdf_print_is_verbose_enabled(unsigned int idx, QDF_MODULE_ID category,
3810 				  QDF_TRACE_LEVEL verbose)
3811 {
3812 	bool verbose_enabled = false;
3813 
3814 	/* Check if index passed is valid */
3815 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3816 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3817 		return verbose_enabled;
3818 	}
3819 
3820 	/* Check if print control object is in use */
3821 	if (!print_ctrl_obj[idx].in_use) {
3822 		pr_info("%s: Invalid print control object\n", __func__);
3823 		return verbose_enabled;
3824 	}
3825 
3826 	/* Check if category passed is valid */
3827 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
3828 		pr_info("%s: Invalid category: %d\n", __func__, category);
3829 		return verbose_enabled;
3830 	}
3831 
3832 	if ((verbose == QDF_TRACE_LEVEL_NONE) ||
3833 	    (verbose >= QDF_TRACE_LEVEL_MAX)) {
3834 		verbose_enabled = false;
3835 	} else if (verbose == QDF_TRACE_LEVEL_ALL) {
3836 		if (print_ctrl_obj[idx].cat_info[category]
3837 					.category_verbose_mask == 0xFFFF)
3838 			verbose_enabled = true;
3839 	} else {
3840 		verbose_enabled =
3841 		(print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
3842 		 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) ? true : false;
3843 	}
3844 
3845 	return verbose_enabled;
3846 }
3847 qdf_export_symbol(qdf_print_is_verbose_enabled);
3848 
3849 #ifdef DBG_LVL_MAC_FILTERING
3850 
3851 QDF_STATUS qdf_print_set_node_flag(unsigned int idx, uint8_t enable)
3852 {
3853 	/* Check if index passed is valid */
3854 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3855 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3856 		return QDF_STATUS_E_FAILURE;
3857 	}
3858 
3859 	/* Check if print control object is in use */
3860 	if (!print_ctrl_obj[idx].in_use) {
3861 		pr_info("%s: Invalid print control object\n", __func__);
3862 		return QDF_STATUS_E_FAILURE;
3863 	}
3864 
3865 	if (enable > 1) {
3866 		pr_info("%s: Incorrect input: Use 1 or 0 to enable or disable\n",
3867 			__func__);
3868 		return QDF_STATUS_E_FAILURE;
3869 	}
3870 
3871 	print_ctrl_obj[idx].dbglvlmac_on = enable;
3872 	pr_info("%s: DbgLVLmac feature %s\n",
3873 		__func__,
3874 		((enable) ? "enabled" : "disabled"));
3875 
3876 	return QDF_STATUS_SUCCESS;
3877 }
3878 qdf_export_symbol(qdf_print_set_node_flag);
3879 
3880 bool qdf_print_get_node_flag(unsigned int idx)
3881 {
3882 	bool node_flag = false;
3883 
3884 	/* Check if index passed is valid */
3885 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3886 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3887 		return node_flag;
3888 	}
3889 
3890 	/* Check if print control object is in use */
3891 	if (!print_ctrl_obj[idx].in_use) {
3892 		pr_info("%s: Invalid print control object\n", __func__);
3893 		return node_flag;
3894 	}
3895 
3896 	if (print_ctrl_obj[idx].dbglvlmac_on)
3897 		node_flag = true;
3898 
3899 	return node_flag;
3900 }
3901 qdf_export_symbol(qdf_print_get_node_flag);
3902 
3903 void qdf_print_clean_node_flag(unsigned int idx)
3904 {
3905 	/* Disable dbglvlmac_on during cleanup */
3906 	print_ctrl_obj[idx].dbglvlmac_on = 0;
3907 }
3908 
3909 #else
3910 
3911 void qdf_print_clean_node_flag(unsigned int idx)
3912 {
3913 	/* No operation in case of no support for DBG_LVL_MAC_FILTERING */
3914 	return;
3915 }
3916 #endif
3917 
3918 void QDF_PRINT_INFO(unsigned int idx, QDF_MODULE_ID module,
3919 		    QDF_TRACE_LEVEL level,
3920 		    char *str_format, ...)
3921 {
3922 	va_list args;
3923 
3924 	/* Generic wrapper API will compile qdf_vprint in order to
3925 	 * log the message. Once QDF converged debug framework is in
3926 	 * place, this will be changed to adapt to the framework, compiling
3927 	 * call to converged tracing API
3928 	 */
3929 	va_start(args, str_format);
3930 	qdf_vprint(str_format, args);
3931 	va_end(args);
3932 }
3933 qdf_export_symbol(QDF_PRINT_INFO);
3934 
3935 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
3936 void qdf_logging_init(void)
3937 {
3938 	wlan_logging_sock_init_svc();
3939 	nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY);
3940 	wlan_logging_notifier_init(qdf_log_dump_at_kernel_enable);
3941 	wlan_logging_set_flush_timer(qdf_log_flush_timer_period);
3942 }
3943 
3944 void qdf_logging_exit(void)
3945 {
3946 	wlan_logging_notifier_deinit(qdf_log_dump_at_kernel_enable);
3947 	nl_srv_exit();
3948 	wlan_logging_sock_deinit_svc();
3949 }
3950 
3951 int qdf_logging_set_flush_timer(uint32_t milliseconds)
3952 {
3953 	if (wlan_logging_set_flush_timer(milliseconds) == 0)
3954 		return QDF_STATUS_SUCCESS;
3955 	else
3956 		return QDF_STATUS_E_FAILURE;
3957 }
3958 
3959 void qdf_logging_flush_logs(void)
3960 {
3961 	wlan_flush_host_logs_for_fatal();
3962 }
3963 
3964 #else
3965 void qdf_logging_init(void)
3966 {
3967 	nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY);
3968 }
3969 
3970 void qdf_logging_exit(void)
3971 {
3972 	nl_srv_exit();
3973 }
3974 
3975 int qdf_logging_set_flush_timer(uint32_t milliseconds)
3976 {
3977 	return QDF_STATUS_E_FAILURE;
3978 }
3979 
3980 void qdf_logging_flush_logs(void)
3981 {
3982 }
3983 #endif
3984 
3985 qdf_export_symbol(qdf_logging_set_flush_timer);
3986 qdf_export_symbol(qdf_logging_flush_logs);
3987 
3988 #ifdef CONFIG_KALLSYMS
3989 inline int qdf_sprint_symbol(char *buffer, void *addr)
3990 {
3991 	return sprint_symbol(buffer, (unsigned long)addr);
3992 }
3993 #else
3994 int qdf_sprint_symbol(char *buffer, void *addr)
3995 {
3996 	if (!buffer)
3997 		return 0;
3998 
3999 	buffer[0] = '\0';
4000 	return 1;
4001 }
4002 #endif
4003 qdf_export_symbol(qdf_sprint_symbol);
4004 
4005 void qdf_set_pidx(int pidx)
4006 {
4007 	qdf_pidx = pidx;
4008 }
4009 qdf_export_symbol(qdf_set_pidx);
4010 
4011 int qdf_get_pidx(void)
4012 {
4013 	return qdf_pidx;
4014 }
4015 qdf_export_symbol(qdf_get_pidx);
4016 
4017 #ifdef PANIC_ON_BUG
4018 #ifdef CONFIG_SLUB_DEBUG
4019 void __qdf_bug(void)
4020 {
4021 	BUG();
4022 }
4023 qdf_export_symbol(__qdf_bug);
4024 #endif /* CONFIG_SLUB_DEBUG */
4025 #endif /* PANIC_ON_BUG */
4026 
4027