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