xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/qdf_trace.c (revision f28396d060cff5c6519f883cb28ae0116ce479f1)
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  * @subtype: packet type
1442  *
1443  * Return: String based on pkt type
1444  */
1445 static
1446 uint8_t *qdf_get_pkt_type_string(uint8_t subtype)
1447 {
1448 	switch (subtype) {
1449 	case QDF_PROTO_EAPOL_M1:
1450 		return "EAPOL-1";
1451 	case QDF_PROTO_EAPOL_M2:
1452 		return "EAPOL-2";
1453 	case QDF_PROTO_EAPOL_M3:
1454 		return "EAPOL-3";
1455 	case QDF_PROTO_EAPOL_M4:
1456 		return "EAPOL-4";
1457 	case QDF_PROTO_DHCP_DISCOVER:
1458 		return "DHCP-D";
1459 	case QDF_PROTO_DHCP_REQUEST:
1460 		return "DHCP-R";
1461 	case QDF_PROTO_DHCP_OFFER:
1462 		return "DHCP-O";
1463 	case QDF_PROTO_DHCP_ACK:
1464 		return "DHCP-A";
1465 	case QDF_PROTO_DHCP_NACK:
1466 		return "DHCP-NA";
1467 	case QDF_PROTO_ARP_REQ:
1468 		return "ARP-RQ";
1469 	case QDF_PROTO_ARP_RES:
1470 		return "ARP-RS";
1471 	case QDF_PROTO_DNS_QUERY:
1472 		return "DNS_Q";
1473 	case QDF_PROTO_DNS_RES:
1474 		return "DNS_RS";
1475 	default:
1476 		return "UNKNOWN";
1477 	}
1478 }
1479 
1480 /**
1481  * qdf_get_pkt_status_string() - Get the string based on pkt status
1482  * @status: packet status
1483  *
1484  * Return: String based on pkt status
1485  */
1486 static
1487 uint8_t *qdf_get_pkt_status_string(uint8_t status)
1488 {
1489 	switch (status) {
1490 	case QDF_TX_RX_STATUS_INVALID:
1491 		return "inv";
1492 	case QDF_TX_RX_STATUS_OK:
1493 		return "succ";
1494 	case QDF_TX_RX_STATUS_FW_DISCARD:
1495 		return "disc";
1496 	case QDF_TX_RX_STATUS_NO_ACK:
1497 		return "nack";
1498 	case QDF_TX_RX_STATUS_DROP:
1499 		return "drop";
1500 	default:
1501 		return "unknown";
1502 	}
1503 }
1504 
1505 /**
1506  * qdf_dp_log_proto_pkt_info() - Send diag log with pkt info
1507  * @sa: Source MAC address
1508  * @da: Destination MAC address
1509  * @type: packet type
1510  * @subtype: packet subtype
1511  * @dir: tx or rx
1512  * @msdu_id: MSDU id
1513  * @status: status code
1514  *
1515  * Return: none
1516  */
1517 void qdf_dp_log_proto_pkt_info(uint8_t *sa, uint8_t *da, uint8_t type,
1518 			       uint8_t subtype, uint8_t dir, uint8_t msdu_id,
1519 			       uint8_t status)
1520 {
1521 	uint8_t pkt_rate_limit;
1522 	static ulong last_ticks[QDF_PROTO_SUBTYPE_MAX] = {0};
1523 	ulong curr_ticks = jiffies;
1524 
1525 	pkt_rate_limit = qdf_get_rate_limit_by_type(type);
1526 
1527 	if (!time_after(curr_ticks, last_ticks[subtype] + HZ / pkt_rate_limit))
1528 		return;
1529 
1530 	last_ticks[subtype] = curr_ticks;
1531 
1532 	if (status == QDF_TX_RX_STATUS_INVALID)
1533 		qdf_nofl_info("%s %s: SA:%pM DA:%pM",
1534 			      qdf_get_pkt_type_string(subtype), dir ? "RX":"TX",
1535 			      sa, da);
1536 	else
1537 		qdf_nofl_info("%s %s: SA:%pM DA:%pM msdu_id:%d status: %s",
1538 			      qdf_get_pkt_type_string(subtype), dir ? "RX":"TX",
1539 			      sa, da, msdu_id,
1540 			      qdf_get_pkt_status_string(status));
1541 }
1542 
1543 qdf_export_symbol(qdf_dp_log_proto_pkt_info);
1544 
1545 /**
1546  * qdf_log_icmpv6_pkt() - log ICMPv6 packet
1547  * @vdev_id: ID of the vdev
1548  * @skb: skb pointer
1549  * @dir: direction
1550  * @pdev_id: ID of the pdev
1551  *
1552  * Return: true/false
1553  */
1554 static bool qdf_log_icmpv6_pkt(uint8_t vdev_id, struct sk_buff *skb,
1555 			       enum qdf_proto_dir dir, uint8_t pdev_id)
1556 {
1557 	enum qdf_proto_subtype subtype;
1558 
1559 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMPv6) &&
1560 		((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ICMPv6 ==
1561 			QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1562 		 (dir == QDF_RX && qdf_nbuf_is_icmpv6_pkt(skb) == true))) {
1563 
1564 		subtype = qdf_nbuf_get_icmpv6_subtype(skb);
1565 
1566 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false;
1567 		if (dir == QDF_TX)
1568 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1569 		else if (dir == QDF_RX)
1570 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1571 
1572 		DPTRACE(qdf_dp_trace_proto_pkt(
1573 			QDF_DP_TRACE_ICMPv6_PACKET_RECORD,
1574 			vdev_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
1575 			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
1576 			QDF_PROTO_TYPE_ICMPv6, subtype, dir, pdev_id, false));
1577 
1578 		switch (subtype) {
1579 		case QDF_PROTO_ICMPV6_REQ:
1580 			g_qdf_dp_trace_data.icmpv6_req++;
1581 			break;
1582 		case QDF_PROTO_ICMPV6_RES:
1583 			g_qdf_dp_trace_data.icmpv6_resp++;
1584 			break;
1585 		case QDF_PROTO_ICMPV6_RS:
1586 			g_qdf_dp_trace_data.icmpv6_rs++;
1587 			break;
1588 		case QDF_PROTO_ICMPV6_RA:
1589 			g_qdf_dp_trace_data.icmpv6_ra++;
1590 			break;
1591 		case QDF_PROTO_ICMPV6_NS:
1592 			g_qdf_dp_trace_data.icmpv6_ns++;
1593 			break;
1594 		case QDF_PROTO_ICMPV6_NA:
1595 			g_qdf_dp_trace_data.icmpv6_na++;
1596 			break;
1597 		default:
1598 			break;
1599 		}
1600 		return true;
1601 	}
1602 
1603 	return false;
1604 }
1605 
1606 /**
1607  * qdf_log_icmp_pkt() - log ICMP packet
1608  * @vdev_id: ID of the vdev
1609  * @skb: skb pointer
1610  * @dir: direction
1611  * @pdev_id: ID of the pdev
1612  *
1613  * Return: true/false
1614  */
1615 static bool qdf_log_icmp_pkt(uint8_t vdev_id, struct sk_buff *skb,
1616 			     enum qdf_proto_dir dir, uint8_t pdev_id)
1617 {
1618 	enum qdf_proto_subtype proto_subtype;
1619 
1620 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMP) &&
1621 	    (qdf_nbuf_is_icmp_pkt(skb) == true)) {
1622 
1623 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false;
1624 		proto_subtype = qdf_nbuf_get_icmp_subtype(skb);
1625 
1626 		if (QDF_TX == dir)
1627 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1628 		else if (QDF_RX == dir)
1629 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1630 
1631 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ICMP_PACKET_RECORD,
1632 					       vdev_id,
1633 					       skb->data +
1634 					       QDF_NBUF_SRC_MAC_OFFSET,
1635 					       skb->data +
1636 					       QDF_NBUF_DEST_MAC_OFFSET,
1637 					       QDF_PROTO_TYPE_ICMP,
1638 					       proto_subtype, dir, pdev_id,
1639 					       false));
1640 
1641 		if (proto_subtype == QDF_PROTO_ICMP_REQ)
1642 			g_qdf_dp_trace_data.icmp_req++;
1643 		else
1644 			g_qdf_dp_trace_data.icmp_resp++;
1645 
1646 		return true;
1647 	}
1648 	return false;
1649 }
1650 
1651 /**
1652  * qdf_log_eapol_pkt() - log EAPOL packet
1653  * @vdev_id: ID of the vdev
1654  * @skb: skb pointer
1655  * @dir: direction
1656  * @pdev_id: ID of the pdev
1657  *
1658  * Return: true/false
1659  */
1660 static bool qdf_log_eapol_pkt(uint8_t vdev_id, struct sk_buff *skb,
1661 			      enum qdf_proto_dir dir, uint8_t pdev_id)
1662 {
1663 	enum qdf_proto_subtype subtype;
1664 	uint32_t dp_eap_trace;
1665 	uint32_t dp_eap_event;
1666 
1667 	dp_eap_trace = qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
1668 	dp_eap_event = qdf_dp_get_proto_event_bitmap() &
1669 				QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
1670 
1671 	if (!dp_eap_trace && !dp_eap_event)
1672 		return false;
1673 
1674 	if (!((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_EAPOL ==
1675 	       QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1676 	      (dir == QDF_RX && qdf_nbuf_is_ipv4_eapol_pkt(skb) == true)))
1677 		return false;
1678 
1679 	subtype = qdf_nbuf_get_eapol_subtype(skb);
1680 
1681 	if (dp_eap_event && dir == QDF_RX)
1682 		qdf_dp_log_proto_pkt_info(skb->data + QDF_NBUF_SRC_MAC_OFFSET,
1683 					  skb->data + QDF_NBUF_DEST_MAC_OFFSET,
1684 					  QDF_PROTO_TYPE_EAPOL, subtype, dir,
1685 					  QDF_TRACE_DEFAULT_MSDU_ID,
1686 					  QDF_TX_RX_STATUS_INVALID);
1687 
1688 	if (dp_eap_trace) {
1689 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
1690 		if (QDF_TX == dir)
1691 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1692 		else if (QDF_RX == dir)
1693 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1694 
1695 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_EAPOL_PACKET_RECORD,
1696 					       vdev_id,
1697 					       skb->data +
1698 					       QDF_NBUF_SRC_MAC_OFFSET,
1699 					       skb->data +
1700 					       QDF_NBUF_DEST_MAC_OFFSET,
1701 					       QDF_PROTO_TYPE_EAPOL, subtype,
1702 					       dir, pdev_id, true));
1703 
1704 		switch (subtype) {
1705 		case QDF_PROTO_EAPOL_M1:
1706 			g_qdf_dp_trace_data.eapol_m1++;
1707 			break;
1708 		case QDF_PROTO_EAPOL_M2:
1709 			g_qdf_dp_trace_data.eapol_m2++;
1710 			break;
1711 		case QDF_PROTO_EAPOL_M3:
1712 			g_qdf_dp_trace_data.eapol_m3++;
1713 			break;
1714 		case QDF_PROTO_EAPOL_M4:
1715 			g_qdf_dp_trace_data.eapol_m4++;
1716 			break;
1717 		default:
1718 			g_qdf_dp_trace_data.eapol_others++;
1719 			break;
1720 		}
1721 	}
1722 
1723 	return true;
1724 }
1725 
1726 /**
1727  * qdf_log_dhcp_pkt() - log DHCP packet
1728  * @vdev_id: ID of the vdev
1729  * @skb: skb pointer
1730  * @dir: direction
1731  * @pdev_id: ID of the pdev
1732  *
1733  * Return: true/false
1734  */
1735 static bool qdf_log_dhcp_pkt(uint8_t vdev_id, struct sk_buff *skb,
1736 			     enum qdf_proto_dir dir, uint8_t pdev_id)
1737 {
1738 	enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
1739 	uint32_t dp_dhcp_trace;
1740 	uint32_t dp_dhcp_event;
1741 
1742 	dp_dhcp_trace = qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_DHCP;
1743 	dp_dhcp_event = qdf_dp_get_proto_event_bitmap() &
1744 				QDF_NBUF_PKT_TRAC_TYPE_DHCP;
1745 
1746 	if (!dp_dhcp_trace && !dp_dhcp_event)
1747 		return false;
1748 
1749 	if (!((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_DHCP ==
1750 	       QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1751 	      (dir == QDF_RX && qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true)))
1752 		return false;
1753 
1754 	subtype = qdf_nbuf_get_dhcp_subtype(skb);
1755 
1756 	if (dp_dhcp_event && dir == QDF_RX)
1757 		qdf_dp_log_proto_pkt_info(skb->data + QDF_NBUF_SRC_MAC_OFFSET,
1758 					  skb->data + QDF_NBUF_DEST_MAC_OFFSET,
1759 					  QDF_PROTO_TYPE_DHCP, subtype, dir,
1760 					  QDF_TRACE_DEFAULT_MSDU_ID,
1761 					  QDF_TX_RX_STATUS_INVALID);
1762 
1763 	if (dp_dhcp_trace) {
1764 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
1765 		if (QDF_TX == dir)
1766 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1767 		else if (QDF_RX == dir)
1768 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1769 
1770 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_DHCP_PACKET_RECORD,
1771 					       vdev_id,
1772 					       skb->data +
1773 					       QDF_NBUF_SRC_MAC_OFFSET,
1774 					       skb->data +
1775 					       QDF_NBUF_DEST_MAC_OFFSET,
1776 					       QDF_PROTO_TYPE_DHCP, subtype,
1777 					       dir, pdev_id, true));
1778 
1779 		switch (subtype) {
1780 		case QDF_PROTO_DHCP_DISCOVER:
1781 			g_qdf_dp_trace_data.dhcp_disc++;
1782 			break;
1783 		case QDF_PROTO_DHCP_OFFER:
1784 			g_qdf_dp_trace_data.dhcp_off++;
1785 			break;
1786 		case QDF_PROTO_DHCP_REQUEST:
1787 			g_qdf_dp_trace_data.dhcp_req++;
1788 			break;
1789 		case QDF_PROTO_DHCP_ACK:
1790 			g_qdf_dp_trace_data.dhcp_ack++;
1791 			break;
1792 		case QDF_PROTO_DHCP_NACK:
1793 			g_qdf_dp_trace_data.dhcp_nack++;
1794 			break;
1795 		default:
1796 			g_qdf_dp_trace_data.eapol_others++;
1797 			break;
1798 		}
1799 	}
1800 
1801 	return true;
1802 }
1803 
1804 /**
1805  * qdf_log_arp_pkt() - log ARP packet
1806  * @vdev_id: ID of the vdev
1807  * @skb: skb pointer
1808  * @dir: direction
1809  * @pdev_id: ID of the pdev
1810  *
1811  * Return: true/false
1812  */
1813 static bool qdf_log_arp_pkt(uint8_t vdev_id, struct sk_buff *skb,
1814 			    enum qdf_proto_dir dir, uint8_t pdev_id)
1815 {
1816 	enum qdf_proto_subtype proto_subtype;
1817 
1818 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ARP) &&
1819 		((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ARP ==
1820 			QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1821 		 (dir == QDF_RX && qdf_nbuf_is_ipv4_arp_pkt(skb) == true))) {
1822 
1823 		proto_subtype = qdf_nbuf_get_arp_subtype(skb);
1824 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
1825 		if (QDF_TX == dir)
1826 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1827 		else if (QDF_RX == dir)
1828 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1829 
1830 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ARP_PACKET_RECORD,
1831 					       vdev_id,
1832 					       skb->data +
1833 					       QDF_NBUF_SRC_MAC_OFFSET,
1834 					       skb->data +
1835 					       QDF_NBUF_DEST_MAC_OFFSET,
1836 					       QDF_PROTO_TYPE_ARP,
1837 					       proto_subtype, dir, pdev_id,
1838 					       true));
1839 
1840 		if (QDF_PROTO_ARP_REQ == proto_subtype)
1841 			g_qdf_dp_trace_data.arp_req++;
1842 		else
1843 			g_qdf_dp_trace_data.arp_resp++;
1844 
1845 		return true;
1846 	}
1847 	return false;
1848 }
1849 
1850 
1851 bool qdf_dp_trace_log_pkt(uint8_t vdev_id, struct sk_buff *skb,
1852 			  enum qdf_proto_dir dir, uint8_t pdev_id)
1853 {
1854 	if (!qdf_dp_get_proto_bitmap() && !qdf_dp_get_proto_event_bitmap())
1855 		return false;
1856 	if (qdf_log_arp_pkt(vdev_id, skb, dir, pdev_id))
1857 		return true;
1858 	if (qdf_log_dhcp_pkt(vdev_id, skb, dir, pdev_id))
1859 		return true;
1860 	if (qdf_log_eapol_pkt(vdev_id, skb, dir, pdev_id))
1861 		return true;
1862 	if (qdf_log_icmp_pkt(vdev_id, skb, dir, pdev_id))
1863 		return true;
1864 	if (qdf_log_icmpv6_pkt(vdev_id, skb, dir, pdev_id))
1865 		return true;
1866 	return false;
1867 }
1868 qdf_export_symbol(qdf_dp_trace_log_pkt);
1869 
1870 void qdf_dp_display_mgmt_pkt(struct qdf_dp_trace_record_s *record,
1871 			      uint16_t index, uint8_t pdev_id, uint8_t info)
1872 {
1873 	int loc;
1874 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
1875 	struct qdf_dp_trace_mgmt_buf *buf =
1876 		(struct qdf_dp_trace_mgmt_buf *)record->data;
1877 
1878 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
1879 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
1880 					 index, info, record);
1881 
1882 	DPTRACE_PRINT("%s [%d] [%s %s]",
1883 		      prepend_str,
1884 		      buf->vdev_id,
1885 		      qdf_dp_type_to_str(buf->type),
1886 		      qdf_dp_subtype_to_str(buf->subtype));
1887 }
1888 qdf_export_symbol(qdf_dp_display_mgmt_pkt);
1889 
1890 
1891 void qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
1892 		uint8_t pdev_id, enum qdf_proto_type type,
1893 		enum qdf_proto_subtype subtype)
1894 {
1895 	struct qdf_dp_trace_mgmt_buf buf;
1896 	int buf_size = sizeof(struct qdf_dp_trace_mgmt_buf);
1897 
1898 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
1899 		return;
1900 
1901 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
1902 		QDF_BUG(0);
1903 
1904 	buf.type = type;
1905 	buf.subtype = subtype;
1906 	buf.vdev_id = vdev_id;
1907 	qdf_dp_add_record(code, pdev_id, (uint8_t *)&buf, buf_size,
1908 			  NULL, 0, true);
1909 }
1910 qdf_export_symbol(qdf_dp_trace_mgmt_pkt);
1911 
1912 static void
1913 qdf_dpt_display_credit_record_debugfs(qdf_debugfs_file_t file,
1914 				      struct qdf_dp_trace_record_s *record,
1915 				      uint32_t index)
1916 {
1917 	int loc;
1918 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
1919 	struct qdf_dp_trace_credit_record *buf =
1920 		(struct qdf_dp_trace_credit_record *)record->data;
1921 
1922 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
1923 					 index, 0, record);
1924 	if (buf->operation == QDF_OP_NA)
1925 		qdf_debugfs_printf(file, "%s [%s] [T: %d G0: %d G1: %d]\n",
1926 				   prepend_str,
1927 				   qdf_dp_credit_source_to_str(buf->source),
1928 				   buf->total_credits, buf->g0_credit,
1929 				   buf->g1_credit);
1930 	else
1931 		qdf_debugfs_printf(file,
1932 				   "%s [%s] [T: %d G0: %d G1: %d] [%s %d]\n",
1933 				   prepend_str,
1934 				   qdf_dp_credit_source_to_str(buf->source),
1935 				   buf->total_credits, buf->g0_credit,
1936 				   buf->g1_credit,
1937 				   qdf_dp_operation_to_str(buf->operation),
1938 				   buf->delta);
1939 }
1940 
1941 void qdf_dp_display_credit_record(struct qdf_dp_trace_record_s *record,
1942 				  uint16_t index, uint8_t pdev_id, uint8_t info)
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, info, record);
1951 	if (buf->operation == QDF_OP_NA)
1952 		DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d]",
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 		DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d] [%s %d]",
1959 			      prepend_str,
1960 			      qdf_dp_credit_source_to_str(buf->source),
1961 			      buf->total_credits, buf->g0_credit,
1962 			      buf->g1_credit,
1963 			      qdf_dp_operation_to_str(buf->operation),
1964 			      buf->delta);
1965 }
1966 
1967 void qdf_dp_trace_credit_record(enum QDF_CREDIT_UPDATE_SOURCE source,
1968 				enum QDF_CREDIT_OPERATION operation,
1969 				int delta, int total_credits,
1970 				int g0_credit, int g1_credit)
1971 {
1972 	struct qdf_dp_trace_credit_record buf;
1973 	int buf_size = sizeof(struct qdf_dp_trace_credit_record);
1974 	enum QDF_DP_TRACE_ID code = QDF_DP_TRACE_TX_CREDIT_RECORD;
1975 
1976 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
1977 		return;
1978 
1979 	if (!(qdf_dp_get_proto_bitmap() & QDF_HL_CREDIT_TRACKING))
1980 		return;
1981 
1982 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
1983 		QDF_BUG(0);
1984 
1985 	buf.source = source;
1986 	buf.operation = operation;
1987 	buf.delta = delta;
1988 	buf.total_credits = total_credits;
1989 	buf.g0_credit = g0_credit;
1990 	buf.g1_credit = g1_credit;
1991 
1992 	qdf_dp_add_record(code, QDF_TRACE_DEFAULT_PDEV_ID, (uint8_t *)&buf,
1993 			  buf_size, NULL, 0, false);
1994 }
1995 qdf_export_symbol(qdf_dp_trace_credit_record);
1996 
1997 void qdf_dp_display_event_record(struct qdf_dp_trace_record_s *record,
1998 			      uint16_t index, uint8_t pdev_id, uint8_t info)
1999 {
2000 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2001 	struct qdf_dp_trace_event_buf *buf =
2002 		(struct qdf_dp_trace_event_buf *)record->data;
2003 
2004 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2005 	qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2006 				   index, info, record);
2007 
2008 	DPTRACE_PRINT("%s [%d] [%s %s]",
2009 		      prepend_str,
2010 		      buf->vdev_id,
2011 		      qdf_dp_type_to_str(buf->type),
2012 		      qdf_dp_subtype_to_str(buf->subtype));
2013 }
2014 qdf_export_symbol(qdf_dp_display_event_record);
2015 
2016 /**
2017  * qdf_dp_trace_record_event() - record events
2018  * @code: dptrace code
2019  * @vdev_id: vdev id
2020  * @pdev_id: pdev_id
2021  * @type: proto type
2022  * @subtype: proto subtype
2023  *
2024  * Return: none
2025  */
2026 void qdf_dp_trace_record_event(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
2027 		uint8_t pdev_id, enum qdf_proto_type type,
2028 		enum qdf_proto_subtype subtype)
2029 {
2030 	struct qdf_dp_trace_event_buf buf;
2031 	int buf_size = sizeof(struct qdf_dp_trace_event_buf);
2032 
2033 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
2034 		return;
2035 
2036 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2037 		QDF_BUG(0);
2038 
2039 	buf.type = type;
2040 	buf.subtype = subtype;
2041 	buf.vdev_id = vdev_id;
2042 	qdf_dp_add_record(code, pdev_id,
2043 			  (uint8_t *)&buf, buf_size, NULL, 0, true);
2044 }
2045 qdf_export_symbol(qdf_dp_trace_record_event);
2046 
2047 
2048 void qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s *record,
2049 			      uint16_t index, uint8_t pdev_id, uint8_t info)
2050 {
2051 	int loc;
2052 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2053 	struct qdf_dp_trace_proto_buf *buf =
2054 		(struct qdf_dp_trace_proto_buf *)record->data;
2055 
2056 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2057 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2058 					 index, info, record);
2059 	DPTRACE_PRINT("%s [%d] [%s] SA: "
2060 		      QDF_MAC_ADDR_STR " %s DA: "
2061 		      QDF_MAC_ADDR_STR,
2062 		      prepend_str,
2063 		      buf->vdev_id,
2064 		      qdf_dp_subtype_to_str(buf->subtype),
2065 		      QDF_MAC_ADDR_ARRAY(buf->sa.bytes),
2066 		      qdf_dp_dir_to_str(buf->dir),
2067 		      QDF_MAC_ADDR_ARRAY(buf->da.bytes));
2068 }
2069 qdf_export_symbol(qdf_dp_display_proto_pkt);
2070 
2071 void qdf_dp_trace_proto_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
2072 		uint8_t *sa, uint8_t *da, enum qdf_proto_type type,
2073 		enum qdf_proto_subtype subtype, enum qdf_proto_dir dir,
2074 		uint8_t pdev_id, bool print)
2075 {
2076 	struct qdf_dp_trace_proto_buf buf;
2077 	int buf_size = sizeof(struct qdf_dp_trace_ptr_buf);
2078 
2079 	if (qdf_dp_enable_check(NULL, code, dir) == false)
2080 		return;
2081 
2082 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2083 		QDF_BUG(0);
2084 
2085 	memcpy(&buf.sa, sa, QDF_NET_ETH_LEN);
2086 	memcpy(&buf.da, da, QDF_NET_ETH_LEN);
2087 	buf.dir = dir;
2088 	buf.type = type;
2089 	buf.subtype = subtype;
2090 	buf.vdev_id = vdev_id;
2091 	qdf_dp_add_record(code, pdev_id,
2092 			  (uint8_t *)&buf, buf_size, NULL, 0, print);
2093 }
2094 qdf_export_symbol(qdf_dp_trace_proto_pkt);
2095 
2096 void qdf_dp_display_ptr_record(struct qdf_dp_trace_record_s *record,
2097 				uint16_t index, uint8_t pdev_id, uint8_t info)
2098 {
2099 	int loc;
2100 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2101 	struct qdf_dp_trace_ptr_buf *buf =
2102 		(struct qdf_dp_trace_ptr_buf *)record->data;
2103 	bool is_free_pkt_ptr_record = false;
2104 
2105 	if ((record->code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) ||
2106 	    (record->code == QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD))
2107 		is_free_pkt_ptr_record = true;
2108 
2109 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2110 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2111 					 index, info, record);
2112 
2113 	if (loc < sizeof(prepend_str))
2114 		scnprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2115 			  "[msdu id %d %s %d]",
2116 			  buf->msdu_id,
2117 			  is_free_pkt_ptr_record ? "status" : "vdev_id",
2118 			  buf->status);
2119 
2120 	if (info & QDF_DP_TRACE_RECORD_INFO_LIVE) {
2121 		/* In live mode donot dump the contents of the cookie */
2122 		DPTRACE_PRINT("%s", prepend_str);
2123 	} else {
2124 		dump_dp_hex_trace(prepend_str, (uint8_t *)&buf->cookie,
2125 			sizeof(buf->cookie));
2126 	}
2127 }
2128 qdf_export_symbol(qdf_dp_display_ptr_record);
2129 
2130 static
2131 enum qdf_proto_type qdf_dp_get_pkt_proto_type(qdf_nbuf_t nbuf)
2132 {
2133 	uint8_t pkt_type;
2134 
2135 	if (!nbuf)
2136 		return QDF_PROTO_TYPE_MAX;
2137 
2138 	if (qdf_nbuf_data_is_dns_query(nbuf) ||
2139 	    qdf_nbuf_data_is_dns_response(nbuf))
2140 		return QDF_PROTO_TYPE_DNS;
2141 
2142 	pkt_type = QDF_NBUF_CB_GET_PACKET_TYPE(nbuf);
2143 
2144 	switch (pkt_type) {
2145 	case QDF_NBUF_CB_PACKET_TYPE_EAPOL:
2146 		return QDF_PROTO_TYPE_EAPOL;
2147 	case QDF_NBUF_CB_PACKET_TYPE_ARP:
2148 		return QDF_PROTO_TYPE_ARP;
2149 	case QDF_NBUF_CB_PACKET_TYPE_DHCP:
2150 		return QDF_PROTO_TYPE_DHCP;
2151 	default:
2152 		return QDF_PROTO_TYPE_MAX;
2153 	}
2154 }
2155 
2156 static
2157 enum qdf_proto_subtype qdf_dp_get_pkt_subtype(qdf_nbuf_t nbuf,
2158 					      enum qdf_proto_type pkt_type)
2159 {
2160 	switch (pkt_type) {
2161 	case QDF_PROTO_TYPE_EAPOL:
2162 		return qdf_nbuf_get_eapol_subtype(nbuf);
2163 	case QDF_PROTO_TYPE_ARP:
2164 		return qdf_nbuf_get_arp_subtype(nbuf);
2165 	case QDF_PROTO_TYPE_DHCP:
2166 		return qdf_nbuf_get_dhcp_subtype(nbuf);
2167 	case QDF_PROTO_TYPE_DNS:
2168 		return (qdf_nbuf_data_is_dns_query(nbuf)) ?
2169 				QDF_PROTO_DNS_QUERY : QDF_PROTO_DNS_RES;
2170 	default:
2171 		return QDF_PROTO_INVALID;
2172 	}
2173 }
2174 
2175 static
2176 bool qdf_dp_proto_log_enable_check(enum qdf_proto_type pkt_type,
2177 				   uint16_t status)
2178 {
2179 	if (pkt_type == QDF_PROTO_TYPE_MAX)
2180 		return false;
2181 
2182 	switch (pkt_type) {
2183 	case QDF_PROTO_TYPE_EAPOL:
2184 		return qdf_dp_get_proto_event_bitmap() &
2185 				QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
2186 	case QDF_PROTO_TYPE_DHCP:
2187 		return qdf_dp_get_proto_event_bitmap() &
2188 				QDF_NBUF_PKT_TRAC_TYPE_DHCP;
2189 	case QDF_PROTO_TYPE_ARP:
2190 		if (status == QDF_TX_RX_STATUS_OK)
2191 			return false;
2192 		else
2193 			return qdf_dp_get_proto_event_bitmap() &
2194 					QDF_NBUF_PKT_TRAC_TYPE_ARP;
2195 	case QDF_PROTO_TYPE_DNS:
2196 		if (status == QDF_TX_RX_STATUS_OK)
2197 			return false;
2198 		else
2199 			return qdf_dp_get_proto_event_bitmap() &
2200 					QDF_NBUF_PKT_TRAC_TYPE_DNS;
2201 	default:
2202 		return false;
2203 	}
2204 }
2205 
2206 /**
2207  * qdf_dp_trace_ptr() - record dptrace
2208  * @code: dptrace code
2209  * @pdev_id: pdev_id
2210  * @data: data
2211  * @size: size of data
2212  * @msdu_id: msdu_id
2213  * @status: return status
2214  *
2215  * Return: none
2216  */
2217 void qdf_dp_trace_ptr(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
2218 		uint8_t pdev_id, uint8_t *data, uint8_t size,
2219 		uint16_t msdu_id, uint16_t status)
2220 {
2221 	struct qdf_dp_trace_ptr_buf buf;
2222 	int buf_size = sizeof(struct qdf_dp_trace_ptr_buf);
2223 	enum qdf_proto_type pkt_type;
2224 
2225 	pkt_type = qdf_dp_get_pkt_proto_type(nbuf);
2226 	if ((code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD ||
2227 	     code == QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD) &&
2228 	    qdf_dp_proto_log_enable_check(pkt_type, status + 1))
2229 		qdf_dp_log_proto_pkt_info(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET,
2230 					 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET,
2231 					 pkt_type,
2232 					 qdf_dp_get_pkt_subtype(nbuf, pkt_type),
2233 					 QDF_TX, msdu_id, status + 1);
2234 
2235 	if (qdf_dp_enable_check(nbuf, code, QDF_TX) == false)
2236 		return;
2237 
2238 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2239 		QDF_BUG(0);
2240 
2241 	qdf_mem_copy(&buf.cookie, data, size);
2242 	buf.msdu_id = msdu_id;
2243 	buf.status = status;
2244 	qdf_dp_add_record(code, pdev_id, (uint8_t *)&buf, buf_size, NULL, 0,
2245 			  QDF_NBUF_CB_DP_TRACE_PRINT(nbuf));
2246 }
2247 qdf_export_symbol(qdf_dp_trace_ptr);
2248 
2249 void qdf_dp_trace_data_pkt(qdf_nbuf_t nbuf, uint8_t pdev_id,
2250 			   enum QDF_DP_TRACE_ID code, uint16_t msdu_id,
2251 			   enum qdf_proto_dir dir)
2252 {
2253 	struct qdf_dp_trace_data_buf buf;
2254 	enum qdf_proto_type pkt_type;
2255 
2256 	pkt_type = qdf_dp_get_pkt_proto_type(nbuf);
2257 	if (code == QDF_DP_TRACE_DROP_PACKET_RECORD &&
2258 	    qdf_dp_proto_log_enable_check(pkt_type, QDF_TX_RX_STATUS_DROP))
2259 		qdf_dp_log_proto_pkt_info(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET,
2260 					 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET,
2261 					 pkt_type,
2262 					 qdf_dp_get_pkt_subtype(nbuf, pkt_type),
2263 					 QDF_TX, msdu_id,
2264 					 QDF_TX_RX_STATUS_DROP);
2265 
2266 	buf.msdu_id = msdu_id;
2267 	if (!qdf_dp_enable_check(nbuf, code, dir))
2268 		return;
2269 
2270 	qdf_dp_add_record(code, pdev_id,
2271 			  nbuf ? qdf_nbuf_data(nbuf) : NULL,
2272 			  nbuf ? nbuf->len - nbuf->data_len : 0,
2273 			  (uint8_t *)&buf, sizeof(struct qdf_dp_trace_data_buf),
2274 			  (nbuf) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false);
2275 }
2276 
2277 qdf_export_symbol(qdf_dp_trace_data_pkt);
2278 
2279 void qdf_dp_display_record(struct qdf_dp_trace_record_s *record,
2280 			   uint16_t index, uint8_t pdev_id, uint8_t info)
2281 {
2282 	int loc;
2283 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2284 
2285 	if (!(pdev_id == QDF_TRACE_DEFAULT_PDEV_ID ||
2286 		pdev_id == record->pdev_id))
2287 		return;
2288 
2289 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2290 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2291 					 index, info, record);
2292 
2293 	switch (record->code) {
2294 	case  QDF_DP_TRACE_HDD_TX_TIMEOUT:
2295 		DPTRACE_PRINT(" %s: HDD TX Timeout", prepend_str);
2296 		break;
2297 	case  QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
2298 		DPTRACE_PRINT(" %s: HDD SoftAP TX Timeout", prepend_str);
2299 		break;
2300 	case  QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
2301 		DPTRACE_PRINT(" %s: CE Fast Packet Error", prepend_str);
2302 		break;
2303 	case QDF_DP_TRACE_LI_DP_NULL_RX_PACKET_RECORD:
2304 	default:
2305 		dump_dp_hex_trace(prepend_str, record->data, record->size);
2306 		break;
2307 	};
2308 }
2309 qdf_export_symbol(qdf_dp_display_record);
2310 
2311 void
2312 qdf_dp_display_data_pkt_record(struct qdf_dp_trace_record_s *record,
2313 			       uint16_t rec_index, uint8_t pdev_id,
2314 			       uint8_t info)
2315 {
2316 	int loc;
2317 	char prepend_str[DP_TRACE_META_DATA_STRLEN + 10];
2318 	struct qdf_dp_trace_data_buf *buf =
2319 		(struct qdf_dp_trace_data_buf *)record->data;
2320 
2321 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2322 
2323 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2324 					 rec_index, info, record);
2325 	if (loc < sizeof(prepend_str))
2326 		loc += snprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2327 				"[%d]", buf->msdu_id);
2328 	dump_dp_hex_trace(prepend_str,
2329 			  &record->data[sizeof(struct qdf_dp_trace_data_buf)],
2330 			  record->size);
2331 }
2332 
2333 /**
2334  * qdf_dp_trace() - Stores the data in buffer
2335  * @nbuf  : defines the netbuf
2336  * @code : defines the event
2337  * @pdev_id: pdev_id
2338  * @data : defines the data to be stored
2339  * @size : defines the size of the data record
2340  *
2341  * Return: None
2342  */
2343 void qdf_dp_trace(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code, uint8_t pdev_id,
2344 	uint8_t *data, uint8_t size, enum qdf_proto_dir dir)
2345 {
2346 
2347 	if (qdf_dp_enable_check(nbuf, code, dir) == false)
2348 		return;
2349 
2350 	qdf_dp_add_record(code, pdev_id, nbuf ? qdf_nbuf_data(nbuf) : NULL,
2351 			  size, NULL, 0,
2352 			  (nbuf) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false);
2353 }
2354 qdf_export_symbol(qdf_dp_trace);
2355 
2356 /**
2357  * qdf_dp_trace_spin_lock_init() - initializes the lock variable before use
2358  * This function will be called from cds_alloc_global_context, we will have lock
2359  * available to use ASAP
2360  *
2361  * Return: None
2362  */
2363 void qdf_dp_trace_spin_lock_init(void)
2364 {
2365 	spin_lock_init(&l_dp_trace_lock);
2366 }
2367 qdf_export_symbol(qdf_dp_trace_spin_lock_init);
2368 
2369 /**
2370  * qdf_dp_trace_disable_live_mode - disable live mode for dptrace
2371  *
2372  * Return: none
2373  */
2374 void qdf_dp_trace_disable_live_mode(void)
2375 {
2376 	g_qdf_dp_trace_data.force_live_mode = 0;
2377 }
2378 qdf_export_symbol(qdf_dp_trace_disable_live_mode);
2379 
2380 /**
2381  * qdf_dp_trace_enable_live_mode() - enable live mode for dptrace
2382  *
2383  * Return: none
2384  */
2385 void qdf_dp_trace_enable_live_mode(void)
2386 {
2387 	g_qdf_dp_trace_data.force_live_mode = 1;
2388 }
2389 qdf_export_symbol(qdf_dp_trace_enable_live_mode);
2390 
2391 /**
2392  * qdf_dp_trace_clear_buffer() - clear dp trace buffer
2393  *
2394  * Return: none
2395  */
2396 void qdf_dp_trace_clear_buffer(void)
2397 {
2398 	g_qdf_dp_trace_data.head = INVALID_QDF_DP_TRACE_ADDR;
2399 	g_qdf_dp_trace_data.tail = INVALID_QDF_DP_TRACE_ADDR;
2400 	g_qdf_dp_trace_data.num = 0;
2401 	g_qdf_dp_trace_data.dump_counter = 0;
2402 	g_qdf_dp_trace_data.num_records_to_dump = MAX_QDF_DP_TRACE_RECORDS;
2403 	if (g_qdf_dp_trace_data.enable)
2404 		memset(g_qdf_dp_trace_tbl, 0,
2405 		       MAX_QDF_DP_TRACE_RECORDS *
2406 		       sizeof(struct qdf_dp_trace_record_s));
2407 }
2408 qdf_export_symbol(qdf_dp_trace_clear_buffer);
2409 
2410 void qdf_dp_trace_dump_stats(void)
2411 {
2412 		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)",
2413 			      g_qdf_dp_trace_data.tx_count,
2414 			      g_qdf_dp_trace_data.rx_count,
2415 			      g_qdf_dp_trace_data.icmp_req,
2416 			      g_qdf_dp_trace_data.icmp_resp,
2417 			      g_qdf_dp_trace_data.arp_req,
2418 			      g_qdf_dp_trace_data.arp_resp,
2419 			      g_qdf_dp_trace_data.icmpv6_req,
2420 			      g_qdf_dp_trace_data.icmpv6_resp,
2421 			      g_qdf_dp_trace_data.icmpv6_ns,
2422 			      g_qdf_dp_trace_data.icmpv6_na,
2423 			      g_qdf_dp_trace_data.icmpv6_rs,
2424 			      g_qdf_dp_trace_data.icmpv6_ra,
2425 			      g_qdf_dp_trace_data.dhcp_disc,
2426 			      g_qdf_dp_trace_data.dhcp_off,
2427 			      g_qdf_dp_trace_data.dhcp_req,
2428 			      g_qdf_dp_trace_data.dhcp_ack,
2429 			      g_qdf_dp_trace_data.dhcp_nack,
2430 			      g_qdf_dp_trace_data.dhcp_others,
2431 			      g_qdf_dp_trace_data.eapol_m1,
2432 			      g_qdf_dp_trace_data.eapol_m2,
2433 			      g_qdf_dp_trace_data.eapol_m3,
2434 			      g_qdf_dp_trace_data.eapol_m4,
2435 			      g_qdf_dp_trace_data.eapol_others);
2436 }
2437 qdf_export_symbol(qdf_dp_trace_dump_stats);
2438 
2439 /**
2440  * qdf_dpt_dump_hex_trace_debugfs() - read data in file
2441  * @file: file to read
2442  * @str: string to prepend the hexdump with.
2443  * @buf: buffer which contains data to be written
2444  * @buf_len: defines the size of the data to be written
2445  *
2446  * Return: None
2447  */
2448 static void qdf_dpt_dump_hex_trace_debugfs(qdf_debugfs_file_t file,
2449 				char *str, uint8_t *buf, uint8_t buf_len)
2450 {
2451 	unsigned char linebuf[BUFFER_SIZE];
2452 	const u8 *ptr = buf;
2453 	int i, linelen, remaining = buf_len;
2454 
2455 	/* Dump the bytes in the last line */
2456 	for (i = 0; i < buf_len; i += ROW_SIZE) {
2457 		linelen = min(remaining, ROW_SIZE);
2458 		remaining -= ROW_SIZE;
2459 
2460 		hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1,
2461 				linebuf, sizeof(linebuf), false);
2462 
2463 		qdf_debugfs_printf(file, "%s %s\n", str, linebuf);
2464 	}
2465 }
2466 
2467 /**
2468  * qdf_dpt_display_proto_pkt_debugfs() - display proto packet
2469  * @file: file to read
2470  * @record: dptrace record
2471  * @index: index
2472  *
2473  * Return: none
2474  */
2475 static void qdf_dpt_display_proto_pkt_debugfs(qdf_debugfs_file_t file,
2476 				struct qdf_dp_trace_record_s *record,
2477 				uint32_t index)
2478 {
2479 	int loc;
2480 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2481 	struct qdf_dp_trace_proto_buf *buf =
2482 		(struct qdf_dp_trace_proto_buf *)record->data;
2483 
2484 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2485 					 index, 0, record);
2486 	qdf_debugfs_printf(file, "%s [%d] [%s] SA: "
2487 			   QDF_MAC_ADDR_STR " %s DA: "
2488 			   QDF_MAC_ADDR_STR,
2489 			   prepend_str,
2490 			   buf->vdev_id,
2491 			   qdf_dp_subtype_to_str(buf->subtype),
2492 			   QDF_MAC_ADDR_ARRAY(buf->sa.bytes),
2493 			   qdf_dp_dir_to_str(buf->dir),
2494 			   QDF_MAC_ADDR_ARRAY(buf->da.bytes));
2495 	qdf_debugfs_printf(file, "\n");
2496 }
2497 
2498 /**
2499  * qdf_dpt_display_mgmt_pkt_debugfs() - display mgmt packet
2500  * @file: file to read
2501  * @record: dptrace record
2502  * @index: index
2503  *
2504  * Return: none
2505  */
2506 static void qdf_dpt_display_mgmt_pkt_debugfs(qdf_debugfs_file_t file,
2507 				struct qdf_dp_trace_record_s *record,
2508 				uint32_t index)
2509 {
2510 
2511 	int loc;
2512 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2513 	struct qdf_dp_trace_mgmt_buf *buf =
2514 		(struct qdf_dp_trace_mgmt_buf *)record->data;
2515 
2516 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2517 					 index, 0, record);
2518 
2519 	qdf_debugfs_printf(file, "%s [%d] [%s %s]\n",
2520 			   prepend_str,
2521 			   buf->vdev_id,
2522 			   qdf_dp_type_to_str(buf->type),
2523 			   qdf_dp_subtype_to_str(buf->subtype));
2524 }
2525 
2526 /**
2527  * qdf_dpt_display_event_record_debugfs() - display event records
2528  * @file: file to read
2529  * @record: dptrace record
2530  * @index: index
2531  *
2532  * Return: none
2533  */
2534 static void qdf_dpt_display_event_record_debugfs(qdf_debugfs_file_t file,
2535 				struct qdf_dp_trace_record_s *record,
2536 				uint32_t index)
2537 {
2538 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2539 	struct qdf_dp_trace_event_buf *buf =
2540 		(struct qdf_dp_trace_event_buf *)record->data;
2541 
2542 	qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2543 				   index, 0, record);
2544 	qdf_debugfs_printf(file, "%s [%d] [%s %s]\n",
2545 			   prepend_str,
2546 			   buf->vdev_id,
2547 			   qdf_dp_type_to_str(buf->type),
2548 			   qdf_dp_subtype_to_str(buf->subtype));
2549 }
2550 
2551 /**
2552  * qdf_dpt_display_ptr_record_debugfs() - display record ptr
2553  * @file: file to read
2554  * @record: dptrace record
2555  * @index: index
2556  *
2557  * Return: none
2558  */
2559 static void qdf_dpt_display_ptr_record_debugfs(qdf_debugfs_file_t file,
2560 				struct qdf_dp_trace_record_s *record,
2561 				uint32_t index)
2562 {
2563 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2564 	int loc;
2565 	struct qdf_dp_trace_ptr_buf *buf =
2566 		(struct qdf_dp_trace_ptr_buf *)record->data;
2567 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2568 					 index, 0, record);
2569 
2570 	if (loc < sizeof(prepend_str))
2571 		scnprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2572 			  "[msdu id %d %s %d]",
2573 			  buf->msdu_id,
2574 			  (record->code ==
2575 				QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) ?
2576 			  "status" : "vdev_id",
2577 			  buf->status);
2578 
2579 	qdf_dpt_dump_hex_trace_debugfs(file, prepend_str,
2580 				       (uint8_t *)&buf->cookie,
2581 				       sizeof(buf->cookie));
2582 }
2583 
2584 /**
2585  * qdf_dpt_display_ptr_record_debugfs() - display record
2586  * @file: file to read
2587  * @record: dptrace record
2588  * @index: index
2589  *
2590  * Return: none
2591  */
2592 static void qdf_dpt_display_record_debugfs(qdf_debugfs_file_t file,
2593 				struct qdf_dp_trace_record_s *record,
2594 				uint32_t index)
2595 {
2596 	int loc;
2597 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2598 	struct qdf_dp_trace_data_buf *buf =
2599 		(struct qdf_dp_trace_data_buf *)record->data;
2600 
2601 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2602 					 index, 0, record);
2603 	if (loc < sizeof(prepend_str))
2604 		loc += snprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2605 				"[%d]", buf->msdu_id);
2606 	qdf_dpt_dump_hex_trace_debugfs(file, prepend_str,
2607 				       record->data, record->size);
2608 }
2609 
2610 uint32_t qdf_dpt_get_curr_pos_debugfs(qdf_debugfs_file_t file,
2611 				      enum qdf_dpt_debugfs_state state)
2612 {
2613 	uint32_t i = 0;
2614 	uint32_t tail;
2615 	uint32_t count = g_qdf_dp_trace_data.num;
2616 
2617 	if (!g_qdf_dp_trace_data.enable) {
2618 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
2619 		  "%s: Tracing Disabled", __func__);
2620 		return QDF_STATUS_E_EMPTY;
2621 	}
2622 
2623 	if (!count) {
2624 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
2625 		  "%s: no packets", __func__);
2626 		return QDF_STATUS_E_EMPTY;
2627 	}
2628 
2629 	if (state == QDF_DPT_DEBUGFS_STATE_SHOW_IN_PROGRESS)
2630 		return g_qdf_dp_trace_data.curr_pos;
2631 
2632 	qdf_debugfs_printf(file,
2633 		"DPT: config - bitmap 0x%x verb %u #rec %u rec_requested %u live_config %u thresh %u time_limit %u\n",
2634 		g_qdf_dp_trace_data.proto_bitmap,
2635 		g_qdf_dp_trace_data.verbosity,
2636 		g_qdf_dp_trace_data.no_of_record,
2637 		g_qdf_dp_trace_data.num_records_to_dump,
2638 		g_qdf_dp_trace_data.live_mode_config,
2639 		g_qdf_dp_trace_data.high_tput_thresh,
2640 		g_qdf_dp_trace_data.thresh_time_limit);
2641 
2642 	qdf_debugfs_printf(file,
2643 		"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",
2644 		g_qdf_dp_trace_data.icmp_req,
2645 		g_qdf_dp_trace_data.icmp_resp,
2646 		g_qdf_dp_trace_data.arp_req,
2647 		g_qdf_dp_trace_data.arp_resp,
2648 		g_qdf_dp_trace_data.icmpv6_req,
2649 		g_qdf_dp_trace_data.icmpv6_resp,
2650 		g_qdf_dp_trace_data.icmpv6_ns,
2651 		g_qdf_dp_trace_data.icmpv6_na,
2652 		g_qdf_dp_trace_data.icmpv6_rs,
2653 		g_qdf_dp_trace_data.icmpv6_ra,
2654 		g_qdf_dp_trace_data.dhcp_disc,
2655 		g_qdf_dp_trace_data.dhcp_off,
2656 		g_qdf_dp_trace_data.dhcp_req,
2657 		g_qdf_dp_trace_data.dhcp_ack,
2658 		g_qdf_dp_trace_data.dhcp_nack,
2659 		g_qdf_dp_trace_data.dhcp_others,
2660 		g_qdf_dp_trace_data.eapol_m1,
2661 		g_qdf_dp_trace_data.eapol_m2,
2662 		g_qdf_dp_trace_data.eapol_m3,
2663 		g_qdf_dp_trace_data.eapol_m4,
2664 		g_qdf_dp_trace_data.eapol_others);
2665 
2666 	qdf_debugfs_printf(file,
2667 		"DPT: Total Records: %d, Head: %d, Tail: %d\n",
2668 		g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head,
2669 		g_qdf_dp_trace_data.tail);
2670 
2671 	spin_lock_bh(&l_dp_trace_lock);
2672 	if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) {
2673 		i = g_qdf_dp_trace_data.head;
2674 		tail = g_qdf_dp_trace_data.tail;
2675 
2676 		if (count > g_qdf_dp_trace_data.num)
2677 			count = g_qdf_dp_trace_data.num;
2678 
2679 		if (tail >= (count - 1))
2680 			i = tail - count + 1;
2681 		else if (count != MAX_QDF_DP_TRACE_RECORDS)
2682 			i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) -
2683 						     tail);
2684 		g_qdf_dp_trace_data.curr_pos = 0;
2685 		g_qdf_dp_trace_data.saved_tail = tail;
2686 	}
2687 	spin_unlock_bh(&l_dp_trace_lock);
2688 
2689 	return g_qdf_dp_trace_data.saved_tail;
2690 }
2691 qdf_export_symbol(qdf_dpt_get_curr_pos_debugfs);
2692 
2693 QDF_STATUS qdf_dpt_dump_stats_debugfs(qdf_debugfs_file_t file,
2694 				      uint32_t curr_pos)
2695 {
2696 	struct qdf_dp_trace_record_s p_record;
2697 	uint32_t i = curr_pos;
2698 	uint16_t num_records_to_dump = g_qdf_dp_trace_data.num_records_to_dump;
2699 
2700 	if (!g_qdf_dp_trace_data.enable) {
2701 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
2702 			  "%s: Tracing Disabled", __func__);
2703 		return QDF_STATUS_E_FAILURE;
2704 	}
2705 
2706 	if (num_records_to_dump > g_qdf_dp_trace_data.num)
2707 		num_records_to_dump = g_qdf_dp_trace_data.num;
2708 
2709 	/*
2710 	 * Max dp trace record size should always be less than
2711 	 * QDF_DP_TRACE_PREPEND_STR_SIZE(100) + BUFFER_SIZE(121).
2712 	 */
2713 	if (WARN_ON(QDF_DP_TRACE_MAX_RECORD_SIZE <
2714 				QDF_DP_TRACE_PREPEND_STR_SIZE + BUFFER_SIZE))
2715 		return QDF_STATUS_E_FAILURE;
2716 
2717 	spin_lock_bh(&l_dp_trace_lock);
2718 	p_record = g_qdf_dp_trace_tbl[i];
2719 	spin_unlock_bh(&l_dp_trace_lock);
2720 
2721 	for (;; ) {
2722 		/*
2723 		 * Initially we get file as 1 page size, and
2724 		 * if remaining size in file is less than one record max size,
2725 		 * then return so that it gets an extra page.
2726 		 */
2727 		if ((file->size - file->count) < QDF_DP_TRACE_MAX_RECORD_SIZE) {
2728 			spin_lock_bh(&l_dp_trace_lock);
2729 			g_qdf_dp_trace_data.curr_pos = i;
2730 			spin_unlock_bh(&l_dp_trace_lock);
2731 			return QDF_STATUS_E_FAILURE;
2732 		}
2733 
2734 		switch (p_record.code) {
2735 		case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD:
2736 		case QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD:
2737 		case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD:
2738 			qdf_dpt_display_ptr_record_debugfs(file, &p_record, i);
2739 			break;
2740 
2741 		case QDF_DP_TRACE_EAPOL_PACKET_RECORD:
2742 		case QDF_DP_TRACE_DHCP_PACKET_RECORD:
2743 		case QDF_DP_TRACE_ARP_PACKET_RECORD:
2744 		case QDF_DP_TRACE_ICMP_PACKET_RECORD:
2745 		case QDF_DP_TRACE_ICMPv6_PACKET_RECORD:
2746 			qdf_dpt_display_proto_pkt_debugfs(file, &p_record, i);
2747 			break;
2748 
2749 		case QDF_DP_TRACE_TX_CREDIT_RECORD:
2750 			qdf_dpt_display_credit_record_debugfs(file, &p_record,
2751 							      i);
2752 			break;
2753 
2754 		case QDF_DP_TRACE_MGMT_PACKET_RECORD:
2755 			qdf_dpt_display_mgmt_pkt_debugfs(file, &p_record, i);
2756 			break;
2757 
2758 		case QDF_DP_TRACE_EVENT_RECORD:
2759 			qdf_dpt_display_event_record_debugfs(file, &p_record,
2760 							     i);
2761 			break;
2762 
2763 		case QDF_DP_TRACE_HDD_TX_TIMEOUT:
2764 			qdf_debugfs_printf(file, "DPT: %04d: %s %s\n",
2765 				i, p_record.time,
2766 				qdf_dp_code_to_string(p_record.code));
2767 			qdf_debugfs_printf(file, "%s: HDD TX Timeout\n");
2768 			break;
2769 
2770 		case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
2771 			qdf_debugfs_printf(file, "%04d: %s %s\n",
2772 				i, p_record.time,
2773 				qdf_dp_code_to_string(p_record.code));
2774 			qdf_debugfs_printf(file,
2775 					   "%s: HDD  SoftAP TX Timeout\n");
2776 			break;
2777 
2778 		case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
2779 			qdf_debugfs_printf(file, "DPT: %04d: %s %s\n",
2780 				i, p_record.time,
2781 				qdf_dp_code_to_string(p_record.code));
2782 			qdf_debugfs_printf(file,
2783 					   "%s: CE Fast Packet Error\n");
2784 			break;
2785 
2786 		case QDF_DP_TRACE_MAX:
2787 			qdf_debugfs_printf(file,
2788 				"%s: QDF_DP_TRACE_MAX event should not be generated\n",
2789 				__func__);
2790 			break;
2791 
2792 		case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
2793 		case QDF_DP_TRACE_HDD_RX_PACKET_RECORD:
2794 		case QDF_DP_TRACE_TX_PACKET_RECORD:
2795 		case QDF_DP_TRACE_RX_PACKET_RECORD:
2796 		case QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD:
2797 		case QDF_DP_TRACE_LI_DP_RX_PACKET_RECORD:
2798 
2799 		default:
2800 			qdf_dpt_display_record_debugfs(file, &p_record, i);
2801 			break;
2802 		}
2803 
2804 		if (++g_qdf_dp_trace_data.dump_counter == num_records_to_dump)
2805 			break;
2806 
2807 		spin_lock_bh(&l_dp_trace_lock);
2808 		if (i == 0)
2809 			i = MAX_QDF_DP_TRACE_RECORDS;
2810 
2811 		i -= 1;
2812 		p_record = g_qdf_dp_trace_tbl[i];
2813 		spin_unlock_bh(&l_dp_trace_lock);
2814 	}
2815 
2816 	g_qdf_dp_trace_data.dump_counter = 0;
2817 
2818 	return QDF_STATUS_SUCCESS;
2819 }
2820 qdf_export_symbol(qdf_dpt_dump_stats_debugfs);
2821 
2822 /**
2823  * qdf_dpt_set_value_debugfs() - Configure the value to control DP trace
2824  * @proto_bitmap: defines the protocol to be tracked
2825  * @no_of_records: defines the nth packet which is traced
2826  * @verbosity: defines the verbosity level
2827  *
2828  * Return: None
2829  */
2830 void qdf_dpt_set_value_debugfs(uint8_t proto_bitmap, uint8_t no_of_record,
2831 			    uint8_t verbosity, uint16_t num_records_to_dump)
2832 {
2833 	if (g_qdf_dp_trace_data.enable) {
2834 		g_qdf_dp_trace_data.proto_bitmap = proto_bitmap;
2835 		g_qdf_dp_trace_data.no_of_record = no_of_record;
2836 		g_qdf_dp_trace_data.verbosity    = verbosity;
2837 		g_qdf_dp_trace_data.num_records_to_dump = num_records_to_dump;
2838 	}
2839 }
2840 qdf_export_symbol(qdf_dpt_set_value_debugfs);
2841 
2842 
2843 /**
2844  * qdf_dp_trace_dump_all() - Dump data from ring buffer via call back functions
2845  * registered with QDF
2846  * @count: Number of lines to dump starting from tail to head
2847  * @pdev_id: pdev_id
2848  *
2849  * Return: None
2850  */
2851 void qdf_dp_trace_dump_all(uint32_t count, uint8_t pdev_id)
2852 {
2853 	struct qdf_dp_trace_record_s p_record;
2854 	int32_t i, tail;
2855 
2856 	if (!g_qdf_dp_trace_data.enable) {
2857 		DPTRACE_PRINT("Tracing Disabled");
2858 		return;
2859 	}
2860 
2861 	DPTRACE_PRINT(
2862 		"DPT: config - bitmap 0x%x verb %u #rec %u live_config %u thresh %u time_limit %u",
2863 		g_qdf_dp_trace_data.proto_bitmap,
2864 		g_qdf_dp_trace_data.verbosity,
2865 		g_qdf_dp_trace_data.no_of_record,
2866 		g_qdf_dp_trace_data.live_mode_config,
2867 		g_qdf_dp_trace_data.high_tput_thresh,
2868 		g_qdf_dp_trace_data.thresh_time_limit);
2869 
2870 	qdf_dp_trace_dump_stats();
2871 
2872 	DPTRACE_PRINT("DPT: Total Records: %d, Head: %d, Tail: %d",
2873 		      g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head,
2874 		      g_qdf_dp_trace_data.tail);
2875 
2876 	/* aquire the lock so that only one thread at a time can read
2877 	 * the ring buffer
2878 	 */
2879 	spin_lock_bh(&l_dp_trace_lock);
2880 
2881 	if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) {
2882 		i = g_qdf_dp_trace_data.head;
2883 		tail = g_qdf_dp_trace_data.tail;
2884 
2885 		if (count) {
2886 			if (count > g_qdf_dp_trace_data.num)
2887 				count = g_qdf_dp_trace_data.num;
2888 			if (tail >= (count - 1))
2889 				i = tail - count + 1;
2890 			else if (count != MAX_QDF_DP_TRACE_RECORDS)
2891 				i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) -
2892 							     tail);
2893 		}
2894 
2895 		p_record = g_qdf_dp_trace_tbl[i];
2896 		spin_unlock_bh(&l_dp_trace_lock);
2897 		for (;; ) {
2898 			qdf_dp_trace_cb_table[p_record.code](&p_record,
2899 							(uint16_t)i, pdev_id, false);
2900 			if (i == tail)
2901 				break;
2902 			i += 1;
2903 
2904 			spin_lock_bh(&l_dp_trace_lock);
2905 			if (MAX_QDF_DP_TRACE_RECORDS == i)
2906 				i = 0;
2907 
2908 			p_record = g_qdf_dp_trace_tbl[i];
2909 			spin_unlock_bh(&l_dp_trace_lock);
2910 		}
2911 	} else {
2912 		spin_unlock_bh(&l_dp_trace_lock);
2913 	}
2914 }
2915 qdf_export_symbol(qdf_dp_trace_dump_all);
2916 
2917 /**
2918  * qdf_dp_trace_throttle_live_mode() - Throttle DP Trace live mode
2919  * @high_bw_request: whether this is a high BW req or not
2920  *
2921  * The function tries to prevent excessive logging into the live buffer by
2922  * having an upper limit on number of packets that can be logged per second.
2923  *
2924  * The intention is to allow occasional pings and data packets and really low
2925  * throughput levels while suppressing bursts and higher throughput levels so
2926  * that we donot hog the live buffer.
2927  *
2928  * If the number of packets printed in a particular second exceeds the thresh,
2929  * disable printing in the next second.
2930  *
2931  * Return: None
2932  */
2933 void qdf_dp_trace_throttle_live_mode(bool high_bw_request)
2934 {
2935 	static int bw_interval_counter;
2936 
2937 	if (g_qdf_dp_trace_data.enable == false ||
2938 		g_qdf_dp_trace_data.live_mode_config == false)
2939 		return;
2940 
2941 	if (high_bw_request) {
2942 		g_qdf_dp_trace_data.live_mode = 0;
2943 		bw_interval_counter = 0;
2944 		return;
2945 	}
2946 
2947 	bw_interval_counter++;
2948 
2949 	if (0 == (bw_interval_counter %
2950 			g_qdf_dp_trace_data.thresh_time_limit)) {
2951 
2952 		spin_lock_bh(&l_dp_trace_lock);
2953 			if (g_qdf_dp_trace_data.print_pkt_cnt <=
2954 				g_qdf_dp_trace_data.high_tput_thresh)
2955 				g_qdf_dp_trace_data.live_mode = 1;
2956 
2957 		g_qdf_dp_trace_data.print_pkt_cnt = 0;
2958 		spin_unlock_bh(&l_dp_trace_lock);
2959 	}
2960 }
2961 qdf_export_symbol(qdf_dp_trace_throttle_live_mode);
2962 
2963 void qdf_dp_trace_apply_tput_policy(bool is_data_traffic)
2964 {
2965 	if (g_qdf_dp_trace_data.dynamic_verbosity_modify) {
2966 		goto check_live_mode;
2967 		return;
2968 	}
2969 
2970 	if (is_data_traffic) {
2971 		g_qdf_dp_trace_data.verbosity =
2972 					QDF_DP_TRACE_VERBOSITY_ULTRA_LOW;
2973 	} else {
2974 		g_qdf_dp_trace_data.verbosity =
2975 					g_qdf_dp_trace_data.ini_conf_verbosity;
2976 	}
2977 check_live_mode:
2978 	qdf_dp_trace_throttle_live_mode(is_data_traffic);
2979 }
2980 #endif
2981 
2982 struct qdf_print_ctrl print_ctrl_obj[MAX_PRINT_CONFIG_SUPPORTED];
2983 
2984 struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = {
2985 	[QDF_MODULE_ID_TDLS] = {"tdls"},
2986 	[QDF_MODULE_ID_ACS] = {"ACS"},
2987 	[QDF_MODULE_ID_SCAN_SM] = {"scan state machine"},
2988 	[QDF_MODULE_ID_SCANENTRY] = {"scan entry"},
2989 	[QDF_MODULE_ID_WDS] = {"WDS"},
2990 	[QDF_MODULE_ID_ACTION] = {"action"},
2991 	[QDF_MODULE_ID_ROAM] = {"STA roaming"},
2992 	[QDF_MODULE_ID_INACT] = {"inactivity"},
2993 	[QDF_MODULE_ID_DOTH] = {"11h"},
2994 	[QDF_MODULE_ID_IQUE] = {"IQUE"},
2995 	[QDF_MODULE_ID_WME] = {"WME"},
2996 	[QDF_MODULE_ID_ACL] = {"ACL"},
2997 	[QDF_MODULE_ID_WPA] = {"WPA/RSN"},
2998 	[QDF_MODULE_ID_RADKEYS] = {"dump 802.1x keys"},
2999 	[QDF_MODULE_ID_RADDUMP] = {"dump radius packet"},
3000 	[QDF_MODULE_ID_RADIUS] = {"802.1x radius client"},
3001 	[QDF_MODULE_ID_DOT1XSM] = {"802.1x state machine"},
3002 	[QDF_MODULE_ID_DOT1X] = {"802.1x authenticator"},
3003 	[QDF_MODULE_ID_POWER] = {"power save"},
3004 	[QDF_MODULE_ID_STATE] = {"state"},
3005 	[QDF_MODULE_ID_OUTPUT] = {"output"},
3006 	[QDF_MODULE_ID_SCAN] = {"scan"},
3007 	[QDF_MODULE_ID_AUTH] = {"authentication"},
3008 	[QDF_MODULE_ID_ASSOC] = {"association"},
3009 	[QDF_MODULE_ID_NODE] = {"node"},
3010 	[QDF_MODULE_ID_ELEMID] = {"element ID"},
3011 	[QDF_MODULE_ID_XRATE] = {"rate"},
3012 	[QDF_MODULE_ID_INPUT] = {"input"},
3013 	[QDF_MODULE_ID_CRYPTO] = {"crypto"},
3014 	[QDF_MODULE_ID_DUMPPKTS] = {"dump packet"},
3015 	[QDF_MODULE_ID_DEBUG] = {"debug"},
3016 	[QDF_MODULE_ID_MLME] = {"mlme"},
3017 	[QDF_MODULE_ID_RRM] = {"rrm"},
3018 	[QDF_MODULE_ID_WNM] = {"wnm"},
3019 	[QDF_MODULE_ID_P2P_PROT] = {"p2p_prot"},
3020 	[QDF_MODULE_ID_PROXYARP] = {"proxyarp"},
3021 	[QDF_MODULE_ID_L2TIF] = {"l2tif"},
3022 	[QDF_MODULE_ID_WIFIPOS] = {"wifipos"},
3023 	[QDF_MODULE_ID_WRAP] = {"wrap"},
3024 	[QDF_MODULE_ID_DFS] = {"dfs"},
3025 	[QDF_MODULE_ID_ATF] = {"atf"},
3026 	[QDF_MODULE_ID_SPLITMAC] = {"splitmac"},
3027 	[QDF_MODULE_ID_IOCTL] = {"ioctl"},
3028 	[QDF_MODULE_ID_NAC] = {"nac"},
3029 	[QDF_MODULE_ID_MESH] = {"mesh"},
3030 	[QDF_MODULE_ID_MBO] = {"mbo"},
3031 	[QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = {"extchanswitch"},
3032 	[QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = {"extchanscan"},
3033 	[QDF_MODULE_ID_TLSHIM] = {"tlshim"},
3034 	[QDF_MODULE_ID_WMI] = {"WMI"},
3035 	[QDF_MODULE_ID_HTT] = {"HTT"},
3036 	[QDF_MODULE_ID_HDD] = {"HDD"},
3037 	[QDF_MODULE_ID_SME] = {"SME"},
3038 	[QDF_MODULE_ID_PE] = {"PE"},
3039 	[QDF_MODULE_ID_WMA] = {"WMA"},
3040 	[QDF_MODULE_ID_SYS] = {"SYS"},
3041 	[QDF_MODULE_ID_QDF] = {"QDF"},
3042 	[QDF_MODULE_ID_SAP] = {"SAP"},
3043 	[QDF_MODULE_ID_HDD_SOFTAP] = {"HDD_SAP"},
3044 	[QDF_MODULE_ID_HDD_DATA] = {"DATA"},
3045 	[QDF_MODULE_ID_HDD_SAP_DATA] = {"SAP_DATA"},
3046 	[QDF_MODULE_ID_HIF] = {"HIF"},
3047 	[QDF_MODULE_ID_HTC] = {"HTC"},
3048 	[QDF_MODULE_ID_TXRX] = {"TXRX"},
3049 	[QDF_MODULE_ID_QDF_DEVICE] = {"QDF_DEV"},
3050 	[QDF_MODULE_ID_CFG] = {"CFG"},
3051 	[QDF_MODULE_ID_BMI] = {"BMI"},
3052 	[QDF_MODULE_ID_EPPING] = {"EPPING"},
3053 	[QDF_MODULE_ID_QVIT] = {"QVIT"},
3054 	[QDF_MODULE_ID_DP] = {"DP"},
3055 	[QDF_MODULE_ID_HAL] = {"HAL"},
3056 	[QDF_MODULE_ID_SOC] = {"SOC"},
3057 	[QDF_MODULE_ID_OS_IF] = {"OSIF"},
3058 	[QDF_MODULE_ID_TARGET_IF] = {"TIF"},
3059 	[QDF_MODULE_ID_SCHEDULER] = {"SCH"},
3060 	[QDF_MODULE_ID_MGMT_TXRX] = {"MGMT_TXRX"},
3061 	[QDF_MODULE_ID_PMO] = {"PMO"},
3062 	[QDF_MODULE_ID_POLICY_MGR] = {"POLICY_MGR"},
3063 	[QDF_MODULE_ID_SA_API] = {"SA_API"},
3064 	[QDF_MODULE_ID_NAN] = {"NAN"},
3065 	[QDF_MODULE_ID_SPECTRAL] = {"SPECTRAL"},
3066 	[QDF_MODULE_ID_P2P] = {"P2P"},
3067 	[QDF_MODULE_ID_OFFCHAN_TXRX] = {"OFFCHAN"},
3068 	[QDF_MODULE_ID_REGULATORY] = {"REGULATORY"},
3069 	[QDF_MODULE_ID_OBJ_MGR] = {"OBJMGR"},
3070 	[QDF_MODULE_ID_SERIALIZATION] = {"SER"},
3071 	[QDF_MODULE_ID_NSS] = {"NSS"},
3072 	[QDF_MODULE_ID_ROAM_DEBUG] = {"roam debug"},
3073 	[QDF_MODULE_ID_DIRECT_BUF_RX] = {"DIRECT_BUF_RX"},
3074 	[QDF_MODULE_ID_DISA] = {"disa"},
3075 	[QDF_MODULE_ID_GREEN_AP] = {"GREEN_AP"},
3076 	[QDF_MODULE_ID_EXTAP] = {"EXTAP"},
3077 	[QDF_MODULE_ID_FD] = {"FILS discovery"},
3078 	[QDF_MODULE_ID_FTM] = {"FTM"},
3079 	[QDF_MODULE_ID_OCB] = {"OCB"},
3080 	[QDF_MODULE_ID_CONFIG] = {"CONFIG"},
3081 	[QDF_MODULE_ID_IPA] = {"IPA"},
3082 	[QDF_MODULE_ID_CP_STATS] = {"CP_STATS"},
3083 	[QDF_MODULE_ID_ACTION_OUI] = {"action_oui"},
3084 	[QDF_MODULE_ID_TARGET] = {"TARGET"},
3085 	[QDF_MODULE_ID_MBSSIE] = {"MBSSIE"},
3086 	[QDF_MODULE_ID_FWOL] = {"fwol"},
3087 	[QDF_MODULE_ID_SM_ENGINE] = {"SM_ENG"},
3088 	[QDF_MODULE_ID_CMN_MLME] = {"CMN_MLME"},
3089 	[QDF_MODULE_ID_BSSCOLOR] = {"BSSCOLOR"},
3090 	[QDF_MODULE_ID_CFR] = {"CFR"},
3091 	[QDF_MODULE_ID_TX_CAPTURE] = {"TX_CAPTURE_ENHANCE"},
3092 	[QDF_MODULE_ID_INTEROP_ISSUES_AP] = {"INTEROP_ISSUES_AP"},
3093 	[QDF_MODULE_ID_BLACKLIST_MGR] = {"blm"},
3094 	[QDF_MODULE_ID_QLD] = {"QLD"},
3095 	[QDF_MODULE_ID_DYNAMIC_MODE_CHG] = {"Dynamic Mode Change"},
3096 	[QDF_MODULE_ID_COEX] = {"COEX"},
3097 	[QDF_MODULE_ID_MON_FILTER] = {"Monitor Filter"},
3098 	[QDF_MODULE_ID_ANY] = {"ANY"},
3099 	[QDF_MODULE_ID_PKT_CAPTURE] = {"pkt_capture"},
3100 };
3101 qdf_export_symbol(g_qdf_category_name);
3102 
3103 /**
3104  * qdf_trace_display() - Display trace
3105  *
3106  * Return:  None
3107  */
3108 void qdf_trace_display(void)
3109 {
3110 	QDF_MODULE_ID module_id;
3111 
3112 	pr_err("     1)FATAL  2)ERROR  3)WARN  4)INFO  5)INFO_H  6)INFO_M  7)INFO_L 8)DEBUG\n");
3113 	for (module_id = 0; module_id < QDF_MODULE_ID_MAX; ++module_id) {
3114 		pr_err("%2d)%s    %s        %s       %s       %s        %s         %s         %s        %s\n",
3115 		       (int)module_id,
3116 		       g_qdf_category_name[module_id].category_name_str,
3117 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3118 			       QDF_TRACE_LEVEL_FATAL) ? "X" : " ",
3119 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3120 			       QDF_TRACE_LEVEL_ERROR) ? "X" : " ",
3121 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3122 			       QDF_TRACE_LEVEL_WARN) ? "X" : " ",
3123 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3124 			       QDF_TRACE_LEVEL_INFO) ? "X" : " ",
3125 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3126 			       QDF_TRACE_LEVEL_INFO_HIGH) ? "X" : " ",
3127 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3128 			       QDF_TRACE_LEVEL_INFO_MED) ? "X" : " ",
3129 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3130 			       QDF_TRACE_LEVEL_INFO_LOW) ? "X" : " ",
3131 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3132 			       QDF_TRACE_LEVEL_DEBUG) ? "X" : " ");
3133 	}
3134 }
3135 qdf_export_symbol(qdf_trace_display);
3136 
3137 #ifdef QDF_TRACE_PRINT_ENABLE
3138 static inline void print_to_console(char *str_buffer)
3139 {
3140 	pr_err("%s\n", str_buffer);
3141 }
3142 #else
3143 
3144 #define print_to_console(str)
3145 #endif
3146 
3147 #ifdef MULTI_IF_NAME
3148 static const char *qdf_trace_wlan_modname(void)
3149 {
3150 	return MULTI_IF_NAME;
3151 }
3152 #else
3153 static const char *qdf_trace_wlan_modname(void)
3154 {
3155 	return "wlan";
3156 }
3157 #endif
3158 
3159 void qdf_trace_msg_cmn(unsigned int idx,
3160 			QDF_MODULE_ID category,
3161 			QDF_TRACE_LEVEL verbose,
3162 			const char *str_format, va_list val)
3163 {
3164 	char str_buffer[QDF_TRACE_BUFFER_SIZE];
3165 	int n;
3166 
3167 	/* Check if index passed is valid */
3168 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3169 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3170 		return;
3171 	}
3172 
3173 	/* Check if print control object is in use */
3174 	if (!print_ctrl_obj[idx].in_use) {
3175 		pr_info("%s: Invalid print control object\n", __func__);
3176 		return;
3177 	}
3178 
3179 	/* Check if category passed is valid */
3180 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
3181 		pr_info("%s: Invalid category: %d\n", __func__, category);
3182 		return;
3183 	}
3184 
3185 	/* Check if verbose mask is valid */
3186 	if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
3187 		pr_info("%s: Invalid verbose level %d\n", __func__, verbose);
3188 		return;
3189 	}
3190 
3191 	/*
3192 	 * Print the trace message when the desired verbose level is set in
3193 	 * the desired category for the print control object
3194 	 */
3195 	if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
3196 	    QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
3197 		static const char * const VERBOSE_STR[] = {
3198 			[QDF_TRACE_LEVEL_NONE] = "",
3199 			[QDF_TRACE_LEVEL_FATAL] = "F",
3200 			[QDF_TRACE_LEVEL_ERROR] = "E",
3201 			[QDF_TRACE_LEVEL_WARN] = "W",
3202 			[QDF_TRACE_LEVEL_INFO] = "I",
3203 			[QDF_TRACE_LEVEL_INFO_HIGH] = "IH",
3204 			[QDF_TRACE_LEVEL_INFO_MED] = "IM",
3205 			[QDF_TRACE_LEVEL_INFO_LOW] = "IL",
3206 			[QDF_TRACE_LEVEL_DEBUG] = "D",
3207 			[QDF_TRACE_LEVEL_TRACE] = "T",
3208 			[QDF_TRACE_LEVEL_ALL] = "" };
3209 
3210 		/* print the prefix string into the string buffer... */
3211 		n = scnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE,
3212 			     "%s: [%d:%s:%s] ", qdf_trace_wlan_modname(),
3213 			     in_interrupt() ? 0 : current->pid,
3214 			     VERBOSE_STR[verbose],
3215 			     g_qdf_category_name[category].category_name_str);
3216 
3217 		/* print the formatted log message after the prefix string */
3218 		vscnprintf(str_buffer + n, QDF_TRACE_BUFFER_SIZE - n,
3219 			   str_format, val);
3220 #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE)
3221 		wlan_log_to_user(verbose, (char *)str_buffer,
3222 				 strlen(str_buffer));
3223 		if (qdf_likely(qdf_log_dump_at_kernel_enable))
3224 			print_to_console(str_buffer);
3225 #else
3226 		pr_err("%s\n", str_buffer);
3227 #endif
3228 	}
3229 }
3230 qdf_export_symbol(qdf_trace_msg_cmn);
3231 
3232 QDF_STATUS qdf_print_setup(void)
3233 {
3234 	int i;
3235 
3236 	/* Loop through all print ctrl objects */
3237 	for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
3238 		if (qdf_print_ctrl_cleanup(i))
3239 			return QDF_STATUS_E_FAILURE;
3240 	}
3241 	return QDF_STATUS_SUCCESS;
3242 }
3243 qdf_export_symbol(qdf_print_setup);
3244 
3245 QDF_STATUS qdf_print_ctrl_cleanup(unsigned int idx)
3246 {
3247 	int i = 0;
3248 
3249 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3250 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3251 		return QDF_STATUS_E_FAILURE;
3252 	}
3253 
3254 	/* Clean up the print control object corresponding to that index
3255 	 * If success, callee to change print control index to -1
3256 	 */
3257 
3258 	for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3259 		print_ctrl_obj[idx].cat_info[i].category_verbose_mask =
3260 							QDF_TRACE_LEVEL_NONE;
3261 	}
3262 	print_ctrl_obj[idx].custom_print = NULL;
3263 	print_ctrl_obj[idx].custom_ctxt = NULL;
3264 	qdf_print_clean_node_flag(idx);
3265 	print_ctrl_obj[idx].in_use = false;
3266 
3267 	return QDF_STATUS_SUCCESS;
3268 }
3269 qdf_export_symbol(qdf_print_ctrl_cleanup);
3270 
3271 int qdf_print_ctrl_register(const struct category_info *cinfo,
3272 			    void *custom_print_handler,
3273 			    void *custom_ctx,
3274 			    const char *pctrl_name)
3275 {
3276 	int idx = -1;
3277 	int i = 0;
3278 
3279 	for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
3280 		if (!print_ctrl_obj[i].in_use) {
3281 			idx = i;
3282 			break;
3283 		}
3284 	}
3285 
3286 	/* Callee to handle idx -1 appropriately */
3287 	if (idx == -1) {
3288 		pr_info("%s: Allocation failed! No print control object free\n",
3289 			__func__);
3290 		return idx;
3291 	}
3292 
3293 	print_ctrl_obj[idx].in_use = true;
3294 
3295 	/*
3296 	 * In case callee does not pass category info,
3297 	 * custom print handler, custom context and print control name,
3298 	 * we do not set any value here. Clean up for the print control
3299 	 * getting allocated would have taken care of initializing
3300 	 * default values.
3301 	 *
3302 	 * We need to only set in_use to 1 in such a case
3303 	 */
3304 
3305 	if (pctrl_name) {
3306 		qdf_str_lcopy(print_ctrl_obj[idx].name, pctrl_name,
3307 			      sizeof(print_ctrl_obj[idx].name));
3308 	}
3309 
3310 	if (custom_print_handler)
3311 		print_ctrl_obj[idx].custom_print = custom_print_handler;
3312 
3313 	if (custom_ctx)
3314 		print_ctrl_obj[idx].custom_ctxt = custom_ctx;
3315 
3316 	if (cinfo) {
3317 		for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3318 			if (cinfo[i].category_verbose_mask ==
3319 			    QDF_TRACE_LEVEL_ALL) {
3320 				print_ctrl_obj[idx].cat_info[i]
3321 				.category_verbose_mask = 0xFFFF;
3322 			} else if ((cinfo[i].category_verbose_mask ==
3323 				   QDF_TRACE_LEVEL_NONE) ||
3324 				   (cinfo[i].category_verbose_mask ==
3325 				   QDF_TRACE_LEVEL_TO_MODULE_BITMASK(
3326 				   QDF_TRACE_LEVEL_NONE))) {
3327 				print_ctrl_obj[idx].cat_info[i]
3328 				.category_verbose_mask = 0;
3329 			} else {
3330 				print_ctrl_obj[idx].cat_info[i]
3331 				.category_verbose_mask =
3332 				cinfo[i].category_verbose_mask;
3333 			}
3334 		}
3335 	}
3336 
3337 	return idx;
3338 }
3339 qdf_export_symbol(qdf_print_ctrl_register);
3340 
3341 #ifdef QDF_TRACE_PRINT_ENABLE
3342 void qdf_shared_print_ctrl_cleanup(void)
3343 {
3344 	qdf_print_ctrl_cleanup(qdf_pidx);
3345 }
3346 qdf_export_symbol(qdf_shared_print_ctrl_cleanup);
3347 
3348 /*
3349  * Set this to invalid value to differentiate with user-provided
3350  * value.
3351  */
3352 int qdf_dbg_mask = QDF_TRACE_LEVEL_MAX;
3353 qdf_export_symbol(qdf_dbg_mask);
3354 qdf_declare_param(qdf_dbg_mask, int);
3355 
3356 /*
3357  * QDF can be passed parameters which indicate the
3358  * debug level for each module.
3359  * an array of string values are passed, each string hold the following form
3360  *
3361  * <module name string>=<integer debug level value>
3362  *
3363  * The array qdf_dbg_arr will hold these module-string=value strings
3364  * The variable qdf_dbg_arr_cnt will have the count of how many such
3365  * string values were passed.
3366  */
3367 static char *qdf_dbg_arr[QDF_MODULE_ID_MAX];
3368 static int qdf_dbg_arr_cnt;
3369 qdf_declare_param_array(qdf_dbg_arr, charp, &qdf_dbg_arr_cnt);
3370 
3371 static uint16_t set_cumulative_verbose_mask(QDF_TRACE_LEVEL max_level)
3372 {
3373 	uint16_t category_verbose_mask = 0;
3374 	QDF_TRACE_LEVEL level;
3375 
3376 	for (level = QDF_TRACE_LEVEL_FATAL; level <= max_level; level++) {
3377 		category_verbose_mask |=
3378 			QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level);
3379 	}
3380 	return category_verbose_mask;
3381 }
3382 
3383 static QDF_MODULE_ID find_qdf_module_from_string(char *str)
3384 {
3385 	QDF_MODULE_ID mod_id;
3386 
3387 	for (mod_id = 0; mod_id < QDF_MODULE_ID_MAX; mod_id++) {
3388 		if (strcasecmp(str,
3389 				g_qdf_category_name[mod_id].category_name_str)
3390 				== 0) {
3391 			break;
3392 		}
3393 	}
3394 	return mod_id;
3395 }
3396 
3397 static void process_qdf_dbg_arr_param(struct category_info *cinfo,
3398 					int array_index)
3399 {
3400 	char *mod_val_str, *mod_str, *val_str;
3401 	unsigned long dbg_level;
3402 	QDF_MODULE_ID mod_id;
3403 
3404 	mod_val_str = qdf_dbg_arr[array_index];
3405 	mod_str = strsep(&mod_val_str, "=");
3406 	val_str = mod_val_str;
3407 	if (!val_str) {
3408 		pr_info("qdf_dbg_arr: %s not in the <mod>=<val> form\n",
3409 				mod_str);
3410 		return;
3411 	}
3412 
3413 	mod_id = find_qdf_module_from_string(mod_str);
3414 	if (mod_id >= QDF_MODULE_ID_MAX) {
3415 		pr_info("ERROR!!Module name %s not in the list of modules\n",
3416 				mod_str);
3417 		return;
3418 	}
3419 
3420 	if (kstrtol(val_str, 10, &dbg_level) < 0) {
3421 		pr_info("ERROR!!Invalid debug level for module: %s\n",
3422 				mod_str);
3423 		return;
3424 	}
3425 
3426 	if (dbg_level >= QDF_TRACE_LEVEL_MAX) {
3427 		pr_info("ERROR!!Debug level for %s too high", mod_str);
3428 		pr_info("max: %d given %lu\n", QDF_TRACE_LEVEL_MAX,
3429 				dbg_level);
3430 		return;
3431 	}
3432 
3433 	pr_info("User passed setting module %s(%d) to level %lu\n",
3434 			mod_str,
3435 			mod_id,
3436 			dbg_level);
3437 	cinfo[mod_id].category_verbose_mask =
3438 		set_cumulative_verbose_mask((QDF_TRACE_LEVEL)dbg_level);
3439 }
3440 
3441 static void set_default_trace_levels(struct category_info *cinfo)
3442 {
3443 	int i;
3444 	static QDF_TRACE_LEVEL module_trace_default_level[QDF_MODULE_ID_MAX] = {
3445 		[QDF_MODULE_ID_TDLS] = QDF_TRACE_LEVEL_NONE,
3446 		[QDF_MODULE_ID_ACS] = QDF_TRACE_LEVEL_NONE,
3447 		[QDF_MODULE_ID_SCAN_SM] = QDF_TRACE_LEVEL_NONE,
3448 		[QDF_MODULE_ID_SCANENTRY] = QDF_TRACE_LEVEL_NONE,
3449 		[QDF_MODULE_ID_WDS] = QDF_TRACE_LEVEL_NONE,
3450 		[QDF_MODULE_ID_ACTION] = QDF_TRACE_LEVEL_NONE,
3451 		[QDF_MODULE_ID_ROAM] = QDF_TRACE_LEVEL_NONE,
3452 		[QDF_MODULE_ID_INACT] = QDF_TRACE_LEVEL_NONE,
3453 		[QDF_MODULE_ID_DOTH] = QDF_TRACE_LEVEL_NONE,
3454 		[QDF_MODULE_ID_IQUE] = QDF_TRACE_LEVEL_NONE,
3455 		[QDF_MODULE_ID_WME] = QDF_TRACE_LEVEL_NONE,
3456 		[QDF_MODULE_ID_ACL] = QDF_TRACE_LEVEL_NONE,
3457 		[QDF_MODULE_ID_WPA] = QDF_TRACE_LEVEL_NONE,
3458 		[QDF_MODULE_ID_RADKEYS] = QDF_TRACE_LEVEL_NONE,
3459 		[QDF_MODULE_ID_RADDUMP] = QDF_TRACE_LEVEL_NONE,
3460 		[QDF_MODULE_ID_RADIUS] = QDF_TRACE_LEVEL_NONE,
3461 		[QDF_MODULE_ID_DOT1XSM] = QDF_TRACE_LEVEL_NONE,
3462 		[QDF_MODULE_ID_DOT1X] = QDF_TRACE_LEVEL_NONE,
3463 		[QDF_MODULE_ID_POWER] = QDF_TRACE_LEVEL_NONE,
3464 		[QDF_MODULE_ID_STATE] = QDF_TRACE_LEVEL_NONE,
3465 		[QDF_MODULE_ID_OUTPUT] = QDF_TRACE_LEVEL_NONE,
3466 		[QDF_MODULE_ID_SCAN] = QDF_TRACE_LEVEL_ERROR,
3467 		[QDF_MODULE_ID_AUTH] = QDF_TRACE_LEVEL_NONE,
3468 		[QDF_MODULE_ID_ASSOC] = QDF_TRACE_LEVEL_NONE,
3469 		[QDF_MODULE_ID_NODE] = QDF_TRACE_LEVEL_NONE,
3470 		[QDF_MODULE_ID_ELEMID] = QDF_TRACE_LEVEL_NONE,
3471 		[QDF_MODULE_ID_XRATE] = QDF_TRACE_LEVEL_NONE,
3472 		[QDF_MODULE_ID_INPUT] = QDF_TRACE_LEVEL_NONE,
3473 		[QDF_MODULE_ID_CRYPTO] = QDF_TRACE_LEVEL_NONE,
3474 		[QDF_MODULE_ID_DUMPPKTS] = QDF_TRACE_LEVEL_NONE,
3475 		[QDF_MODULE_ID_DEBUG] = QDF_TRACE_LEVEL_NONE,
3476 		[QDF_MODULE_ID_MLME] = QDF_TRACE_LEVEL_ERROR,
3477 		[QDF_MODULE_ID_RRM] = QDF_TRACE_LEVEL_NONE,
3478 		[QDF_MODULE_ID_WNM] = QDF_TRACE_LEVEL_NONE,
3479 		[QDF_MODULE_ID_P2P_PROT] = QDF_TRACE_LEVEL_NONE,
3480 		[QDF_MODULE_ID_PROXYARP] = QDF_TRACE_LEVEL_NONE,
3481 		[QDF_MODULE_ID_L2TIF] = QDF_TRACE_LEVEL_NONE,
3482 		[QDF_MODULE_ID_WIFIPOS] = QDF_TRACE_LEVEL_NONE,
3483 		[QDF_MODULE_ID_WRAP] = QDF_TRACE_LEVEL_NONE,
3484 		[QDF_MODULE_ID_DFS] = QDF_TRACE_LEVEL_NONE,
3485 		[QDF_MODULE_ID_ATF] = QDF_TRACE_LEVEL_ERROR,
3486 		[QDF_MODULE_ID_SPLITMAC] = QDF_TRACE_LEVEL_NONE,
3487 		[QDF_MODULE_ID_IOCTL] = QDF_TRACE_LEVEL_NONE,
3488 		[QDF_MODULE_ID_NAC] = QDF_TRACE_LEVEL_NONE,
3489 		[QDF_MODULE_ID_MESH] = QDF_TRACE_LEVEL_NONE,
3490 		[QDF_MODULE_ID_MBO] = QDF_TRACE_LEVEL_NONE,
3491 		[QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = QDF_TRACE_LEVEL_NONE,
3492 		[QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = QDF_TRACE_LEVEL_NONE,
3493 		[QDF_MODULE_ID_TLSHIM] = QDF_TRACE_LEVEL_NONE,
3494 		[QDF_MODULE_ID_WMI] = QDF_TRACE_LEVEL_ERROR,
3495 		[QDF_MODULE_ID_HTT] = QDF_TRACE_LEVEL_NONE,
3496 		[QDF_MODULE_ID_HDD] = QDF_TRACE_LEVEL_NONE,
3497 		[QDF_MODULE_ID_SME] = QDF_TRACE_LEVEL_NONE,
3498 		[QDF_MODULE_ID_PE] = QDF_TRACE_LEVEL_NONE,
3499 		[QDF_MODULE_ID_WMA] = QDF_TRACE_LEVEL_NONE,
3500 		[QDF_MODULE_ID_SYS] = QDF_TRACE_LEVEL_NONE,
3501 		[QDF_MODULE_ID_QDF] = QDF_TRACE_LEVEL_ERROR,
3502 		[QDF_MODULE_ID_SAP] = QDF_TRACE_LEVEL_NONE,
3503 		[QDF_MODULE_ID_HDD_SOFTAP] = QDF_TRACE_LEVEL_NONE,
3504 		[QDF_MODULE_ID_HDD_DATA] = QDF_TRACE_LEVEL_NONE,
3505 		[QDF_MODULE_ID_HDD_SAP_DATA] = QDF_TRACE_LEVEL_NONE,
3506 		[QDF_MODULE_ID_HIF] = QDF_TRACE_LEVEL_ERROR,
3507 		[QDF_MODULE_ID_HTC] = QDF_TRACE_LEVEL_NONE,
3508 		[QDF_MODULE_ID_TXRX] = QDF_TRACE_LEVEL_NONE,
3509 		[QDF_MODULE_ID_QDF_DEVICE] = QDF_TRACE_LEVEL_NONE,
3510 		[QDF_MODULE_ID_CFG] = QDF_TRACE_LEVEL_NONE,
3511 		[QDF_MODULE_ID_BMI] = QDF_TRACE_LEVEL_NONE,
3512 		[QDF_MODULE_ID_EPPING] = QDF_TRACE_LEVEL_NONE,
3513 		[QDF_MODULE_ID_QVIT] = QDF_TRACE_LEVEL_NONE,
3514 		[QDF_MODULE_ID_DP] = QDF_TRACE_LEVEL_FATAL,
3515 		[QDF_MODULE_ID_HAL] = QDF_TRACE_LEVEL_NONE,
3516 		[QDF_MODULE_ID_SOC] = QDF_TRACE_LEVEL_NONE,
3517 		[QDF_MODULE_ID_OS_IF] = QDF_TRACE_LEVEL_NONE,
3518 		[QDF_MODULE_ID_TARGET_IF] = QDF_TRACE_LEVEL_INFO,
3519 		[QDF_MODULE_ID_SCHEDULER] = QDF_TRACE_LEVEL_FATAL,
3520 		[QDF_MODULE_ID_MGMT_TXRX] = QDF_TRACE_LEVEL_NONE,
3521 		[QDF_MODULE_ID_SERIALIZATION] = QDF_TRACE_LEVEL_ERROR,
3522 		[QDF_MODULE_ID_PMO] = QDF_TRACE_LEVEL_NONE,
3523 		[QDF_MODULE_ID_P2P] = QDF_TRACE_LEVEL_NONE,
3524 		[QDF_MODULE_ID_POLICY_MGR] = QDF_TRACE_LEVEL_NONE,
3525 		[QDF_MODULE_ID_CONFIG] = QDF_TRACE_LEVEL_ERROR,
3526 		[QDF_MODULE_ID_REGULATORY] = QDF_TRACE_LEVEL_NONE,
3527 		[QDF_MODULE_ID_SA_API] = QDF_TRACE_LEVEL_NONE,
3528 		[QDF_MODULE_ID_NAN] = QDF_TRACE_LEVEL_NONE,
3529 		[QDF_MODULE_ID_OFFCHAN_TXRX] = QDF_TRACE_LEVEL_NONE,
3530 		[QDF_MODULE_ID_SON] = QDF_TRACE_LEVEL_NONE,
3531 		[QDF_MODULE_ID_SPECTRAL] = QDF_TRACE_LEVEL_ERROR,
3532 		[QDF_MODULE_ID_OBJ_MGR] = QDF_TRACE_LEVEL_FATAL,
3533 		[QDF_MODULE_ID_NSS] = QDF_TRACE_LEVEL_ERROR,
3534 		[QDF_MODULE_ID_ROAM_DEBUG] = QDF_TRACE_LEVEL_ERROR,
3535 		[QDF_MODULE_ID_CDP] = QDF_TRACE_LEVEL_NONE,
3536 		[QDF_MODULE_ID_DIRECT_BUF_RX] = QDF_TRACE_LEVEL_ERROR,
3537 		[QDF_MODULE_ID_DISA] = QDF_TRACE_LEVEL_NONE,
3538 		[QDF_MODULE_ID_GREEN_AP] = QDF_TRACE_LEVEL_ERROR,
3539 		[QDF_MODULE_ID_FTM] = QDF_TRACE_LEVEL_ERROR,
3540 		[QDF_MODULE_ID_EXTAP] = QDF_TRACE_LEVEL_NONE,
3541 		[QDF_MODULE_ID_FD] = QDF_TRACE_LEVEL_ERROR,
3542 		[QDF_MODULE_ID_OCB] = QDF_TRACE_LEVEL_ERROR,
3543 		[QDF_MODULE_ID_IPA] = QDF_TRACE_LEVEL_NONE,
3544 		[QDF_MODULE_ID_ACTION_OUI] = QDF_TRACE_LEVEL_NONE,
3545 		[QDF_MODULE_ID_CP_STATS] = QDF_TRACE_LEVEL_ERROR,
3546 		[QDF_MODULE_ID_MBSSIE] = QDF_TRACE_LEVEL_INFO,
3547 		[QDF_MODULE_ID_FWOL] = QDF_TRACE_LEVEL_NONE,
3548 		[QDF_MODULE_ID_SM_ENGINE] = QDF_TRACE_LEVEL_ERROR,
3549 		[QDF_MODULE_ID_CMN_MLME] = QDF_TRACE_LEVEL_INFO,
3550 		[QDF_MODULE_ID_BSSCOLOR] = QDF_TRACE_LEVEL_ERROR,
3551 		[QDF_MODULE_ID_CFR] = QDF_TRACE_LEVEL_ERROR,
3552 		[QDF_MODULE_ID_TX_CAPTURE] = QDF_TRACE_LEVEL_NONE,
3553 		[QDF_MODULE_ID_INTEROP_ISSUES_AP] = QDF_TRACE_LEVEL_NONE,
3554 		[QDF_MODULE_ID_BLACKLIST_MGR] = QDF_TRACE_LEVEL_NONE,
3555 		[QDF_MODULE_ID_QLD] = QDF_TRACE_LEVEL_ERROR,
3556 		[QDF_MODULE_ID_DYNAMIC_MODE_CHG] = QDF_TRACE_LEVEL_INFO,
3557 		[QDF_MODULE_ID_COEX] = QDF_TRACE_LEVEL_ERROR,
3558 		[QDF_MODULE_ID_MON_FILTER] = QDF_TRACE_LEVEL_INFO,
3559 		[QDF_MODULE_ID_ANY] = QDF_TRACE_LEVEL_INFO,
3560 		[QDF_MODULE_ID_PKT_CAPTURE] = QDF_TRACE_LEVEL_NONE,
3561 	};
3562 
3563 	for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3564 		cinfo[i].category_verbose_mask = set_cumulative_verbose_mask(
3565 				module_trace_default_level[i]);
3566 	}
3567 }
3568 
3569 void qdf_shared_print_ctrl_init(void)
3570 {
3571 	int i;
3572 	struct category_info cinfo[MAX_SUPPORTED_CATEGORY];
3573 
3574 	set_default_trace_levels(cinfo);
3575 
3576 	/*
3577 	 * User specified across-module single debug level
3578 	 */
3579 	if ((qdf_dbg_mask >= 0) && (qdf_dbg_mask < QDF_TRACE_LEVEL_MAX)) {
3580 		pr_info("User specified module debug level of %d\n",
3581 			qdf_dbg_mask);
3582 		for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3583 			cinfo[i].category_verbose_mask =
3584 			set_cumulative_verbose_mask(qdf_dbg_mask);
3585 		}
3586 	} else if (qdf_dbg_mask != QDF_TRACE_LEVEL_MAX) {
3587 		pr_info("qdf_dbg_mask value is invalid\n");
3588 		pr_info("Using the default module debug levels instead\n");
3589 	}
3590 
3591 	/*
3592 	 * Module ID-Level specified as array during module load
3593 	 */
3594 	for (i = 0; i < qdf_dbg_arr_cnt; i++) {
3595 		process_qdf_dbg_arr_param(cinfo, i);
3596 	}
3597 	qdf_pidx = qdf_print_ctrl_register(cinfo, NULL, NULL,
3598 			"LOG_SHARED_OBJ");
3599 }
3600 qdf_export_symbol(qdf_shared_print_ctrl_init);
3601 #endif
3602 
3603 QDF_STATUS qdf_print_set_category_verbose(unsigned int idx,
3604 						QDF_MODULE_ID category,
3605 						QDF_TRACE_LEVEL verbose,
3606 						bool is_set)
3607 {
3608 	/* Check if index passed is valid */
3609 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3610 		pr_err("%s: Invalid index - %d\n", __func__, idx);
3611 		return QDF_STATUS_E_FAILURE;
3612 	}
3613 
3614 	/* Check if print control object is in use */
3615 	if (!print_ctrl_obj[idx].in_use) {
3616 		pr_err("%s: Invalid print control object\n", __func__);
3617 		return QDF_STATUS_E_FAILURE;
3618 	}
3619 
3620 	/* Check if category passed is valid */
3621 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
3622 		pr_err("%s: Invalid category: %d\n", __func__, category);
3623 		return QDF_STATUS_E_FAILURE;
3624 	}
3625 
3626 	/* Check if verbose mask is valid */
3627 	if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
3628 		pr_err("%s: Invalid verbose level %d\n", __func__, verbose);
3629 		return QDF_STATUS_E_FAILURE;
3630 	}
3631 
3632 	if (verbose == QDF_TRACE_LEVEL_ALL) {
3633 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
3634 				0xFFFF;
3635 		return QDF_STATUS_SUCCESS;
3636 	}
3637 
3638 	if (verbose == QDF_TRACE_LEVEL_NONE) {
3639 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
3640 				QDF_TRACE_LEVEL_NONE;
3641 		return QDF_STATUS_SUCCESS;
3642 	}
3643 
3644 	if (!is_set) {
3645 		if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask
3646 		    & QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
3647 			print_ctrl_obj[idx].cat_info[category]
3648 				.category_verbose_mask &=
3649 				~QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
3650 		}
3651 	} else {
3652 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask |=
3653 				QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
3654 	}
3655 
3656 	pr_debug("%s: Print control object %d, Category %d, Verbose level %d\n",
3657 		__func__,
3658 		idx,
3659 		category,
3660 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask);
3661 
3662 	return QDF_STATUS_SUCCESS;
3663 }
3664 qdf_export_symbol(qdf_print_set_category_verbose);
3665 
3666 void qdf_log_dump_at_kernel_level(bool enable)
3667 {
3668 	if (qdf_log_dump_at_kernel_enable == enable) {
3669 		QDF_TRACE_INFO(QDF_MODULE_ID_QDF,
3670 			       "qdf_log_dump_at_kernel_enable is already %d\n",
3671 			       enable);
3672 	}
3673 	qdf_log_dump_at_kernel_enable = enable;
3674 }
3675 
3676 qdf_export_symbol(qdf_log_dump_at_kernel_level);
3677 
3678 bool qdf_print_is_category_enabled(unsigned int idx, QDF_MODULE_ID category)
3679 {
3680 	QDF_TRACE_LEVEL verbose_mask;
3681 
3682 	/* Check if index passed is valid */
3683 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3684 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3685 		return false;
3686 	}
3687 
3688 	/* Check if print control object is in use */
3689 	if (!print_ctrl_obj[idx].in_use) {
3690 		pr_info("%s: Invalid print control object\n", __func__);
3691 		return false;
3692 	}
3693 
3694 	/* Check if category passed is valid */
3695 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
3696 		pr_info("%s: Invalid category: %d\n", __func__, category);
3697 		return false;
3698 	}
3699 
3700 	verbose_mask =
3701 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask;
3702 
3703 	if (verbose_mask == QDF_TRACE_LEVEL_NONE)
3704 		return false;
3705 	else
3706 		return true;
3707 }
3708 qdf_export_symbol(qdf_print_is_category_enabled);
3709 
3710 bool qdf_print_is_verbose_enabled(unsigned int idx, QDF_MODULE_ID category,
3711 				  QDF_TRACE_LEVEL verbose)
3712 {
3713 	bool verbose_enabled = false;
3714 
3715 	/* Check if index passed is valid */
3716 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3717 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3718 		return verbose_enabled;
3719 	}
3720 
3721 	/* Check if print control object is in use */
3722 	if (!print_ctrl_obj[idx].in_use) {
3723 		pr_info("%s: Invalid print control object\n", __func__);
3724 		return verbose_enabled;
3725 	}
3726 
3727 	/* Check if category passed is valid */
3728 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
3729 		pr_info("%s: Invalid category: %d\n", __func__, category);
3730 		return verbose_enabled;
3731 	}
3732 
3733 	if ((verbose == QDF_TRACE_LEVEL_NONE) ||
3734 	    (verbose >= QDF_TRACE_LEVEL_MAX)) {
3735 		verbose_enabled = false;
3736 	} else if (verbose == QDF_TRACE_LEVEL_ALL) {
3737 		if (print_ctrl_obj[idx].cat_info[category]
3738 					.category_verbose_mask == 0xFFFF)
3739 			verbose_enabled = true;
3740 	} else {
3741 		verbose_enabled =
3742 		(print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
3743 		 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) ? true : false;
3744 	}
3745 
3746 	return verbose_enabled;
3747 }
3748 qdf_export_symbol(qdf_print_is_verbose_enabled);
3749 
3750 #ifdef DBG_LVL_MAC_FILTERING
3751 
3752 QDF_STATUS qdf_print_set_node_flag(unsigned int idx, uint8_t enable)
3753 {
3754 	/* Check if index passed is valid */
3755 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3756 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3757 		return QDF_STATUS_E_FAILURE;
3758 	}
3759 
3760 	/* Check if print control object is in use */
3761 	if (!print_ctrl_obj[idx].in_use) {
3762 		pr_info("%s: Invalid print control object\n", __func__);
3763 		return QDF_STATUS_E_FAILURE;
3764 	}
3765 
3766 	if (enable > 1) {
3767 		pr_info("%s: Incorrect input: Use 1 or 0 to enable or disable\n",
3768 			__func__);
3769 		return QDF_STATUS_E_FAILURE;
3770 	}
3771 
3772 	print_ctrl_obj[idx].dbglvlmac_on = enable;
3773 	pr_info("%s: DbgLVLmac feature %s\n",
3774 		__func__,
3775 		((enable) ? "enabled" : "disabled"));
3776 
3777 	return QDF_STATUS_SUCCESS;
3778 }
3779 qdf_export_symbol(qdf_print_set_node_flag);
3780 
3781 bool qdf_print_get_node_flag(unsigned int idx)
3782 {
3783 	bool node_flag = false;
3784 
3785 	/* Check if index passed is valid */
3786 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3787 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3788 		return node_flag;
3789 	}
3790 
3791 	/* Check if print control object is in use */
3792 	if (!print_ctrl_obj[idx].in_use) {
3793 		pr_info("%s: Invalid print control object\n", __func__);
3794 		return node_flag;
3795 	}
3796 
3797 	if (print_ctrl_obj[idx].dbglvlmac_on)
3798 		node_flag = true;
3799 
3800 	return node_flag;
3801 }
3802 qdf_export_symbol(qdf_print_get_node_flag);
3803 
3804 void qdf_print_clean_node_flag(unsigned int idx)
3805 {
3806 	/* Disable dbglvlmac_on during cleanup */
3807 	print_ctrl_obj[idx].dbglvlmac_on = 0;
3808 }
3809 
3810 #else
3811 
3812 void qdf_print_clean_node_flag(unsigned int idx)
3813 {
3814 	/* No operation in case of no support for DBG_LVL_MAC_FILTERING */
3815 	return;
3816 }
3817 #endif
3818 
3819 void QDF_PRINT_INFO(unsigned int idx, QDF_MODULE_ID module,
3820 		    QDF_TRACE_LEVEL level,
3821 		    char *str_format, ...)
3822 {
3823 	va_list args;
3824 
3825 	/* Generic wrapper API will compile qdf_vprint in order to
3826 	 * log the message. Once QDF converged debug framework is in
3827 	 * place, this will be changed to adapt to the framework, compiling
3828 	 * call to converged tracing API
3829 	 */
3830 	va_start(args, str_format);
3831 	qdf_vprint(str_format, args);
3832 	va_end(args);
3833 }
3834 qdf_export_symbol(QDF_PRINT_INFO);
3835 
3836 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
3837 void qdf_logging_init(void)
3838 {
3839 	wlan_logging_sock_init_svc();
3840 	nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY);
3841 	wlan_logging_set_flush_timer(qdf_log_flush_timer_period);
3842 }
3843 
3844 void qdf_logging_exit(void)
3845 {
3846 	nl_srv_exit();
3847 	wlan_logging_sock_deinit_svc();
3848 }
3849 
3850 int qdf_logging_set_flush_timer(uint32_t milliseconds)
3851 {
3852 	if (wlan_logging_set_flush_timer(milliseconds) == 0)
3853 		return QDF_STATUS_SUCCESS;
3854 	else
3855 		return QDF_STATUS_E_FAILURE;
3856 }
3857 
3858 void qdf_logging_flush_logs(void)
3859 {
3860 	wlan_flush_host_logs_for_fatal();
3861 }
3862 
3863 #else
3864 void qdf_logging_init(void)
3865 {
3866 	nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY);
3867 }
3868 
3869 void qdf_logging_exit(void)
3870 {
3871 	nl_srv_exit();
3872 }
3873 
3874 int qdf_logging_set_flush_timer(uint32_t milliseconds)
3875 {
3876 	return QDF_STATUS_E_FAILURE;
3877 }
3878 
3879 void qdf_logging_flush_logs(void)
3880 {
3881 }
3882 #endif
3883 
3884 qdf_export_symbol(qdf_logging_set_flush_timer);
3885 qdf_export_symbol(qdf_logging_flush_logs);
3886 
3887 #ifdef CONFIG_KALLSYMS
3888 inline int qdf_sprint_symbol(char *buffer, void *addr)
3889 {
3890 	return sprint_symbol(buffer, (unsigned long)addr);
3891 }
3892 #else
3893 int qdf_sprint_symbol(char *buffer, void *addr)
3894 {
3895 	if (!buffer)
3896 		return 0;
3897 
3898 	buffer[0] = '\0';
3899 	return 1;
3900 }
3901 #endif
3902 qdf_export_symbol(qdf_sprint_symbol);
3903 
3904 void qdf_set_pidx(int pidx)
3905 {
3906 	qdf_pidx = pidx;
3907 }
3908 qdf_export_symbol(qdf_set_pidx);
3909 
3910 int qdf_get_pidx(void)
3911 {
3912 	return qdf_pidx;
3913 }
3914 qdf_export_symbol(qdf_get_pidx);
3915 
3916 #ifdef PANIC_ON_BUG
3917 #ifdef CONFIG_SLUB_DEBUG
3918 void __qdf_bug(void)
3919 {
3920 	BUG();
3921 }
3922 qdf_export_symbol(__qdf_bug);
3923 #endif /* CONFIG_SLUB_DEBUG */
3924 #endif /* PANIC_ON_BUG */
3925 
3926