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