xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/qdf_trace.c (revision 5bae17edf3b450753abb053863a3fae314d10229)
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 	struct qdf_dp_trace_proto_cmn cmn_info;
1509 
1510 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMPv6) &&
1511 		((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ICMPv6 ==
1512 			QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1513 		 (dir == QDF_RX && qdf_nbuf_is_icmpv6_pkt(skb) == true))) {
1514 
1515 		subtype = qdf_nbuf_get_icmpv6_subtype(skb);
1516 
1517 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false;
1518 		if (dir == QDF_TX)
1519 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1520 		else if (dir == QDF_RX)
1521 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1522 
1523 		cmn_info.vdev_id = vdev_id;
1524 		cmn_info.type = QDF_PROTO_TYPE_ICMPv6;
1525 		cmn_info.subtype = subtype;
1526 		cmn_info.proto_priv_data = 0;
1527 		cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb);
1528 		DPTRACE(qdf_dp_trace_proto_pkt(
1529 			QDF_DP_TRACE_ICMPv6_PACKET_RECORD,
1530 			(skb->data + QDF_NBUF_SRC_MAC_OFFSET),
1531 			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
1532 			dir, pdev_id, false, &cmn_info));
1533 
1534 		switch (subtype) {
1535 		case QDF_PROTO_ICMPV6_REQ:
1536 			g_qdf_dp_trace_data.icmpv6_req++;
1537 			break;
1538 		case QDF_PROTO_ICMPV6_RES:
1539 			g_qdf_dp_trace_data.icmpv6_resp++;
1540 			break;
1541 		case QDF_PROTO_ICMPV6_RS:
1542 			g_qdf_dp_trace_data.icmpv6_rs++;
1543 			break;
1544 		case QDF_PROTO_ICMPV6_RA:
1545 			g_qdf_dp_trace_data.icmpv6_ra++;
1546 			break;
1547 		case QDF_PROTO_ICMPV6_NS:
1548 			g_qdf_dp_trace_data.icmpv6_ns++;
1549 			break;
1550 		case QDF_PROTO_ICMPV6_NA:
1551 			g_qdf_dp_trace_data.icmpv6_na++;
1552 			break;
1553 		default:
1554 			break;
1555 		}
1556 		return true;
1557 	}
1558 
1559 	return false;
1560 }
1561 
1562 /**
1563  * qdf_log_icmp_pkt() - log ICMP packet
1564  * @vdev_id: ID of the vdev
1565  * @skb: skb pointer
1566  * @dir: direction
1567  * @pdev_id: ID of the pdev
1568  *
1569  * Return: true/false
1570  */
1571 static bool qdf_log_icmp_pkt(uint8_t vdev_id, struct sk_buff *skb,
1572 			     enum qdf_proto_dir dir, uint8_t pdev_id)
1573 {
1574 	uint8_t *data = NULL;
1575 	uint16_t seq_num = 0;
1576 	uint16_t icmp_id = 0;
1577 	struct qdf_dp_trace_proto_cmn cmn_info;
1578 
1579 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMP) &&
1580 	    (qdf_nbuf_is_icmp_pkt(skb) == true)) {
1581 
1582 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false;
1583 		cmn_info.subtype = qdf_nbuf_get_icmp_subtype(skb);
1584 
1585 		data = qdf_nbuf_data(skb);
1586 		icmp_id = qdf_cpu_to_be16(*(uint16_t *)(data + ICMP_ID_OFFSET));
1587 		seq_num = qdf_cpu_to_be16(*(uint16_t *)(data + ICMP_SEQ_NUM_OFFSET));
1588 
1589 		cmn_info.proto_priv_data = ((uint32_t)icmp_id) << 16;
1590 		cmn_info.proto_priv_data |= (uint32_t)seq_num;
1591 		cmn_info.type = QDF_PROTO_TYPE_ICMP;
1592 		cmn_info.vdev_id = vdev_id;
1593 		cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb);
1594 
1595 		if (QDF_TX == dir)
1596 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1597 		else if (QDF_RX == dir)
1598 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1599 
1600 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ICMP_PACKET_RECORD,
1601 					       skb->data +
1602 					       QDF_NBUF_SRC_MAC_OFFSET,
1603 					       skb->data +
1604 					       QDF_NBUF_DEST_MAC_OFFSET,
1605 					       dir, pdev_id,
1606 					       false, &cmn_info));
1607 
1608 		if (cmn_info.subtype == QDF_PROTO_ICMP_REQ)
1609 			g_qdf_dp_trace_data.icmp_req++;
1610 		else
1611 			g_qdf_dp_trace_data.icmp_resp++;
1612 
1613 		return true;
1614 	}
1615 	return false;
1616 }
1617 
1618 #ifdef CONNECTIVITY_DIAG_EVENT
1619 enum diag_tx_status wlan_get_diag_tx_status(enum qdf_dp_tx_rx_status tx_status)
1620 {
1621 	switch (tx_status) {
1622 	case DIAG_TX_RX_STATUS_FW_DISCARD:
1623 	case DIAG_TX_RX_STATUS_INVALID:
1624 	case DIAG_TX_RX_STATUS_DROP:
1625 	case DIAG_TX_RX_STATUS_DOWNLOAD_SUCC:
1626 	case DIAG_TX_RX_STATUS_DEFAULT:
1627 	default:
1628 		return DIAG_TX_STATUS_FAIL;
1629 	case DIAG_TX_RX_STATUS_NO_ACK:
1630 		return DIAG_TX_STATUS_NO_ACK;
1631 	case DIAG_TX_RX_STATUS_OK:
1632 		return DIAG_TX_STATUS_ACK;
1633 	}
1634 
1635 	return DIAG_TX_STATUS_FAIL;
1636 }
1637 
1638 /**
1639  * qdf_subtype_to_wlan_main_tag() - Convert qdf subtype to wlan main tag
1640  * @subtype: EAPoL key subtype
1641  *
1642  * Return: Wlan main tag subtype
1643  */
1644 static int qdf_subtype_to_wlan_main_tag(enum qdf_proto_subtype subtype)
1645 {
1646 	switch (subtype) {
1647 	case QDF_PROTO_DHCP_DISCOVER:
1648 		return WLAN_CONN_DIAG_DHCP_DISC_EVENT;
1649 	case QDF_PROTO_DHCP_REQUEST:
1650 		return WLAN_CONN_DIAG_DHCP_REQUEST_EVENT;
1651 	case QDF_PROTO_DHCP_OFFER:
1652 		return WLAN_CONN_DIAG_DHCP_OFFER_EVENT;
1653 	case QDF_PROTO_DHCP_ACK:
1654 		return WLAN_CONN_DIAG_DHCP_ACK_EVENT;
1655 	case QDF_PROTO_DHCP_NACK:
1656 		return WLAN_CONN_DIAG_DHCP_NACK_EVENT;
1657 	case QDF_PROTO_EAPOL_M1:
1658 		return WLAN_CONN_DIAG_EAPOL_M1_EVENT;
1659 	case QDF_PROTO_EAPOL_M2:
1660 		return WLAN_CONN_DIAG_EAPOL_M2_EVENT;
1661 	case QDF_PROTO_EAPOL_M3:
1662 		return WLAN_CONN_DIAG_EAPOL_M3_EVENT;
1663 	case QDF_PROTO_EAPOL_M4:
1664 		return WLAN_CONN_DIAG_EAPOL_M4_EVENT;
1665 	case QDF_PROTO_EAP_REQUEST:
1666 		return WLAN_CONN_DIAG_EAP_REQ_EVENT;
1667 	case QDF_PROTO_EAP_RESPONSE:
1668 		return WLAN_CONN_DIAG_EAP_RESP_EVENT;
1669 	case QDF_PROTO_EAP_SUCCESS:
1670 		return WLAN_CONN_DIAG_EAP_SUCC_EVENT;
1671 	case QDF_PROTO_EAP_FAILURE:
1672 		return WLAN_CONN_DIAG_EAP_FAIL_EVENT;
1673 	case QDF_PROTO_EAPOL_START:
1674 		return WLAN_CONN_DIAG_EAP_START_EVENT;
1675 	default:
1676 		return WLAN_CONN_DIAG_MAX;
1677 	}
1678 }
1679 
1680 /**
1681  * qdf_get_wlan_eap_code() - Get EAP code
1682  * @data: skb data pointer
1683  *
1684  * Return: EAP code value
1685  */
1686 static int qdf_get_wlan_eap_code(uint8_t *data)
1687 {
1688 	uint8_t code = *(data + EAP_CODE_OFFSET);
1689 
1690 	switch (code) {
1691 	case QDF_EAP_REQUEST:
1692 		return WLAN_CONN_DIAG_EAP_REQ_EVENT;
1693 	case QDF_EAP_RESPONSE:
1694 		return WLAN_CONN_DIAG_EAP_RESP_EVENT;
1695 	case QDF_EAP_SUCCESS:
1696 		return WLAN_CONN_DIAG_EAP_SUCC_EVENT;
1697 	case QDF_EAP_FAILURE:
1698 		return WLAN_CONN_DIAG_EAP_FAIL_EVENT;
1699 	default:
1700 		return WLAN_CONN_DIAG_MAX;
1701 	}
1702 }
1703 
1704 /**
1705  * qdf_eapol_get_key_type() - Get EAPOL key type
1706  * @data: skb data pointer
1707  * @subtype: EAPoL key subtype
1708  *
1709  * Return: EAPOL key type
1710  */
1711 static
1712 uint8_t qdf_eapol_get_key_type(uint8_t *data, enum qdf_proto_subtype subtype)
1713 {
1714 	uint16_t key_info = *(uint16_t *)(data + EAPOL_KEY_INFO_OFFSET);
1715 
1716 	/* If key type is PTK, key type will be set in EAPOL Key info */
1717 	if (key_info & EAPOL_KEY_TYPE_MASK)
1718 		return qdf_subtype_to_wlan_main_tag(subtype);
1719 	else if (key_info & EAPOL_KEY_ENCRYPTED_MASK)
1720 		return WLAN_CONN_DIAG_GTK_M1_EVENT;
1721 	else
1722 		return WLAN_CONN_DIAG_GTK_M2_EVENT;
1723 }
1724 
1725 /**
1726  * qdf_skip_wlan_connectivity_log() - Check if connectivity log need to skip
1727  * @type: Protocol type
1728  * @subtype: Protocol subtype
1729  * @dir: Rx or Tx
1730  * @op_mode: Vdev Operation mode
1731  *
1732  * Return: true or false
1733  */
1734 static inline
1735 bool qdf_skip_wlan_connectivity_log(enum qdf_proto_type type,
1736 				    enum qdf_proto_subtype subtype,
1737 				    enum qdf_proto_dir dir,
1738 				    enum QDF_OPMODE op_mode)
1739 {
1740 	if (op_mode != QDF_STA_MODE)
1741 		return true;
1742 
1743 	if (dir == QDF_RX && type == QDF_PROTO_TYPE_DHCP &&
1744 	    (subtype == QDF_PROTO_DHCP_DISCOVER ||
1745 	     subtype == QDF_PROTO_DHCP_REQUEST))
1746 		return true;
1747 	return false;
1748 }
1749 
1750 /**
1751  * qdf_fill_wlan_connectivity_log() - Fill and queue protocol packet to logging
1752  * the logging queue
1753  * @type: Protocol type
1754  * @subtype: Protocol subtype
1755  * @dir: Rx or Tx
1756  * @qdf_tx_status: Tx completion status
1757  * @op_mode: Vdev Operation mode
1758  * @vdev_id: DP vdev ID
1759  * @data: skb data pointer
1760  * @band: band
1761  *
1762  * Return: None
1763  */
1764 static
1765 void qdf_fill_wlan_connectivity_log(enum qdf_proto_type type,
1766 				    enum qdf_proto_subtype subtype,
1767 				    enum qdf_proto_dir dir,
1768 				    enum qdf_dp_tx_rx_status qdf_tx_status,
1769 				    enum QDF_OPMODE op_mode,
1770 				    uint8_t vdev_id, uint8_t *data,
1771 				    uint8_t band)
1772 {
1773 	uint8_t pkt_type;
1774 
1775 	WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_packet_info);
1776 
1777 	if (qdf_skip_wlan_connectivity_log(type, subtype, dir, op_mode))
1778 		return;
1779 
1780 	qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
1781 
1782 	wlan_diag_event.diag_cmn.timestamp_us =
1783 					qdf_get_time_of_the_day_ms() * 1000;
1784 	wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get());
1785 	wlan_diag_event.diag_cmn.vdev_id = vdev_id;
1786 
1787 	wlan_diag_event.version = DIAG_MGMT_VERSION_V2;
1788 
1789 	if (type == QDF_PROTO_TYPE_DHCP) {
1790 		wlan_diag_event.subtype =
1791 					qdf_subtype_to_wlan_main_tag(subtype);
1792 	} else if (type == QDF_PROTO_TYPE_EAPOL) {
1793 		pkt_type = *(data + EAPOL_PACKET_TYPE_OFFSET);
1794 		if (pkt_type == EAPOL_PACKET_TYPE_EAP) {
1795 			wlan_diag_event.subtype =
1796 						qdf_get_wlan_eap_code(data);
1797 			wlan_diag_event.eap_type =
1798 						*(data + EAP_TYPE_OFFSET);
1799 			wlan_diag_event.eap_len =
1800 			   qdf_ntohs(*(uint16_t *)(data + EAP_LENGTH_OFFSET));
1801 		} else if (pkt_type == EAPOL_PACKET_TYPE_KEY) {
1802 			wlan_diag_event.subtype =
1803 					qdf_eapol_get_key_type(data, subtype);
1804 		} else if (pkt_type == EAPOL_PACKET_TYPE_START) {
1805 			wlan_diag_event.subtype =
1806 					WLAN_CONN_DIAG_EAP_START_EVENT;
1807 			wlan_diag_event.eap_len =
1808 			    qdf_ntohs(*(uint16_t *)(data + EAPOL_PKT_LEN_OFFSET));
1809 		} else {
1810 			return;
1811 		}
1812 	} else {
1813 		return;
1814 	}
1815 
1816 	wlan_diag_event.supported_links = band;
1817 
1818 	/*Tx completion status needs to be logged*/
1819 	if (dir == QDF_TX) {
1820 		wlan_diag_event.is_tx = 1;
1821 		wlan_diag_event.tx_status =
1822 					wlan_get_diag_tx_status(qdf_tx_status);
1823 	}
1824 
1825 	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_CONN_DP);
1826 }
1827 
1828 #else
1829 static inline
1830 void qdf_fill_wlan_connectivity_log(enum qdf_proto_type type,
1831 				    enum qdf_proto_subtype subtype,
1832 				    enum qdf_proto_dir dir,
1833 				    enum qdf_dp_tx_rx_status qdf_tx_status,
1834 				    enum QDF_OPMODE op_mode,
1835 				    uint8_t vdev_id, uint8_t *data,
1836 				    uint8_t band)
1837 {
1838 }
1839 #endif
1840 
1841 /**
1842  * qdf_log_eapol_pkt() - log EAPOL packet
1843  * @vdev_id: ID of the vdev
1844  * @skb: skb pointer
1845  * @dir: direction
1846  * @pdev_id: ID of the pdev
1847  * @op_mode: Vdev Operation mode
1848  *
1849  * Return: true/false
1850  */
1851 static bool qdf_log_eapol_pkt(uint8_t vdev_id, struct sk_buff *skb,
1852 			      enum qdf_proto_dir dir, uint8_t pdev_id,
1853 				  enum QDF_OPMODE op_mode)
1854 {
1855 	enum qdf_proto_subtype subtype;
1856 	uint32_t dp_eap_trace;
1857 	uint32_t dp_eap_event;
1858 	struct qdf_dp_trace_proto_cmn cmn_info;
1859 
1860 	dp_eap_trace = qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
1861 	dp_eap_event = qdf_dp_get_proto_event_bitmap() &
1862 				QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
1863 
1864 	if (!dp_eap_trace && !dp_eap_event)
1865 		return false;
1866 
1867 	if (!((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_EAPOL ==
1868 	       QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1869 	      (dir == QDF_RX && qdf_nbuf_is_ipv4_eapol_pkt(skb) == true)))
1870 		return false;
1871 
1872 	subtype = qdf_nbuf_get_eapol_subtype(skb);
1873 
1874 	if (dp_eap_event && dir == QDF_RX) {
1875 		qdf_dp_log_proto_pkt_info(skb->data + QDF_NBUF_SRC_MAC_OFFSET,
1876 					  skb->data + QDF_NBUF_DEST_MAC_OFFSET,
1877 					  QDF_PROTO_TYPE_EAPOL, subtype, dir,
1878 					  QDF_TRACE_DEFAULT_MSDU_ID,
1879 					  QDF_TX_RX_STATUS_INVALID);
1880 		qdf_fill_wlan_connectivity_log(QDF_PROTO_TYPE_EAPOL, subtype,
1881 					       QDF_RX, 0, op_mode,
1882 					       vdev_id, skb->data,
1883 					       qdf_nbuf_rx_get_band(skb));
1884 	}
1885 
1886 	if (dp_eap_trace) {
1887 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
1888 		if (QDF_TX == dir)
1889 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1890 		else if (QDF_RX == dir)
1891 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1892 
1893 		cmn_info.vdev_id = vdev_id;
1894 		cmn_info.type = QDF_PROTO_TYPE_EAPOL;
1895 		cmn_info.subtype = subtype;
1896 		cmn_info.proto_priv_data = 0;
1897 		cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb);
1898 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_EAPOL_PACKET_RECORD,
1899 					       skb->data +
1900 					       QDF_NBUF_SRC_MAC_OFFSET,
1901 					       skb->data +
1902 					       QDF_NBUF_DEST_MAC_OFFSET,
1903 					       dir, pdev_id, true, &cmn_info));
1904 
1905 		switch (subtype) {
1906 		case QDF_PROTO_EAPOL_M1:
1907 			g_qdf_dp_trace_data.eapol_m1++;
1908 			break;
1909 		case QDF_PROTO_EAPOL_M2:
1910 			g_qdf_dp_trace_data.eapol_m2++;
1911 			break;
1912 		case QDF_PROTO_EAPOL_M3:
1913 			g_qdf_dp_trace_data.eapol_m3++;
1914 			break;
1915 		case QDF_PROTO_EAPOL_M4:
1916 			g_qdf_dp_trace_data.eapol_m4++;
1917 			break;
1918 		default:
1919 			g_qdf_dp_trace_data.eapol_others++;
1920 			break;
1921 		}
1922 	}
1923 
1924 	return true;
1925 }
1926 
1927 /**
1928  * qdf_log_dhcp_pkt() - log DHCP packet
1929  * @vdev_id: ID of the vdev
1930  * @skb: skb pointer
1931  * @dir: direction
1932  * @pdev_id: ID of the pdev
1933  * @op_mode: Vdev Operation mode
1934  *
1935  * Return: true/false
1936  */
1937 static bool qdf_log_dhcp_pkt(uint8_t vdev_id, struct sk_buff *skb,
1938 			     enum qdf_proto_dir dir, uint8_t pdev_id,
1939 			     enum QDF_OPMODE op_mode)
1940 {
1941 	enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
1942 	uint32_t dp_dhcp_trace;
1943 	uint32_t dp_dhcp_event;
1944 	struct qdf_dp_trace_proto_cmn cmn_info;
1945 
1946 	dp_dhcp_trace = qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_DHCP;
1947 	dp_dhcp_event = qdf_dp_get_proto_event_bitmap() &
1948 				QDF_NBUF_PKT_TRAC_TYPE_DHCP;
1949 
1950 	if (!dp_dhcp_trace && !dp_dhcp_event)
1951 		return false;
1952 
1953 	if (!((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_DHCP ==
1954 	       QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1955 	      (dir == QDF_RX && qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true)))
1956 		return false;
1957 
1958 	subtype = qdf_nbuf_get_dhcp_subtype(skb);
1959 
1960 	if (dp_dhcp_event && dir == QDF_RX) {
1961 		qdf_dp_log_proto_pkt_info(skb->data + QDF_NBUF_SRC_MAC_OFFSET,
1962 					  skb->data + QDF_NBUF_DEST_MAC_OFFSET,
1963 					  QDF_PROTO_TYPE_DHCP, subtype, dir,
1964 					  QDF_TRACE_DEFAULT_MSDU_ID,
1965 					  QDF_TX_RX_STATUS_INVALID);
1966 		qdf_fill_wlan_connectivity_log(QDF_PROTO_TYPE_DHCP, subtype,
1967 					       QDF_RX, 0, op_mode, vdev_id, 0,
1968 					       qdf_nbuf_rx_get_band(skb));
1969 	}
1970 
1971 	if (dp_dhcp_trace) {
1972 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
1973 		if (QDF_TX == dir)
1974 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1975 		else if (QDF_RX == dir)
1976 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1977 
1978 		cmn_info.vdev_id = vdev_id;
1979 		cmn_info.type = QDF_PROTO_TYPE_DHCP;
1980 		cmn_info.subtype = subtype;
1981 		cmn_info.proto_priv_data = 0;
1982 		cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb);
1983 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_DHCP_PACKET_RECORD,
1984 					       skb->data +
1985 					       QDF_NBUF_SRC_MAC_OFFSET,
1986 					       skb->data +
1987 					       QDF_NBUF_DEST_MAC_OFFSET,
1988 					       dir, pdev_id, true, &cmn_info));
1989 
1990 		switch (subtype) {
1991 		case QDF_PROTO_DHCP_DISCOVER:
1992 			g_qdf_dp_trace_data.dhcp_disc++;
1993 			break;
1994 		case QDF_PROTO_DHCP_OFFER:
1995 			g_qdf_dp_trace_data.dhcp_off++;
1996 			break;
1997 		case QDF_PROTO_DHCP_REQUEST:
1998 			g_qdf_dp_trace_data.dhcp_req++;
1999 			break;
2000 		case QDF_PROTO_DHCP_ACK:
2001 			g_qdf_dp_trace_data.dhcp_ack++;
2002 			break;
2003 		case QDF_PROTO_DHCP_NACK:
2004 			g_qdf_dp_trace_data.dhcp_nack++;
2005 			break;
2006 		default:
2007 			g_qdf_dp_trace_data.eapol_others++;
2008 			break;
2009 		}
2010 	}
2011 
2012 	return true;
2013 }
2014 
2015 /**
2016  * qdf_log_arp_pkt() - log ARP packet
2017  * @vdev_id: ID of the vdev
2018  * @skb: skb pointer
2019  * @dir: direction
2020  * @pdev_id: ID of the pdev
2021  *
2022  * Return: true/false
2023  */
2024 static bool qdf_log_arp_pkt(uint8_t vdev_id, struct sk_buff *skb,
2025 			    enum qdf_proto_dir dir, uint8_t pdev_id)
2026 {
2027 	enum qdf_proto_subtype proto_subtype;
2028 	struct qdf_dp_trace_proto_cmn cmn_info;
2029 
2030 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ARP) &&
2031 		((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ARP ==
2032 			QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
2033 		 (dir == QDF_RX && qdf_nbuf_is_ipv4_arp_pkt(skb) == true))) {
2034 
2035 		proto_subtype = qdf_nbuf_get_arp_subtype(skb);
2036 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
2037 		if (QDF_TX == dir)
2038 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
2039 		else if (QDF_RX == dir)
2040 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
2041 
2042 		cmn_info.vdev_id = vdev_id;
2043 		cmn_info.type = QDF_PROTO_TYPE_ARP;
2044 		cmn_info.subtype = proto_subtype;
2045 		cmn_info.proto_priv_data = 0;
2046 		cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb);
2047 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ARP_PACKET_RECORD,
2048 					       skb->data +
2049 					       QDF_NBUF_SRC_MAC_OFFSET,
2050 					       skb->data +
2051 					       QDF_NBUF_DEST_MAC_OFFSET,
2052 					       dir, pdev_id, true,
2053 					       &cmn_info));
2054 
2055 		if (QDF_PROTO_ARP_REQ == proto_subtype)
2056 			g_qdf_dp_trace_data.arp_req++;
2057 		else
2058 			g_qdf_dp_trace_data.arp_resp++;
2059 
2060 		return true;
2061 	}
2062 	return false;
2063 }
2064 
2065 
2066 bool qdf_dp_trace_log_pkt(uint8_t vdev_id, struct sk_buff *skb,
2067 			  enum qdf_proto_dir dir, uint8_t pdev_id,
2068 			  enum QDF_OPMODE op_mode)
2069 {
2070 	if (!qdf_dp_get_proto_bitmap() && !qdf_dp_get_proto_event_bitmap())
2071 		return false;
2072 	if (qdf_log_arp_pkt(vdev_id, skb, dir, pdev_id))
2073 		return true;
2074 	if (qdf_log_dhcp_pkt(vdev_id, skb, dir, pdev_id, op_mode))
2075 		return true;
2076 	if (qdf_log_eapol_pkt(vdev_id, skb, dir, pdev_id, op_mode))
2077 		return true;
2078 	if (qdf_log_icmp_pkt(vdev_id, skb, dir, pdev_id))
2079 		return true;
2080 	if (qdf_log_icmpv6_pkt(vdev_id, skb, dir, pdev_id))
2081 		return true;
2082 	return false;
2083 }
2084 qdf_export_symbol(qdf_dp_trace_log_pkt);
2085 
2086 void qdf_dp_display_mgmt_pkt(struct qdf_dp_trace_record_s *record,
2087 			      uint16_t index, uint8_t pdev_id, uint8_t info)
2088 {
2089 	int loc;
2090 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2091 	struct qdf_dp_trace_mgmt_buf *buf =
2092 		(struct qdf_dp_trace_mgmt_buf *)record->data;
2093 
2094 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2095 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2096 					 index, info, record);
2097 
2098 	DPTRACE_PRINT("%s [%d] [%s %s]",
2099 		      prepend_str,
2100 		      buf->vdev_id,
2101 		      qdf_dp_type_to_str(buf->type),
2102 		      qdf_dp_subtype_to_str(buf->subtype));
2103 }
2104 qdf_export_symbol(qdf_dp_display_mgmt_pkt);
2105 
2106 
2107 void qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
2108 		uint8_t pdev_id, enum qdf_proto_type type,
2109 		enum qdf_proto_subtype subtype)
2110 {
2111 	struct qdf_dp_trace_mgmt_buf buf;
2112 	int buf_size = sizeof(struct qdf_dp_trace_mgmt_buf);
2113 
2114 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
2115 		return;
2116 
2117 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2118 		QDF_BUG(0);
2119 
2120 	buf.type = type;
2121 	buf.subtype = subtype;
2122 	buf.vdev_id = vdev_id;
2123 	qdf_dp_add_record(code, pdev_id, (uint8_t *)&buf, buf_size,
2124 			  NULL, 0, true);
2125 }
2126 qdf_export_symbol(qdf_dp_trace_mgmt_pkt);
2127 
2128 static void
2129 qdf_dpt_display_credit_record_debugfs(qdf_debugfs_file_t file,
2130 				      struct qdf_dp_trace_record_s *record,
2131 				      uint32_t index)
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, 0, record);
2140 	if (buf->operation == QDF_OP_NA)
2141 		qdf_debugfs_printf(file, "%s [%s] [T: %d G0: %d G1: %d]\n",
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 		qdf_debugfs_printf(file,
2148 				   "%s [%s] [T: %d G0: %d G1: %d] [%s %d]\n",
2149 				   prepend_str,
2150 				   qdf_dp_credit_source_to_str(buf->source),
2151 				   buf->total_credits, buf->g0_credit,
2152 				   buf->g1_credit,
2153 				   qdf_dp_operation_to_str(buf->operation),
2154 				   buf->delta);
2155 }
2156 
2157 void qdf_dp_display_credit_record(struct qdf_dp_trace_record_s *record,
2158 				  uint16_t index, uint8_t pdev_id, uint8_t info)
2159 {
2160 	int loc;
2161 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2162 	struct qdf_dp_trace_credit_record *buf =
2163 		(struct qdf_dp_trace_credit_record *)record->data;
2164 
2165 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2166 					 index, info, record);
2167 	if (buf->operation == QDF_OP_NA)
2168 		DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d]",
2169 			      prepend_str,
2170 			      qdf_dp_credit_source_to_str(buf->source),
2171 			      buf->total_credits, buf->g0_credit,
2172 			      buf->g1_credit);
2173 	else
2174 		DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d] [%s %d]",
2175 			      prepend_str,
2176 			      qdf_dp_credit_source_to_str(buf->source),
2177 			      buf->total_credits, buf->g0_credit,
2178 			      buf->g1_credit,
2179 			      qdf_dp_operation_to_str(buf->operation),
2180 			      buf->delta);
2181 }
2182 
2183 void qdf_dp_trace_credit_record(enum QDF_CREDIT_UPDATE_SOURCE source,
2184 				enum QDF_CREDIT_OPERATION operation,
2185 				int delta, int total_credits,
2186 				int g0_credit, int g1_credit)
2187 {
2188 	struct qdf_dp_trace_credit_record buf;
2189 	int buf_size = sizeof(struct qdf_dp_trace_credit_record);
2190 	enum QDF_DP_TRACE_ID code = QDF_DP_TRACE_TX_CREDIT_RECORD;
2191 
2192 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
2193 		return;
2194 
2195 	if (!(qdf_dp_get_proto_bitmap() & QDF_HL_CREDIT_TRACKING))
2196 		return;
2197 
2198 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2199 		QDF_BUG(0);
2200 
2201 	buf.source = source;
2202 	buf.operation = operation;
2203 	buf.delta = delta;
2204 	buf.total_credits = total_credits;
2205 	buf.g0_credit = g0_credit;
2206 	buf.g1_credit = g1_credit;
2207 
2208 	qdf_dp_add_record(code, QDF_TRACE_DEFAULT_PDEV_ID, (uint8_t *)&buf,
2209 			  buf_size, NULL, 0, false);
2210 }
2211 qdf_export_symbol(qdf_dp_trace_credit_record);
2212 
2213 void qdf_dp_display_event_record(struct qdf_dp_trace_record_s *record,
2214 			      uint16_t index, uint8_t pdev_id, uint8_t info)
2215 {
2216 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2217 	struct qdf_dp_trace_event_buf *buf =
2218 		(struct qdf_dp_trace_event_buf *)record->data;
2219 
2220 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2221 	qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2222 				   index, info, record);
2223 
2224 	DPTRACE_PRINT("%s [%d] [%s %s]",
2225 		      prepend_str,
2226 		      buf->vdev_id,
2227 		      qdf_dp_type_to_str(buf->type),
2228 		      qdf_dp_subtype_to_str(buf->subtype));
2229 }
2230 qdf_export_symbol(qdf_dp_display_event_record);
2231 
2232 void qdf_dp_trace_record_event(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
2233 			       uint8_t pdev_id, enum qdf_proto_type type,
2234 			       enum qdf_proto_subtype subtype)
2235 {
2236 	struct qdf_dp_trace_event_buf buf;
2237 	int buf_size = sizeof(struct qdf_dp_trace_event_buf);
2238 
2239 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
2240 		return;
2241 
2242 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2243 		QDF_BUG(0);
2244 
2245 	buf.type = type;
2246 	buf.subtype = subtype;
2247 	buf.vdev_id = vdev_id;
2248 	qdf_dp_add_record(code, pdev_id,
2249 			  (uint8_t *)&buf, buf_size, NULL, 0, true);
2250 }
2251 qdf_export_symbol(qdf_dp_trace_record_event);
2252 
2253 
2254 void qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s *record,
2255 			      uint16_t index, uint8_t pdev_id, uint8_t info)
2256 {
2257 	int loc;
2258 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2259 	struct qdf_dp_trace_proto_buf *buf =
2260 		(struct qdf_dp_trace_proto_buf *)record->data;
2261 
2262 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2263 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2264 					 index, info, record);
2265 
2266 	if (QDF_RX == buf->dir)
2267 		DPTRACE_PRINT("%s [%d] [%d] [%s] SA: "
2268 			      QDF_MAC_ADDR_FMT " %s DA:"
2269 			      QDF_MAC_ADDR_FMT " proto priv data = %08x",
2270 			      prepend_str,
2271 			      buf->cmn_info.vdev_id,
2272 			      buf->cmn_info.mpdu_seq,
2273 			      qdf_dp_subtype_to_str(buf->cmn_info.subtype),
2274 			      QDF_MAC_ADDR_REF(buf->sa.bytes),
2275 			      qdf_dp_dir_to_str(buf->dir),
2276 			      QDF_MAC_ADDR_REF(buf->da.bytes),
2277 			      buf->cmn_info.proto_priv_data);
2278 	else
2279 		DPTRACE_PRINT("%s [%d] [%s] SA: "
2280 			      QDF_MAC_ADDR_FMT " %s DA:"
2281 			      QDF_MAC_ADDR_FMT " proto priv data = %08x",
2282 			      prepend_str,
2283 			      buf->cmn_info.vdev_id,
2284 			      qdf_dp_subtype_to_str(buf->cmn_info.subtype),
2285 			      QDF_MAC_ADDR_REF(buf->sa.bytes),
2286 			      qdf_dp_dir_to_str(buf->dir),
2287 			      QDF_MAC_ADDR_REF(buf->da.bytes),
2288 			      buf->cmn_info.proto_priv_data);
2289 }
2290 qdf_export_symbol(qdf_dp_display_proto_pkt);
2291 
2292 void qdf_dp_trace_proto_pkt(enum QDF_DP_TRACE_ID code,
2293 			    uint8_t *sa, uint8_t *da,
2294 			    enum qdf_proto_dir dir,
2295 			    uint8_t pdev_id, bool print,
2296 			    struct qdf_dp_trace_proto_cmn *cmn_info)
2297 {
2298 	struct qdf_dp_trace_proto_buf buf;
2299 	int buf_size = sizeof(struct qdf_dp_trace_proto_buf);
2300 
2301 	if (qdf_dp_enable_check(NULL, code, dir) == false)
2302 		return;
2303 
2304 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2305 		QDF_BUG(0);
2306 
2307 	memcpy(&buf.sa, sa, QDF_NET_ETH_LEN);
2308 	memcpy(&buf.da, da, QDF_NET_ETH_LEN);
2309 	memcpy(&buf.cmn_info, cmn_info, sizeof(*cmn_info));
2310 	buf.dir = dir;
2311 	qdf_dp_add_record(code, pdev_id,
2312 			  (uint8_t *)&buf, buf_size, NULL, 0, print);
2313 }
2314 qdf_export_symbol(qdf_dp_trace_proto_pkt);
2315 
2316 void qdf_dp_display_ptr_record(struct qdf_dp_trace_record_s *record,
2317 				uint16_t index, uint8_t pdev_id, uint8_t info)
2318 {
2319 	int loc;
2320 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2321 	struct qdf_dp_trace_ptr_buf *buf =
2322 		(struct qdf_dp_trace_ptr_buf *)record->data;
2323 	bool is_free_pkt_ptr_record = false;
2324 
2325 	if ((record->code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) ||
2326 	    (record->code == QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD))
2327 		is_free_pkt_ptr_record = true;
2328 
2329 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2330 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2331 					 index, info, record);
2332 
2333 	if (loc < sizeof(prepend_str))
2334 		scnprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2335 			  "[msdu id %d %s %d]",
2336 			  buf->msdu_id,
2337 			  is_free_pkt_ptr_record ? "status" : "vdev_id",
2338 			  buf->status);
2339 
2340 	if (info & QDF_DP_TRACE_RECORD_INFO_LIVE) {
2341 		/* In live mode donot dump the contents of the cookie */
2342 		DPTRACE_PRINT("%s", prepend_str);
2343 	} else {
2344 		dump_dp_hex_trace(prepend_str, (uint8_t *)&buf->cookie,
2345 			sizeof(buf->cookie));
2346 	}
2347 }
2348 qdf_export_symbol(qdf_dp_display_ptr_record);
2349 
2350 static
2351 enum qdf_proto_type qdf_dp_get_pkt_proto_type(qdf_nbuf_t nbuf)
2352 {
2353 	uint8_t pkt_type;
2354 
2355 	if (!nbuf)
2356 		return QDF_PROTO_TYPE_MAX;
2357 
2358 	if (qdf_nbuf_data_is_dns_query(nbuf) ||
2359 	    qdf_nbuf_data_is_dns_response(nbuf))
2360 		return QDF_PROTO_TYPE_DNS;
2361 
2362 	pkt_type = QDF_NBUF_CB_GET_PACKET_TYPE(nbuf);
2363 
2364 	switch (pkt_type) {
2365 	case QDF_NBUF_CB_PACKET_TYPE_EAPOL:
2366 		return QDF_PROTO_TYPE_EAPOL;
2367 	case QDF_NBUF_CB_PACKET_TYPE_ARP:
2368 		return QDF_PROTO_TYPE_ARP;
2369 	case QDF_NBUF_CB_PACKET_TYPE_DHCP:
2370 		return QDF_PROTO_TYPE_DHCP;
2371 	default:
2372 		return QDF_PROTO_TYPE_MAX;
2373 	}
2374 }
2375 
2376 static
2377 enum qdf_proto_subtype qdf_dp_get_pkt_subtype(qdf_nbuf_t nbuf,
2378 					      enum qdf_proto_type pkt_type)
2379 {
2380 	switch (pkt_type) {
2381 	case QDF_PROTO_TYPE_EAPOL:
2382 		return qdf_nbuf_get_eapol_subtype(nbuf);
2383 	case QDF_PROTO_TYPE_ARP:
2384 		return qdf_nbuf_get_arp_subtype(nbuf);
2385 	case QDF_PROTO_TYPE_DHCP:
2386 		return qdf_nbuf_get_dhcp_subtype(nbuf);
2387 	case QDF_PROTO_TYPE_DNS:
2388 		return (qdf_nbuf_data_is_dns_query(nbuf)) ?
2389 				QDF_PROTO_DNS_QUERY : QDF_PROTO_DNS_RES;
2390 	default:
2391 		return QDF_PROTO_INVALID;
2392 	}
2393 }
2394 
2395 static
2396 bool qdf_dp_proto_log_enable_check(enum qdf_proto_type pkt_type,
2397 				   uint16_t status)
2398 {
2399 	if (pkt_type == QDF_PROTO_TYPE_MAX)
2400 		return false;
2401 
2402 	switch (pkt_type) {
2403 	case QDF_PROTO_TYPE_EAPOL:
2404 		return qdf_dp_get_proto_event_bitmap() &
2405 				QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
2406 	case QDF_PROTO_TYPE_DHCP:
2407 		return qdf_dp_get_proto_event_bitmap() &
2408 				QDF_NBUF_PKT_TRAC_TYPE_DHCP;
2409 	case QDF_PROTO_TYPE_ARP:
2410 		if (status == QDF_TX_RX_STATUS_OK)
2411 			return false;
2412 		else
2413 			return qdf_dp_get_proto_event_bitmap() &
2414 					QDF_NBUF_PKT_TRAC_TYPE_ARP;
2415 	case QDF_PROTO_TYPE_DNS:
2416 		if (status == QDF_TX_RX_STATUS_OK)
2417 			return false;
2418 		else
2419 			return qdf_dp_get_proto_event_bitmap() &
2420 					QDF_NBUF_PKT_TRAC_TYPE_DNS;
2421 	default:
2422 		return false;
2423 	}
2424 }
2425 
2426 void qdf_dp_track_noack_check(qdf_nbuf_t nbuf, enum qdf_proto_subtype *subtype)
2427 {
2428 	enum qdf_proto_type pkt_type = qdf_dp_get_pkt_proto_type(nbuf);
2429 	uint16_t dp_track = 0;
2430 
2431 	switch (pkt_type) {
2432 	case QDF_PROTO_TYPE_EAPOL:
2433 		dp_track = qdf_dp_get_proto_bitmap() &
2434 				QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
2435 		break;
2436 	case QDF_PROTO_TYPE_DHCP:
2437 		dp_track = qdf_dp_get_proto_bitmap() &
2438 				QDF_NBUF_PKT_TRAC_TYPE_DHCP;
2439 		break;
2440 	case QDF_PROTO_TYPE_ARP:
2441 		dp_track = qdf_dp_get_proto_bitmap() &
2442 					QDF_NBUF_PKT_TRAC_TYPE_ARP;
2443 		break;
2444 	case QDF_PROTO_TYPE_DNS:
2445 		dp_track = qdf_dp_get_proto_bitmap() &
2446 					QDF_NBUF_PKT_TRAC_TYPE_DNS;
2447 		break;
2448 	default:
2449 		break;
2450 	}
2451 
2452 	if (!dp_track) {
2453 		*subtype = QDF_PROTO_INVALID;
2454 		return;
2455 	}
2456 
2457 	*subtype = qdf_dp_get_pkt_subtype(nbuf, pkt_type);
2458 }
2459 qdf_export_symbol(qdf_dp_track_noack_check);
2460 
2461 enum qdf_dp_tx_rx_status qdf_dp_get_status_from_a_status(uint8_t status)
2462 {
2463 	if (status == QDF_A_STATUS_ERROR)
2464 		return QDF_TX_RX_STATUS_INVALID;
2465 	else if (status == QDF_A_STATUS_OK)
2466 		return QDF_TX_RX_STATUS_OK;
2467 	else
2468 		return QDF_TX_RX_STATUS_MAX;
2469 }
2470 qdf_export_symbol(qdf_dp_get_status_from_a_status);
2471 
2472 void qdf_dp_trace_ptr(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
2473 		uint8_t pdev_id, uint8_t *data, uint8_t size,
2474 		uint16_t msdu_id, uint16_t buf_arg_status,
2475 		enum qdf_dp_tx_rx_status qdf_tx_status,
2476 		enum QDF_OPMODE op_mode)
2477 {
2478 	struct qdf_dp_trace_ptr_buf buf;
2479 	int buf_size = sizeof(struct qdf_dp_trace_ptr_buf);
2480 	enum qdf_proto_type pkt_type;
2481 	enum qdf_proto_subtype subtype;
2482 
2483 	pkt_type = qdf_dp_get_pkt_proto_type(nbuf);
2484 	if ((code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD ||
2485 	     code == QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD) &&
2486 	    qdf_dp_proto_log_enable_check(pkt_type, qdf_tx_status)) {
2487 		subtype = qdf_dp_get_pkt_subtype(nbuf, pkt_type);
2488 		qdf_dp_log_proto_pkt_info(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET,
2489 					 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET,
2490 					 pkt_type, subtype,
2491 					 QDF_TX, msdu_id, qdf_tx_status);
2492 		qdf_fill_wlan_connectivity_log(pkt_type, subtype,
2493 					       QDF_TX, qdf_tx_status, op_mode,
2494 					       QDF_NBUF_CB_TX_VDEV_CTX(nbuf),
2495 					       nbuf->data,
2496 					       qdf_nbuf_tx_get_band(nbuf));
2497 	}
2498 
2499 	if (qdf_dp_enable_check(nbuf, code, QDF_TX) == false)
2500 		return;
2501 
2502 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2503 		QDF_BUG(0);
2504 
2505 	qdf_mem_copy(&buf.cookie, data, size);
2506 	buf.msdu_id = msdu_id;
2507 	buf.status = buf_arg_status;
2508 	qdf_dp_add_record(code, pdev_id, (uint8_t *)&buf, buf_size, NULL, 0,
2509 			  QDF_NBUF_CB_DP_TRACE_PRINT(nbuf));
2510 }
2511 qdf_export_symbol(qdf_dp_trace_ptr);
2512 
2513 void qdf_dp_trace_data_pkt(qdf_nbuf_t nbuf, uint8_t pdev_id,
2514 			   enum QDF_DP_TRACE_ID code, uint16_t msdu_id,
2515 			   enum qdf_proto_dir dir)
2516 {
2517 	struct qdf_dp_trace_data_buf buf;
2518 	enum qdf_proto_type pkt_type;
2519 
2520 	pkt_type = qdf_dp_get_pkt_proto_type(nbuf);
2521 	if (code == QDF_DP_TRACE_DROP_PACKET_RECORD &&
2522 	    qdf_dp_proto_log_enable_check(pkt_type, QDF_TX_RX_STATUS_DROP))
2523 		qdf_dp_log_proto_pkt_info(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET,
2524 					 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET,
2525 					 pkt_type,
2526 					 qdf_dp_get_pkt_subtype(nbuf, pkt_type),
2527 					 QDF_TX, msdu_id,
2528 					 QDF_TX_RX_STATUS_DROP);
2529 
2530 	buf.msdu_id = msdu_id;
2531 	if (!qdf_dp_enable_check(nbuf, code, dir))
2532 		return;
2533 
2534 	qdf_dp_add_record(code, pdev_id,
2535 			  nbuf ? qdf_nbuf_data(nbuf) : NULL,
2536 			  nbuf ? nbuf->len - nbuf->data_len : 0,
2537 			  (uint8_t *)&buf, sizeof(struct qdf_dp_trace_data_buf),
2538 			  (nbuf) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false);
2539 }
2540 
2541 qdf_export_symbol(qdf_dp_trace_data_pkt);
2542 
2543 void qdf_dp_display_record(struct qdf_dp_trace_record_s *record,
2544 			   uint16_t index, uint8_t pdev_id, uint8_t info)
2545 {
2546 	int loc;
2547 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2548 
2549 	if (!(pdev_id == QDF_TRACE_DEFAULT_PDEV_ID ||
2550 		pdev_id == record->pdev_id))
2551 		return;
2552 
2553 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2554 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2555 					 index, info, record);
2556 
2557 	switch (record->code) {
2558 	case  QDF_DP_TRACE_HDD_TX_TIMEOUT:
2559 		DPTRACE_PRINT(" %s: HDD TX Timeout", prepend_str);
2560 		break;
2561 	case  QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
2562 		DPTRACE_PRINT(" %s: HDD SoftAP TX Timeout", prepend_str);
2563 		break;
2564 	case  QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
2565 		DPTRACE_PRINT(" %s: CE Fast Packet Error", prepend_str);
2566 		break;
2567 	case QDF_DP_TRACE_LI_DP_NULL_RX_PACKET_RECORD:
2568 	default:
2569 		dump_dp_hex_trace(prepend_str, record->data, record->size);
2570 		break;
2571 	};
2572 }
2573 qdf_export_symbol(qdf_dp_display_record);
2574 
2575 void
2576 qdf_dp_display_data_pkt_record(struct qdf_dp_trace_record_s *record,
2577 			       uint16_t rec_index, uint8_t pdev_id,
2578 			       uint8_t info)
2579 {
2580 	int loc;
2581 	char prepend_str[DP_TRACE_META_DATA_STRLEN + 10];
2582 	struct qdf_dp_trace_data_buf *buf =
2583 		(struct qdf_dp_trace_data_buf *)record->data;
2584 
2585 	qdf_mem_zero(prepend_str, sizeof(prepend_str));
2586 
2587 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2588 					 rec_index, info, record);
2589 	if (loc < sizeof(prepend_str))
2590 		loc += snprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2591 				"[%d]", buf->msdu_id);
2592 	dump_dp_hex_trace(prepend_str,
2593 			  &record->data[sizeof(struct qdf_dp_trace_data_buf)],
2594 			  record->size);
2595 }
2596 
2597 void qdf_dp_trace(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code, uint8_t pdev_id,
2598 	uint8_t *data, uint8_t size, enum qdf_proto_dir dir)
2599 {
2600 
2601 	if (qdf_dp_enable_check(nbuf, code, dir) == false)
2602 		return;
2603 
2604 	qdf_dp_add_record(code, pdev_id, nbuf ? qdf_nbuf_data(nbuf) : NULL,
2605 			  size, NULL, 0,
2606 			  (nbuf) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false);
2607 }
2608 qdf_export_symbol(qdf_dp_trace);
2609 
2610 void qdf_dp_trace_spin_lock_init(void)
2611 {
2612 	spin_lock_init(&l_dp_trace_lock);
2613 }
2614 qdf_export_symbol(qdf_dp_trace_spin_lock_init);
2615 
2616 void qdf_dp_trace_disable_live_mode(void)
2617 {
2618 	g_qdf_dp_trace_data.force_live_mode = 0;
2619 }
2620 qdf_export_symbol(qdf_dp_trace_disable_live_mode);
2621 
2622 void qdf_dp_trace_enable_live_mode(void)
2623 {
2624 	g_qdf_dp_trace_data.force_live_mode = 1;
2625 }
2626 qdf_export_symbol(qdf_dp_trace_enable_live_mode);
2627 
2628 void qdf_dp_trace_clear_buffer(void)
2629 {
2630 	g_qdf_dp_trace_data.head = INVALID_QDF_DP_TRACE_ADDR;
2631 	g_qdf_dp_trace_data.tail = INVALID_QDF_DP_TRACE_ADDR;
2632 	g_qdf_dp_trace_data.num = 0;
2633 	g_qdf_dp_trace_data.dump_counter = 0;
2634 	g_qdf_dp_trace_data.num_records_to_dump = MAX_QDF_DP_TRACE_RECORDS;
2635 	if (g_qdf_dp_trace_data.enable)
2636 		memset(g_qdf_dp_trace_tbl, 0,
2637 		       MAX_QDF_DP_TRACE_RECORDS *
2638 		       sizeof(struct qdf_dp_trace_record_s));
2639 }
2640 qdf_export_symbol(qdf_dp_trace_clear_buffer);
2641 
2642 void qdf_dp_trace_dump_stats(void)
2643 {
2644 		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)",
2645 			      g_qdf_dp_trace_data.tx_count,
2646 			      g_qdf_dp_trace_data.rx_count,
2647 			      g_qdf_dp_trace_data.icmp_req,
2648 			      g_qdf_dp_trace_data.icmp_resp,
2649 			      g_qdf_dp_trace_data.arp_req,
2650 			      g_qdf_dp_trace_data.arp_resp,
2651 			      g_qdf_dp_trace_data.icmpv6_req,
2652 			      g_qdf_dp_trace_data.icmpv6_resp,
2653 			      g_qdf_dp_trace_data.icmpv6_ns,
2654 			      g_qdf_dp_trace_data.icmpv6_na,
2655 			      g_qdf_dp_trace_data.icmpv6_rs,
2656 			      g_qdf_dp_trace_data.icmpv6_ra,
2657 			      g_qdf_dp_trace_data.dhcp_disc,
2658 			      g_qdf_dp_trace_data.dhcp_off,
2659 			      g_qdf_dp_trace_data.dhcp_req,
2660 			      g_qdf_dp_trace_data.dhcp_ack,
2661 			      g_qdf_dp_trace_data.dhcp_nack,
2662 			      g_qdf_dp_trace_data.dhcp_others,
2663 			      g_qdf_dp_trace_data.eapol_m1,
2664 			      g_qdf_dp_trace_data.eapol_m2,
2665 			      g_qdf_dp_trace_data.eapol_m3,
2666 			      g_qdf_dp_trace_data.eapol_m4,
2667 			      g_qdf_dp_trace_data.eapol_others);
2668 }
2669 qdf_export_symbol(qdf_dp_trace_dump_stats);
2670 
2671 /**
2672  * qdf_dpt_dump_hex_trace_debugfs() - read data in file
2673  * @file: file to read
2674  * @str: string to prepend the hexdump with.
2675  * @buf: buffer which contains data to be written
2676  * @buf_len: defines the size of the data to be written
2677  *
2678  * Return: None
2679  */
2680 static void qdf_dpt_dump_hex_trace_debugfs(qdf_debugfs_file_t file,
2681 				char *str, uint8_t *buf, uint8_t buf_len)
2682 {
2683 	unsigned char linebuf[BUFFER_SIZE];
2684 	const u8 *ptr = buf;
2685 	int i, linelen, remaining = buf_len;
2686 
2687 	/* Dump the bytes in the last line */
2688 	for (i = 0; i < buf_len; i += ROW_SIZE) {
2689 		linelen = min(remaining, ROW_SIZE);
2690 		remaining -= ROW_SIZE;
2691 
2692 		hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1,
2693 				linebuf, sizeof(linebuf), false);
2694 
2695 		qdf_debugfs_printf(file, "%s %s\n", str, linebuf);
2696 	}
2697 }
2698 
2699 /**
2700  * qdf_dpt_display_proto_pkt_debugfs() - display proto packet
2701  * @file: file to read
2702  * @record: dptrace record
2703  * @index: index
2704  *
2705  * Return: none
2706  */
2707 static void qdf_dpt_display_proto_pkt_debugfs(qdf_debugfs_file_t file,
2708 				struct qdf_dp_trace_record_s *record,
2709 				uint32_t index)
2710 {
2711 	int loc;
2712 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2713 	struct qdf_dp_trace_proto_buf *buf =
2714 		(struct qdf_dp_trace_proto_buf *)record->data;
2715 
2716 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2717 					 index, 0, record);
2718 	qdf_debugfs_printf(file, "%s [%d] [%s] SA: "
2719 			   QDF_MAC_ADDR_FMT " %s DA: "
2720 			   QDF_MAC_ADDR_FMT,
2721 			   prepend_str,
2722 			   buf->cmn_info.vdev_id,
2723 			   qdf_dp_subtype_to_str(buf->cmn_info.subtype),
2724 			   QDF_MAC_ADDR_REF(buf->sa.bytes),
2725 			   qdf_dp_dir_to_str(buf->dir),
2726 			   QDF_MAC_ADDR_REF(buf->da.bytes));
2727 	qdf_debugfs_printf(file, "\n");
2728 }
2729 
2730 /**
2731  * qdf_dpt_display_mgmt_pkt_debugfs() - display mgmt packet
2732  * @file: file to read
2733  * @record: dptrace record
2734  * @index: index
2735  *
2736  * Return: none
2737  */
2738 static void qdf_dpt_display_mgmt_pkt_debugfs(qdf_debugfs_file_t file,
2739 				struct qdf_dp_trace_record_s *record,
2740 				uint32_t index)
2741 {
2742 
2743 	int loc;
2744 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2745 	struct qdf_dp_trace_mgmt_buf *buf =
2746 		(struct qdf_dp_trace_mgmt_buf *)record->data;
2747 
2748 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2749 					 index, 0, record);
2750 
2751 	qdf_debugfs_printf(file, "%s [%d] [%s %s]\n",
2752 			   prepend_str,
2753 			   buf->vdev_id,
2754 			   qdf_dp_type_to_str(buf->type),
2755 			   qdf_dp_subtype_to_str(buf->subtype));
2756 }
2757 
2758 /**
2759  * qdf_dpt_display_event_record_debugfs() - display event records
2760  * @file: file to read
2761  * @record: dptrace record
2762  * @index: index
2763  *
2764  * Return: none
2765  */
2766 static void qdf_dpt_display_event_record_debugfs(qdf_debugfs_file_t file,
2767 				struct qdf_dp_trace_record_s *record,
2768 				uint32_t index)
2769 {
2770 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2771 	struct qdf_dp_trace_event_buf *buf =
2772 		(struct qdf_dp_trace_event_buf *)record->data;
2773 
2774 	qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2775 				   index, 0, record);
2776 	qdf_debugfs_printf(file, "%s [%d] [%s %s]\n",
2777 			   prepend_str,
2778 			   buf->vdev_id,
2779 			   qdf_dp_type_to_str(buf->type),
2780 			   qdf_dp_subtype_to_str(buf->subtype));
2781 }
2782 
2783 /**
2784  * qdf_dpt_display_ptr_record_debugfs() - display record ptr
2785  * @file: file to read
2786  * @record: dptrace record
2787  * @index: index
2788  *
2789  * Return: none
2790  */
2791 static void qdf_dpt_display_ptr_record_debugfs(qdf_debugfs_file_t file,
2792 				struct qdf_dp_trace_record_s *record,
2793 				uint32_t index)
2794 {
2795 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2796 	int loc;
2797 	struct qdf_dp_trace_ptr_buf *buf =
2798 		(struct qdf_dp_trace_ptr_buf *)record->data;
2799 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2800 					 index, 0, record);
2801 
2802 	if (loc < sizeof(prepend_str))
2803 		scnprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2804 			  "[msdu id %d %s %d]",
2805 			  buf->msdu_id,
2806 			  (record->code ==
2807 				QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) ?
2808 			  "status" : "vdev_id",
2809 			  buf->status);
2810 
2811 	qdf_dpt_dump_hex_trace_debugfs(file, prepend_str,
2812 				       (uint8_t *)&buf->cookie,
2813 				       sizeof(buf->cookie));
2814 }
2815 
2816 /**
2817  * qdf_dpt_display_record_debugfs() - display record
2818  * @file: file to read
2819  * @record: dptrace record
2820  * @index: index
2821  *
2822  * Return: none
2823  */
2824 static void qdf_dpt_display_record_debugfs(qdf_debugfs_file_t file,
2825 				struct qdf_dp_trace_record_s *record,
2826 				uint32_t index)
2827 {
2828 	int loc;
2829 	char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2830 	struct qdf_dp_trace_data_buf *buf =
2831 		(struct qdf_dp_trace_data_buf *)record->data;
2832 
2833 	loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2834 					 index, 0, record);
2835 	if (loc < sizeof(prepend_str))
2836 		loc += snprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2837 				"[%d]", buf->msdu_id);
2838 	qdf_dpt_dump_hex_trace_debugfs(file, prepend_str,
2839 				       record->data, record->size);
2840 }
2841 
2842 uint32_t qdf_dpt_get_curr_pos_debugfs(qdf_debugfs_file_t file,
2843 				      enum qdf_dpt_debugfs_state state)
2844 {
2845 	uint32_t i = 0;
2846 	uint32_t tail;
2847 	uint32_t count = g_qdf_dp_trace_data.num;
2848 
2849 	if (!g_qdf_dp_trace_data.enable) {
2850 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
2851 		  "%s: Tracing Disabled", __func__);
2852 		return QDF_STATUS_E_EMPTY;
2853 	}
2854 
2855 	if (!count) {
2856 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
2857 		  "%s: no packets", __func__);
2858 		return QDF_STATUS_E_EMPTY;
2859 	}
2860 
2861 	if (state == QDF_DPT_DEBUGFS_STATE_SHOW_IN_PROGRESS)
2862 		return g_qdf_dp_trace_data.curr_pos;
2863 
2864 	qdf_debugfs_printf(file,
2865 		"DPT: config - bitmap 0x%x verb %u #rec %u rec_requested %u live_config %u thresh %u time_limit %u\n",
2866 		g_qdf_dp_trace_data.proto_bitmap,
2867 		g_qdf_dp_trace_data.verbosity,
2868 		g_qdf_dp_trace_data.no_of_record,
2869 		g_qdf_dp_trace_data.num_records_to_dump,
2870 		g_qdf_dp_trace_data.live_mode_config,
2871 		g_qdf_dp_trace_data.high_tput_thresh,
2872 		g_qdf_dp_trace_data.thresh_time_limit);
2873 
2874 	qdf_debugfs_printf(file,
2875 		"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",
2876 		g_qdf_dp_trace_data.icmp_req,
2877 		g_qdf_dp_trace_data.icmp_resp,
2878 		g_qdf_dp_trace_data.arp_req,
2879 		g_qdf_dp_trace_data.arp_resp,
2880 		g_qdf_dp_trace_data.icmpv6_req,
2881 		g_qdf_dp_trace_data.icmpv6_resp,
2882 		g_qdf_dp_trace_data.icmpv6_ns,
2883 		g_qdf_dp_trace_data.icmpv6_na,
2884 		g_qdf_dp_trace_data.icmpv6_rs,
2885 		g_qdf_dp_trace_data.icmpv6_ra,
2886 		g_qdf_dp_trace_data.dhcp_disc,
2887 		g_qdf_dp_trace_data.dhcp_off,
2888 		g_qdf_dp_trace_data.dhcp_req,
2889 		g_qdf_dp_trace_data.dhcp_ack,
2890 		g_qdf_dp_trace_data.dhcp_nack,
2891 		g_qdf_dp_trace_data.dhcp_others,
2892 		g_qdf_dp_trace_data.eapol_m1,
2893 		g_qdf_dp_trace_data.eapol_m2,
2894 		g_qdf_dp_trace_data.eapol_m3,
2895 		g_qdf_dp_trace_data.eapol_m4,
2896 		g_qdf_dp_trace_data.eapol_others);
2897 
2898 	qdf_debugfs_printf(file,
2899 		"DPT: Total Records: %d, Head: %d, Tail: %d\n",
2900 		g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head,
2901 		g_qdf_dp_trace_data.tail);
2902 
2903 	spin_lock_bh(&l_dp_trace_lock);
2904 	if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) {
2905 		i = g_qdf_dp_trace_data.head;
2906 		tail = g_qdf_dp_trace_data.tail;
2907 
2908 		if (count > g_qdf_dp_trace_data.num)
2909 			count = g_qdf_dp_trace_data.num;
2910 
2911 		if (tail >= (count - 1))
2912 			i = tail - count + 1;
2913 		else if (count != MAX_QDF_DP_TRACE_RECORDS)
2914 			i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) -
2915 						     tail);
2916 		g_qdf_dp_trace_data.curr_pos = 0;
2917 		g_qdf_dp_trace_data.saved_tail = tail;
2918 	}
2919 	spin_unlock_bh(&l_dp_trace_lock);
2920 
2921 	return g_qdf_dp_trace_data.saved_tail;
2922 }
2923 qdf_export_symbol(qdf_dpt_get_curr_pos_debugfs);
2924 
2925 QDF_STATUS qdf_dpt_dump_stats_debugfs(qdf_debugfs_file_t file,
2926 				      uint32_t curr_pos)
2927 {
2928 	struct qdf_dp_trace_record_s p_record;
2929 	uint32_t i = curr_pos;
2930 	uint16_t num_records_to_dump = g_qdf_dp_trace_data.num_records_to_dump;
2931 
2932 	if (!g_qdf_dp_trace_data.enable) {
2933 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
2934 			  "%s: Tracing Disabled", __func__);
2935 		return QDF_STATUS_E_FAILURE;
2936 	}
2937 
2938 	if (num_records_to_dump > g_qdf_dp_trace_data.num)
2939 		num_records_to_dump = g_qdf_dp_trace_data.num;
2940 
2941 	/*
2942 	 * Max dp trace record size should always be less than
2943 	 * QDF_DP_TRACE_PREPEND_STR_SIZE(100) + BUFFER_SIZE(121).
2944 	 */
2945 	if (WARN_ON(QDF_DP_TRACE_MAX_RECORD_SIZE <
2946 				QDF_DP_TRACE_PREPEND_STR_SIZE + BUFFER_SIZE))
2947 		return QDF_STATUS_E_FAILURE;
2948 
2949 	spin_lock_bh(&l_dp_trace_lock);
2950 	p_record = g_qdf_dp_trace_tbl[i];
2951 	spin_unlock_bh(&l_dp_trace_lock);
2952 
2953 	for (;; ) {
2954 		/*
2955 		 * Initially we get file as 1 page size, and
2956 		 * if remaining size in file is less than one record max size,
2957 		 * then return so that it gets an extra page.
2958 		 */
2959 		if ((file->size - file->count) < QDF_DP_TRACE_MAX_RECORD_SIZE) {
2960 			spin_lock_bh(&l_dp_trace_lock);
2961 			g_qdf_dp_trace_data.curr_pos = i;
2962 			spin_unlock_bh(&l_dp_trace_lock);
2963 			return QDF_STATUS_E_FAILURE;
2964 		}
2965 
2966 		switch (p_record.code) {
2967 		case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD:
2968 		case QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD:
2969 		case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD:
2970 			qdf_dpt_display_ptr_record_debugfs(file, &p_record, i);
2971 			break;
2972 
2973 		case QDF_DP_TRACE_EAPOL_PACKET_RECORD:
2974 		case QDF_DP_TRACE_DHCP_PACKET_RECORD:
2975 		case QDF_DP_TRACE_ARP_PACKET_RECORD:
2976 		case QDF_DP_TRACE_ICMP_PACKET_RECORD:
2977 		case QDF_DP_TRACE_ICMPv6_PACKET_RECORD:
2978 			qdf_dpt_display_proto_pkt_debugfs(file, &p_record, i);
2979 			break;
2980 
2981 		case QDF_DP_TRACE_TX_CREDIT_RECORD:
2982 			qdf_dpt_display_credit_record_debugfs(file, &p_record,
2983 							      i);
2984 			break;
2985 
2986 		case QDF_DP_TRACE_MGMT_PACKET_RECORD:
2987 			qdf_dpt_display_mgmt_pkt_debugfs(file, &p_record, i);
2988 			break;
2989 
2990 		case QDF_DP_TRACE_EVENT_RECORD:
2991 			qdf_dpt_display_event_record_debugfs(file, &p_record,
2992 							     i);
2993 			break;
2994 
2995 		case QDF_DP_TRACE_HDD_TX_TIMEOUT:
2996 			qdf_debugfs_printf(
2997 					file, "DPT: %04d: %llu %s\n",
2998 					i, p_record.time,
2999 					qdf_dp_code_to_string(p_record.code));
3000 			qdf_debugfs_printf(file, "HDD TX Timeout\n");
3001 			break;
3002 
3003 		case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
3004 			qdf_debugfs_printf(
3005 					file, "DPT: %04d: %llu %s\n",
3006 					i, p_record.time,
3007 					qdf_dp_code_to_string(p_record.code));
3008 			qdf_debugfs_printf(file, "HDD SoftAP TX Timeout\n");
3009 			break;
3010 
3011 		case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
3012 			qdf_debugfs_printf(
3013 					file, "DPT: %04d: %llu %s\n",
3014 					i, p_record.time,
3015 					qdf_dp_code_to_string(p_record.code));
3016 			qdf_debugfs_printf(file, "CE Fast Packet Error\n");
3017 			break;
3018 
3019 		case QDF_DP_TRACE_MAX:
3020 			qdf_debugfs_printf(file,
3021 				"%s: QDF_DP_TRACE_MAX event should not be generated\n",
3022 				__func__);
3023 			break;
3024 
3025 		case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
3026 		case QDF_DP_TRACE_HDD_RX_PACKET_RECORD:
3027 		case QDF_DP_TRACE_TX_PACKET_RECORD:
3028 		case QDF_DP_TRACE_RX_PACKET_RECORD:
3029 		case QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD:
3030 		case QDF_DP_TRACE_LI_DP_RX_PACKET_RECORD:
3031 
3032 		default:
3033 			qdf_dpt_display_record_debugfs(file, &p_record, i);
3034 			break;
3035 		}
3036 
3037 		if (++g_qdf_dp_trace_data.dump_counter == num_records_to_dump)
3038 			break;
3039 
3040 		spin_lock_bh(&l_dp_trace_lock);
3041 		if (i == 0)
3042 			i = MAX_QDF_DP_TRACE_RECORDS;
3043 
3044 		i -= 1;
3045 		p_record = g_qdf_dp_trace_tbl[i];
3046 		spin_unlock_bh(&l_dp_trace_lock);
3047 	}
3048 
3049 	g_qdf_dp_trace_data.dump_counter = 0;
3050 
3051 	return QDF_STATUS_SUCCESS;
3052 }
3053 qdf_export_symbol(qdf_dpt_dump_stats_debugfs);
3054 
3055 void qdf_dpt_set_value_debugfs(uint8_t proto_bitmap, uint8_t no_of_record,
3056 			    uint8_t verbosity, uint16_t num_records_to_dump)
3057 {
3058 	if (g_qdf_dp_trace_data.enable) {
3059 		g_qdf_dp_trace_data.proto_bitmap = proto_bitmap;
3060 		g_qdf_dp_trace_data.no_of_record = no_of_record;
3061 		g_qdf_dp_trace_data.verbosity    = verbosity;
3062 		g_qdf_dp_trace_data.num_records_to_dump = num_records_to_dump;
3063 	}
3064 }
3065 qdf_export_symbol(qdf_dpt_set_value_debugfs);
3066 
3067 
3068 void qdf_dp_trace_dump_all(uint32_t count, uint8_t pdev_id)
3069 {
3070 	struct qdf_dp_trace_record_s p_record;
3071 	int32_t i, tail;
3072 
3073 	if (!g_qdf_dp_trace_data.enable) {
3074 		DPTRACE_PRINT("Tracing Disabled");
3075 		return;
3076 	}
3077 
3078 	DPTRACE_PRINT(
3079 		"DPT: config - bitmap 0x%x verb %u #rec %u live_config %u thresh %u time_limit %u",
3080 		g_qdf_dp_trace_data.proto_bitmap,
3081 		g_qdf_dp_trace_data.verbosity,
3082 		g_qdf_dp_trace_data.no_of_record,
3083 		g_qdf_dp_trace_data.live_mode_config,
3084 		g_qdf_dp_trace_data.high_tput_thresh,
3085 		g_qdf_dp_trace_data.thresh_time_limit);
3086 
3087 	qdf_dp_trace_dump_stats();
3088 
3089 	DPTRACE_PRINT("DPT: Total Records: %d, Head: %d, Tail: %d",
3090 		      g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head,
3091 		      g_qdf_dp_trace_data.tail);
3092 
3093 	/* acquire the lock so that only one thread at a time can read
3094 	 * the ring buffer
3095 	 */
3096 	spin_lock_bh(&l_dp_trace_lock);
3097 
3098 	if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) {
3099 		i = g_qdf_dp_trace_data.head;
3100 		tail = g_qdf_dp_trace_data.tail;
3101 
3102 		if (count) {
3103 			if (count > g_qdf_dp_trace_data.num)
3104 				count = g_qdf_dp_trace_data.num;
3105 			if (tail >= (count - 1))
3106 				i = tail - count + 1;
3107 			else if (count != MAX_QDF_DP_TRACE_RECORDS)
3108 				i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) -
3109 							     tail);
3110 		}
3111 
3112 		p_record = g_qdf_dp_trace_tbl[i];
3113 		spin_unlock_bh(&l_dp_trace_lock);
3114 		for (;; ) {
3115 			qdf_dp_trace_cb_table[p_record.code](&p_record,
3116 							(uint16_t)i, pdev_id, false);
3117 			if (i == tail)
3118 				break;
3119 			i += 1;
3120 
3121 			spin_lock_bh(&l_dp_trace_lock);
3122 			if (MAX_QDF_DP_TRACE_RECORDS == i)
3123 				i = 0;
3124 
3125 			p_record = g_qdf_dp_trace_tbl[i];
3126 			spin_unlock_bh(&l_dp_trace_lock);
3127 		}
3128 	} else {
3129 		spin_unlock_bh(&l_dp_trace_lock);
3130 	}
3131 }
3132 qdf_export_symbol(qdf_dp_trace_dump_all);
3133 
3134 void qdf_dp_trace_throttle_live_mode(bool high_bw_request)
3135 {
3136 	static int bw_interval_counter;
3137 
3138 	if (g_qdf_dp_trace_data.enable == false ||
3139 		g_qdf_dp_trace_data.live_mode_config == false)
3140 		return;
3141 
3142 	if (high_bw_request) {
3143 		g_qdf_dp_trace_data.live_mode = 0;
3144 		bw_interval_counter = 0;
3145 		return;
3146 	}
3147 
3148 	bw_interval_counter++;
3149 
3150 	if (0 == (bw_interval_counter %
3151 			g_qdf_dp_trace_data.thresh_time_limit)) {
3152 
3153 		spin_lock_bh(&l_dp_trace_lock);
3154 			if (g_qdf_dp_trace_data.print_pkt_cnt <=
3155 				g_qdf_dp_trace_data.high_tput_thresh)
3156 				g_qdf_dp_trace_data.live_mode = 1;
3157 
3158 		g_qdf_dp_trace_data.print_pkt_cnt = 0;
3159 		spin_unlock_bh(&l_dp_trace_lock);
3160 	}
3161 }
3162 qdf_export_symbol(qdf_dp_trace_throttle_live_mode);
3163 
3164 void qdf_dp_trace_apply_tput_policy(bool is_data_traffic)
3165 {
3166 	if (g_qdf_dp_trace_data.dynamic_verbosity_modify) {
3167 		goto check_live_mode;
3168 		return;
3169 	}
3170 
3171 	if (is_data_traffic) {
3172 		g_qdf_dp_trace_data.verbosity =
3173 					QDF_DP_TRACE_VERBOSITY_ULTRA_LOW;
3174 	} else {
3175 		g_qdf_dp_trace_data.verbosity =
3176 					g_qdf_dp_trace_data.ini_conf_verbosity;
3177 	}
3178 check_live_mode:
3179 	qdf_dp_trace_throttle_live_mode(is_data_traffic);
3180 }
3181 #endif
3182 
3183 struct qdf_print_ctrl print_ctrl_obj[MAX_PRINT_CONFIG_SUPPORTED];
3184 
3185 struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = {
3186 	[QDF_MODULE_ID_TDLS] = {"tdls"},
3187 	[QDF_MODULE_ID_ACS] = {"ACS"},
3188 	[QDF_MODULE_ID_SCAN_SM] = {"scan state machine"},
3189 	[QDF_MODULE_ID_SCANENTRY] = {"scan entry"},
3190 	[QDF_MODULE_ID_WDS] = {"WDS"},
3191 	[QDF_MODULE_ID_ACTION] = {"action"},
3192 	[QDF_MODULE_ID_ROAM] = {"STA roaming"},
3193 	[QDF_MODULE_ID_INACT] = {"inactivity"},
3194 	[QDF_MODULE_ID_DOTH] = {"11h"},
3195 	[QDF_MODULE_ID_IQUE] = {"IQUE"},
3196 	[QDF_MODULE_ID_WME] = {"WME"},
3197 	[QDF_MODULE_ID_ACL] = {"ACL"},
3198 	[QDF_MODULE_ID_WPA] = {"WPA/RSN"},
3199 	[QDF_MODULE_ID_RADKEYS] = {"dump 802.1x keys"},
3200 	[QDF_MODULE_ID_RADDUMP] = {"dump radius packet"},
3201 	[QDF_MODULE_ID_RADIUS] = {"802.1x radius client"},
3202 	[QDF_MODULE_ID_DOT1XSM] = {"802.1x state machine"},
3203 	[QDF_MODULE_ID_DOT1X] = {"802.1x authenticator"},
3204 	[QDF_MODULE_ID_POWER] = {"power save"},
3205 	[QDF_MODULE_ID_STATE] = {"state"},
3206 	[QDF_MODULE_ID_OUTPUT] = {"output"},
3207 	[QDF_MODULE_ID_SCAN] = {"scan"},
3208 	[QDF_MODULE_ID_AUTH] = {"authentication"},
3209 	[QDF_MODULE_ID_ASSOC] = {"association"},
3210 	[QDF_MODULE_ID_NODE] = {"node"},
3211 	[QDF_MODULE_ID_ELEMID] = {"element ID"},
3212 	[QDF_MODULE_ID_XRATE] = {"rate"},
3213 	[QDF_MODULE_ID_INPUT] = {"input"},
3214 	[QDF_MODULE_ID_CRYPTO] = {"crypto"},
3215 	[QDF_MODULE_ID_DUMPPKTS] = {"dump packet"},
3216 	[QDF_MODULE_ID_DEBUG] = {"debug"},
3217 	[QDF_MODULE_ID_MLME] = {"mlme"},
3218 	[QDF_MODULE_ID_RRM] = {"rrm"},
3219 	[QDF_MODULE_ID_WNM] = {"wnm"},
3220 	[QDF_MODULE_ID_P2P_PROT] = {"p2p_prot"},
3221 	[QDF_MODULE_ID_PROXYARP] = {"proxyarp"},
3222 	[QDF_MODULE_ID_L2TIF] = {"l2tif"},
3223 	[QDF_MODULE_ID_WIFIPOS] = {"wifipos"},
3224 	[QDF_MODULE_ID_WRAP] = {"wrap"},
3225 	[QDF_MODULE_ID_DFS] = {"dfs"},
3226 	[QDF_MODULE_ID_ATF] = {"atf"},
3227 	[QDF_MODULE_ID_SPLITMAC] = {"splitmac"},
3228 	[QDF_MODULE_ID_IOCTL] = {"ioctl"},
3229 	[QDF_MODULE_ID_NAC] = {"nac"},
3230 	[QDF_MODULE_ID_MESH] = {"mesh"},
3231 	[QDF_MODULE_ID_MBO] = {"mbo"},
3232 	[QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = {"extchanswitch"},
3233 	[QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = {"extchanscan"},
3234 	[QDF_MODULE_ID_TLSHIM] = {"tlshim"},
3235 	[QDF_MODULE_ID_WMI] = {"WMI"},
3236 	[QDF_MODULE_ID_HTT] = {"HTT"},
3237 	[QDF_MODULE_ID_HDD] = {"HDD"},
3238 	[QDF_MODULE_ID_SME] = {"SME"},
3239 	[QDF_MODULE_ID_PE] = {"PE"},
3240 	[QDF_MODULE_ID_WMA] = {"WMA"},
3241 	[QDF_MODULE_ID_SYS] = {"SYS"},
3242 	[QDF_MODULE_ID_QDF] = {"QDF"},
3243 	[QDF_MODULE_ID_SAP] = {"SAP"},
3244 	[QDF_MODULE_ID_HDD_SOFTAP] = {"HDD_SAP"},
3245 	[QDF_MODULE_ID_HDD_DATA] = {"DATA"},
3246 	[QDF_MODULE_ID_HDD_SAP_DATA] = {"SAP_DATA"},
3247 	[QDF_MODULE_ID_HIF] = {"HIF"},
3248 	[QDF_MODULE_ID_HTC] = {"HTC"},
3249 	[QDF_MODULE_ID_TXRX] = {"TXRX"},
3250 	[QDF_MODULE_ID_QDF_DEVICE] = {"QDF_DEV"},
3251 	[QDF_MODULE_ID_CFG] = {"CFG"},
3252 	[QDF_MODULE_ID_BMI] = {"BMI"},
3253 	[QDF_MODULE_ID_EPPING] = {"EPPING"},
3254 	[QDF_MODULE_ID_QVIT] = {"QVIT"},
3255 	[QDF_MODULE_ID_DP] = {"DP"},
3256 	[QDF_MODULE_ID_HAL] = {"HAL"},
3257 	[QDF_MODULE_ID_SOC] = {"SOC"},
3258 	[QDF_MODULE_ID_OS_IF] = {"OSIF"},
3259 	[QDF_MODULE_ID_TARGET_IF] = {"TIF"},
3260 	[QDF_MODULE_ID_SCHEDULER] = {"SCH"},
3261 	[QDF_MODULE_ID_MGMT_TXRX] = {"MGMT_TXRX"},
3262 	[QDF_MODULE_ID_PMO] = {"PMO"},
3263 	[QDF_MODULE_ID_POLICY_MGR] = {"POLICY_MGR"},
3264 	[QDF_MODULE_ID_SA_API] = {"SA_API"},
3265 	[QDF_MODULE_ID_NAN] = {"NAN"},
3266 	[QDF_MODULE_ID_SPECTRAL] = {"SPECTRAL"},
3267 	[QDF_MODULE_ID_P2P] = {"P2P"},
3268 	[QDF_MODULE_ID_OFFCHAN_TXRX] = {"OFFCHAN"},
3269 	[QDF_MODULE_ID_REGULATORY] = {"REGULATORY"},
3270 	[QDF_MODULE_ID_OBJ_MGR] = {"OBJMGR"},
3271 	[QDF_MODULE_ID_SERIALIZATION] = {"SER"},
3272 	[QDF_MODULE_ID_NSS] = {"NSS"},
3273 	[QDF_MODULE_ID_ROAM_DEBUG] = {"roam debug"},
3274 	[QDF_MODULE_ID_DIRECT_BUF_RX] = {"DIRECT_BUF_RX"},
3275 	[QDF_MODULE_ID_DISA] = {"disa"},
3276 	[QDF_MODULE_ID_GREEN_AP] = {"GREEN_AP"},
3277 	[QDF_MODULE_ID_FD] = {"FILS discovery"},
3278 	[QDF_MODULE_ID_FTM] = {"FTM"},
3279 	[QDF_MODULE_ID_OCB] = {"OCB"},
3280 	[QDF_MODULE_ID_CONFIG] = {"CONFIG"},
3281 	[QDF_MODULE_ID_IPA] = {"IPA"},
3282 	[QDF_MODULE_ID_CP_STATS] = {"CP_STATS"},
3283 	[QDF_MODULE_ID_DCS] = {"DCS"},
3284 	[QDF_MODULE_ID_ACTION_OUI] = {"action_oui"},
3285 	[QDF_MODULE_ID_TARGET] = {"TARGET"},
3286 	[QDF_MODULE_ID_MBSSIE] = {"MBSSIE"},
3287 	[QDF_MODULE_ID_FWOL] = {"fwol"},
3288 	[QDF_MODULE_ID_SM_ENGINE] = {"SM_ENG"},
3289 	[QDF_MODULE_ID_CMN_MLME] = {"CMN_MLME"},
3290 	[QDF_MODULE_ID_BSSCOLOR] = {"BSSCOLOR"},
3291 	[QDF_MODULE_ID_CFR] = {"CFR"},
3292 	[QDF_MODULE_ID_DP_TX_CAPTURE] = {"TX_CAPTURE_ENHANCE"},
3293 	[QDF_MODULE_ID_INTEROP_ISSUES_AP] = {"INTEROP_ISSUES_AP"},
3294 	[QDF_MODULE_ID_DENYLIST_MGR] = {"dlm"},
3295 	[QDF_MODULE_ID_QLD] = {"QLD"},
3296 	[QDF_MODULE_ID_DYNAMIC_MODE_CHG] = {"Dynamic Mode Change"},
3297 	[QDF_MODULE_ID_COEX] = {"COEX"},
3298 	[QDF_MODULE_ID_MON_FILTER] = {"Monitor Filter"},
3299 	[QDF_MODULE_ID_PKT_CAPTURE] = {"pkt_capture"},
3300 	[QDF_MODULE_ID_RPTR] = {"RPTR"},
3301 	[QDF_MODULE_ID_6GHZ] = {"6GHZ"},
3302 	[QDF_MODULE_ID_IOT_SIM] = {"IOT_SIM"},
3303 	[QDF_MODULE_ID_MSCS] = {"MSCS"},
3304 	[QDF_MODULE_ID_GPIO] = {"GPIO_CFG"},
3305 	[QDF_MODULE_ID_IFMGR] = {"IF_MGR"},
3306 	[QDF_MODULE_ID_DIAG] = {"DIAG"},
3307 	[QDF_MODULE_ID_DP_INIT] = {"DP_INIT"},
3308 	[QDF_MODULE_ID_DP_TX] = {"DP_TX"},
3309 	[QDF_MODULE_ID_DP_RX] = {"DP_RX"},
3310 	[QDF_MODULE_ID_DP_STATS] = {"DP_STATS"},
3311 	[QDF_MODULE_ID_DP_HTT] = {"DP_HTT"},
3312 	[QDF_MODULE_ID_DP_PEER] = {"DP_PEER"},
3313 	[QDF_MODULE_ID_DP_RX_ERROR] = {"DP_RX_ERROR"},
3314 	[QDF_MODULE_ID_DP_HTT_TX_STATS] = {"DP_HTT_TX_STATS"},
3315 	[QDF_MODULE_ID_DP_RX_MON_STATUS] = {"DP_RX_MON_STATUS"},
3316 	[QDF_MODULE_ID_DP_RX_MON_DEST] = {"DP_RX_MON_DEST"},
3317 	[QDF_MODULE_ID_DP_REO] = {"DP_REO"},
3318 	[QDF_MODULE_ID_DP_TX_COMP] = {"DP_TX_COMP"},
3319 	[QDF_MODULE_ID_DP_VDEV] = {"DP_VDEV"},
3320 	[QDF_MODULE_ID_DP_CDP] = {"DP_CDP"},
3321 	[QDF_MODULE_ID_TSO] = {"TSO"},
3322 	[QDF_MODULE_ID_ME] = {"ME"},
3323 	[QDF_MODULE_ID_QWRAP] = {"QWRAP"},
3324 	[QDF_MODULE_ID_DBDC_REP] = {"DBDC_REP"},
3325 	[QDF_MODULE_ID_EXT_AP] = {"EXT_AP"},
3326 	[QDF_MODULE_ID_MLO] = {"MLO_MGR"},
3327 	[QDF_MODULE_ID_MGMT_RX_REO] = {"MGMT_RX_REO"},
3328 	[QDF_MODULE_ID_MLOIE] = {"MLOIE"},
3329 	[QDF_MODULE_ID_MBSS] = {"MBSS"},
3330 	[QDF_MODULE_ID_MON] = {"MONITOR"},
3331 	[QDF_MODULE_ID_AFC] = {"AFC"},
3332 	[QDF_MODULE_ID_TWT] = {"TWT"},
3333 	[QDF_MODULE_ID_SON] = {"SON"},
3334 	[QDF_MODULE_ID_WLAN_PRE_CAC] = {"PRE_CAC"},
3335 	[QDF_MODULE_ID_T2LM] = {"T2LM"},
3336 	[QDF_MODULE_ID_DP_SAWF] = {"DP_SAWF"},
3337 	[QDF_MODULE_ID_SCS] = {"SCS"},
3338 	[QDF_MODULE_ID_DP_UMAC_RESET] = {"UMAC_HW_RESET"},
3339 	[QDF_MODULE_ID_COAP] = {"COAP"},
3340 	[QDF_MODULE_ID_FTM_TIME_SYNC] = {"Time Sync"},
3341 	[QDF_MODULE_ID_WIFI_RADAR] = {"WIFI RADAR"},
3342 	[QDF_MODULE_ID_CDP] =  {"CDP"},
3343 	[QDF_MODULE_ID_QMI] = {"QMI"},
3344 	[QDF_MODULE_ID_SOUNDING] = {"SOUNDING"},
3345 	[QDF_MODULE_ID_SAWF] = {"SAWF"},
3346 	[QDF_MODULE_ID_EPCS] = {"EPCS"},
3347 	[QDF_MODULE_ID_LL_SAP] = {"LL_SAP"},
3348 	[QDF_MODULE_ID_COHOSTED_BSS] = {"COHOSTED_BSS"},
3349 	[QDF_MODULE_ID_TELEMETRY_AGENT] = {"TELEMETRY_AGENT"},
3350 	[QDF_MODULE_ID_RF_PATH_SWITCH] = {"Dynamic RF Path Switch"},
3351 	[QDF_MODULE_ID_ANY] = {"ANY"},
3352 };
3353 qdf_export_symbol(g_qdf_category_name);
3354 
3355 void qdf_trace_display(void)
3356 {
3357 	QDF_MODULE_ID module_id;
3358 
3359 	pr_err("     1)FATAL  2)ERROR  3)WARN  4)INFO  5)INFO_H  6)INFO_M  7)INFO_L 8)DEBUG\n");
3360 	for (module_id = 0; module_id < QDF_MODULE_ID_MAX; ++module_id) {
3361 		pr_err("%2d)%s    %s        %s       %s       %s        %s         %s         %s        %s\n",
3362 		       (int)module_id,
3363 		       g_qdf_category_name[module_id].category_name_str,
3364 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3365 			       QDF_TRACE_LEVEL_FATAL) ? "X" : " ",
3366 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3367 			       QDF_TRACE_LEVEL_ERROR) ? "X" : " ",
3368 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3369 			       QDF_TRACE_LEVEL_WARN) ? "X" : " ",
3370 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3371 			       QDF_TRACE_LEVEL_INFO) ? "X" : " ",
3372 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3373 			       QDF_TRACE_LEVEL_INFO_HIGH) ? "X" : " ",
3374 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3375 			       QDF_TRACE_LEVEL_INFO_MED) ? "X" : " ",
3376 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3377 			       QDF_TRACE_LEVEL_INFO_LOW) ? "X" : " ",
3378 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3379 			       QDF_TRACE_LEVEL_DEBUG) ? "X" : " ");
3380 	}
3381 }
3382 qdf_export_symbol(qdf_trace_display);
3383 
3384 #ifdef WLAN_MAX_LOGS_PER_SEC
3385 static qdf_time_t __log_window_end;
3386 static qdf_atomic_t __log_window_count;
3387 uint32_t qdf_rl_print_count = WLAN_MAX_LOGS_PER_SEC;
3388 uint32_t qdf_rl_print_time = 1;
3389 uint32_t qdf_rl_print_suppressed;
3390 
3391 bool qdf_detected_excessive_logging(void)
3392 {
3393 	qdf_time_t now = qdf_system_ticks();
3394 	bool excessive_prints = false;
3395 
3396 	/*
3397 	 * If 'now' is more recent than the end of the window, reset.
3398 	 *
3399 	 * Note: This is not thread safe, and can result in more than one reset.
3400 	 * For our purposes, this is fine.
3401 	 */
3402 	if (!qdf_atomic_read(&__log_window_count)) {
3403 		__log_window_end = now + (qdf_system_ticks_per_sec * qdf_rl_print_time);
3404 	} else if (qdf_system_time_after(now, __log_window_end)) {
3405 		__log_window_end = now + (qdf_system_ticks_per_sec * qdf_rl_print_time);
3406 		qdf_atomic_set(&__log_window_count, 0);
3407 	}
3408 
3409 	if (qdf_atomic_inc_return(&__log_window_count) > qdf_rl_print_count)
3410 		excessive_prints = true;
3411 
3412 	return excessive_prints;
3413 }
3414 
3415 void qdf_rl_print_count_set(uint32_t rl_print_count)
3416 {
3417 	qdf_rl_print_count = rl_print_count;
3418 }
3419 
3420 qdf_export_symbol(qdf_rl_print_count_set);
3421 
3422 void qdf_rl_print_time_set(uint32_t rl_print_time)
3423 {
3424 	qdf_rl_print_time = rl_print_time;
3425 }
3426 
3427 qdf_export_symbol(qdf_rl_print_time_set);
3428 
3429 void qdf_rl_print_suppressed_log(void)
3430 {
3431 	if (qdf_rl_print_suppressed) {
3432 		pr_err("QDF Ratelimiting: %d prints suppressed",
3433 		       qdf_rl_print_suppressed);
3434 		qdf_rl_print_suppressed = 0;
3435 	}
3436 }
3437 
3438 void qdf_rl_print_suppressed_inc(void)
3439 {
3440 	qdf_rl_print_suppressed++;
3441 }
3442 #else
3443 #define qdf_rl_print_suppressed_log()
3444 #define qdf_rl_print_suppressed_inc()
3445 #endif /* WLAN_MAX_LOGS_PER_SEC */
3446 
3447 #ifdef QDF_TRACE_PRINT_ENABLE
3448 static inline void print_to_console(char *str_buffer)
3449 {
3450 	if (qdf_in_interrupt() && qdf_detected_excessive_logging()) {
3451 		qdf_rl_print_suppressed_inc();
3452 		return;
3453 	}
3454 	qdf_rl_print_suppressed_log();
3455 	pr_err("%s\n", str_buffer);
3456 }
3457 #else
3458 
3459 #define print_to_console(str)
3460 #endif
3461 
3462 #ifdef MULTI_IF_NAME
3463 static const char *qdf_trace_wlan_modname(void)
3464 {
3465 	return MULTI_IF_NAME;
3466 }
3467 #else
3468 static const char *qdf_trace_wlan_modname(void)
3469 {
3470 	return "wlan";
3471 }
3472 #endif
3473 
3474 void qdf_trace_msg_cmn(unsigned int idx,
3475 			QDF_MODULE_ID category,
3476 			QDF_TRACE_LEVEL verbose,
3477 			const char *str_format, va_list val)
3478 {
3479 	char str_buffer[QDF_TRACE_BUFFER_SIZE];
3480 	int n;
3481 
3482 	/* Check if index passed is valid */
3483 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3484 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3485 		return;
3486 	}
3487 
3488 	/* Check if print control object is in use */
3489 	if (!print_ctrl_obj[idx].in_use) {
3490 		pr_info("%s: Invalid print control object\n", __func__);
3491 		return;
3492 	}
3493 
3494 	/* Check if category passed is valid */
3495 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
3496 		vscnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, str_format, val);
3497 		pr_info("%s: Invalid category: %d, log: %s\n",
3498 			__func__, category, str_buffer);
3499 		return;
3500 	}
3501 
3502 	/* Check if verbose mask is valid */
3503 	if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
3504 		vscnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, str_format, val);
3505 		pr_info("%s: Invalid verbose level %d, log: %s\n",
3506 			__func__, verbose, str_buffer);
3507 		return;
3508 	}
3509 
3510 	/*
3511 	 * Print the trace message when the desired verbose level is set in
3512 	 * the desired category for the print control object
3513 	 */
3514 	if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
3515 	    QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
3516 		static const char * const VERBOSE_STR[] = {
3517 			[QDF_TRACE_LEVEL_NONE] = "",
3518 			[QDF_TRACE_LEVEL_FATAL] = "F",
3519 			[QDF_TRACE_LEVEL_ERROR] = "E",
3520 			[QDF_TRACE_LEVEL_WARN] = "W",
3521 			[QDF_TRACE_LEVEL_INFO] = "I",
3522 			[QDF_TRACE_LEVEL_INFO_HIGH] = "IH",
3523 			[QDF_TRACE_LEVEL_INFO_MED] = "IM",
3524 			[QDF_TRACE_LEVEL_INFO_LOW] = "IL",
3525 			[QDF_TRACE_LEVEL_DEBUG] = "D",
3526 			[QDF_TRACE_LEVEL_TRACE] = "T",
3527 			[QDF_TRACE_LEVEL_ALL] = "" };
3528 
3529 		/* print the prefix string into the string buffer... */
3530 		n = scnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE,
3531 			     "%s: [%d:%s:%s] ", qdf_trace_wlan_modname(),
3532 			     in_interrupt() ? 0 : current->pid,
3533 			     VERBOSE_STR[verbose],
3534 			     g_qdf_category_name[category].category_name_str);
3535 
3536 		/* print the formatted log message after the prefix string */
3537 		vscnprintf(str_buffer + n, QDF_TRACE_BUFFER_SIZE - n,
3538 			   str_format, val);
3539 #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE)
3540 		wlan_log_to_user(verbose, (char *)str_buffer,
3541 				 strlen(str_buffer));
3542 		if (qdf_unlikely(qdf_log_dump_at_kernel_enable))
3543 			print_to_console(str_buffer);
3544 #else
3545 		pr_err("%s\n", str_buffer);
3546 #endif
3547 	}
3548 }
3549 qdf_export_symbol(qdf_trace_msg_cmn);
3550 
3551 QDF_STATUS qdf_print_setup(void)
3552 {
3553 	int i;
3554 
3555 	/* Loop through all print ctrl objects */
3556 	for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
3557 		if (qdf_print_ctrl_cleanup(i))
3558 			return QDF_STATUS_E_FAILURE;
3559 	}
3560 	return QDF_STATUS_SUCCESS;
3561 }
3562 qdf_export_symbol(qdf_print_setup);
3563 
3564 QDF_STATUS qdf_print_ctrl_cleanup(unsigned int idx)
3565 {
3566 	int i = 0;
3567 
3568 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3569 		pr_info("%s: Invalid index - %d\n", __func__, idx);
3570 		return QDF_STATUS_E_FAILURE;
3571 	}
3572 
3573 	/* Clean up the print control object corresponding to that index
3574 	 * If success, callee to change print control index to -1
3575 	 */
3576 
3577 	for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3578 		print_ctrl_obj[idx].cat_info[i].category_verbose_mask =
3579 							QDF_TRACE_LEVEL_NONE;
3580 	}
3581 	print_ctrl_obj[idx].custom_print = NULL;
3582 	print_ctrl_obj[idx].custom_ctxt = NULL;
3583 	qdf_print_clean_node_flag(idx);
3584 	print_ctrl_obj[idx].in_use = false;
3585 
3586 	return QDF_STATUS_SUCCESS;
3587 }
3588 qdf_export_symbol(qdf_print_ctrl_cleanup);
3589 
3590 int qdf_print_ctrl_register(const struct category_info *cinfo,
3591 			    void *custom_print_handler,
3592 			    void *custom_ctx,
3593 			    const char *pctrl_name)
3594 {
3595 	int idx = -1;
3596 	int i = 0;
3597 
3598 	for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
3599 		if (!print_ctrl_obj[i].in_use) {
3600 			idx = i;
3601 			break;
3602 		}
3603 	}
3604 
3605 	/* Callee to handle idx -1 appropriately */
3606 	if (idx == -1) {
3607 		pr_info("%s: Allocation failed! No print control object free\n",
3608 			__func__);
3609 		return idx;
3610 	}
3611 
3612 	print_ctrl_obj[idx].in_use = true;
3613 
3614 	/*
3615 	 * In case callee does not pass category info,
3616 	 * custom print handler, custom context and print control name,
3617 	 * we do not set any value here. Clean up for the print control
3618 	 * getting allocated would have taken care of initializing
3619 	 * default values.
3620 	 *
3621 	 * We need to only set in_use to 1 in such a case
3622 	 */
3623 
3624 	if (pctrl_name) {
3625 		qdf_str_lcopy(print_ctrl_obj[idx].name, pctrl_name,
3626 			      sizeof(print_ctrl_obj[idx].name));
3627 	}
3628 
3629 	if (custom_print_handler)
3630 		print_ctrl_obj[idx].custom_print = custom_print_handler;
3631 
3632 	if (custom_ctx)
3633 		print_ctrl_obj[idx].custom_ctxt = custom_ctx;
3634 
3635 	if (cinfo) {
3636 		for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3637 			if (cinfo[i].category_verbose_mask ==
3638 			    QDF_TRACE_LEVEL_ALL) {
3639 				print_ctrl_obj[idx].cat_info[i]
3640 				.category_verbose_mask = 0xFFFF;
3641 			} else if ((cinfo[i].category_verbose_mask ==
3642 				   QDF_TRACE_LEVEL_NONE) ||
3643 				   (cinfo[i].category_verbose_mask ==
3644 				   QDF_TRACE_LEVEL_TO_MODULE_BITMASK(
3645 				   QDF_TRACE_LEVEL_NONE))) {
3646 				print_ctrl_obj[idx].cat_info[i]
3647 				.category_verbose_mask = 0;
3648 			} else {
3649 				print_ctrl_obj[idx].cat_info[i]
3650 				.category_verbose_mask =
3651 				cinfo[i].category_verbose_mask;
3652 			}
3653 		}
3654 	}
3655 
3656 	return idx;
3657 }
3658 qdf_export_symbol(qdf_print_ctrl_register);
3659 
3660 #ifdef QDF_TRACE_PRINT_ENABLE
3661 void qdf_shared_print_ctrl_cleanup(void)
3662 {
3663 	qdf_print_ctrl_cleanup(qdf_pidx);
3664 }
3665 qdf_export_symbol(qdf_shared_print_ctrl_cleanup);
3666 
3667 /*
3668  * Set this to invalid value to differentiate with user-provided
3669  * value.
3670  */
3671 int qdf_dbg_mask = QDF_TRACE_LEVEL_MAX;
3672 qdf_export_symbol(qdf_dbg_mask);
3673 qdf_declare_param(qdf_dbg_mask, int);
3674 
3675 /*
3676  * QDF can be passed parameters which indicate the
3677  * debug level for each module.
3678  * an array of string values are passed, each string hold the following form
3679  *
3680  * <module name string>=<integer debug level value>
3681  *
3682  * The array qdf_dbg_arr will hold these module-string=value strings
3683  * The variable qdf_dbg_arr_cnt will have the count of how many such
3684  * string values were passed.
3685  */
3686 static char *qdf_dbg_arr[QDF_MODULE_ID_MAX];
3687 static int qdf_dbg_arr_cnt;
3688 qdf_declare_param_array(qdf_dbg_arr, charp, &qdf_dbg_arr_cnt);
3689 
3690 static uint16_t set_cumulative_verbose_mask(QDF_TRACE_LEVEL max_level)
3691 {
3692 	uint16_t category_verbose_mask = 0;
3693 	QDF_TRACE_LEVEL level;
3694 
3695 	for (level = QDF_TRACE_LEVEL_FATAL; level <= max_level; level++) {
3696 		category_verbose_mask |=
3697 			QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level);
3698 	}
3699 	return category_verbose_mask;
3700 }
3701 
3702 static QDF_MODULE_ID find_qdf_module_from_string(char *str)
3703 {
3704 	QDF_MODULE_ID mod_id;
3705 
3706 	for (mod_id = 0; mod_id < QDF_MODULE_ID_MAX; mod_id++) {
3707 		if (strcasecmp(str,
3708 				g_qdf_category_name[mod_id].category_name_str)
3709 				== 0) {
3710 			break;
3711 		}
3712 	}
3713 	return mod_id;
3714 }
3715 
3716 static void process_qdf_dbg_arr_param(struct category_info *cinfo,
3717 					int array_index)
3718 {
3719 	char *mod_val_str, *mod_str, *val_str;
3720 	unsigned long dbg_level;
3721 	QDF_MODULE_ID mod_id;
3722 
3723 	mod_val_str = qdf_dbg_arr[array_index];
3724 	mod_str = strsep(&mod_val_str, "=");
3725 	val_str = mod_val_str;
3726 	if (!val_str) {
3727 		pr_info("qdf_dbg_arr: %s not in the <mod>=<val> form\n",
3728 				mod_str);
3729 		return;
3730 	}
3731 
3732 	mod_id = find_qdf_module_from_string(mod_str);
3733 	if (mod_id >= QDF_MODULE_ID_MAX) {
3734 		pr_info("ERROR!!Module name %s not in the list of modules\n",
3735 				mod_str);
3736 		return;
3737 	}
3738 
3739 	if (kstrtol(val_str, 10, &dbg_level) < 0) {
3740 		pr_info("ERROR!!Invalid debug level for module: %s\n",
3741 				mod_str);
3742 		return;
3743 	}
3744 
3745 	if (dbg_level >= QDF_TRACE_LEVEL_MAX) {
3746 		pr_info("ERROR!!Debug level for %s too high", mod_str);
3747 		pr_info("max: %d given %lu\n", QDF_TRACE_LEVEL_MAX,
3748 				dbg_level);
3749 		return;
3750 	}
3751 
3752 	pr_info("User passed setting module %s(%d) to level %lu\n",
3753 			mod_str,
3754 			mod_id,
3755 			dbg_level);
3756 	cinfo[mod_id].category_verbose_mask =
3757 		set_cumulative_verbose_mask((QDF_TRACE_LEVEL)dbg_level);
3758 }
3759 
3760 static void set_default_trace_levels(struct category_info *cinfo)
3761 {
3762 	int i;
3763 	static QDF_TRACE_LEVEL module_trace_default_level[QDF_MODULE_ID_MAX] = {
3764 		[QDF_MODULE_ID_TDLS] = QDF_TRACE_LEVEL_NONE,
3765 		[QDF_MODULE_ID_ACS] = QDF_TRACE_LEVEL_NONE,
3766 		[QDF_MODULE_ID_SCAN_SM] = QDF_TRACE_LEVEL_NONE,
3767 		[QDF_MODULE_ID_SCANENTRY] = QDF_TRACE_LEVEL_NONE,
3768 		[QDF_MODULE_ID_WDS] = QDF_TRACE_LEVEL_NONE,
3769 		[QDF_MODULE_ID_ACTION] = QDF_TRACE_LEVEL_NONE,
3770 		[QDF_MODULE_ID_ROAM] = QDF_TRACE_LEVEL_NONE,
3771 		[QDF_MODULE_ID_INACT] = QDF_TRACE_LEVEL_NONE,
3772 		[QDF_MODULE_ID_DOTH] = QDF_TRACE_LEVEL_NONE,
3773 		[QDF_MODULE_ID_IQUE] = QDF_TRACE_LEVEL_NONE,
3774 		[QDF_MODULE_ID_WME] = QDF_TRACE_LEVEL_NONE,
3775 		[QDF_MODULE_ID_ACL] = QDF_TRACE_LEVEL_NONE,
3776 		[QDF_MODULE_ID_WPA] = QDF_TRACE_LEVEL_NONE,
3777 		[QDF_MODULE_ID_RADKEYS] = QDF_TRACE_LEVEL_NONE,
3778 		[QDF_MODULE_ID_RADDUMP] = QDF_TRACE_LEVEL_NONE,
3779 		[QDF_MODULE_ID_RADIUS] = QDF_TRACE_LEVEL_NONE,
3780 		[QDF_MODULE_ID_DOT1XSM] = QDF_TRACE_LEVEL_NONE,
3781 		[QDF_MODULE_ID_DOT1X] = QDF_TRACE_LEVEL_NONE,
3782 		[QDF_MODULE_ID_POWER] = QDF_TRACE_LEVEL_NONE,
3783 		[QDF_MODULE_ID_STATE] = QDF_TRACE_LEVEL_NONE,
3784 		[QDF_MODULE_ID_OUTPUT] = QDF_TRACE_LEVEL_NONE,
3785 		[QDF_MODULE_ID_SCAN] = QDF_TRACE_LEVEL_ERROR,
3786 		[QDF_MODULE_ID_AUTH] = QDF_TRACE_LEVEL_NONE,
3787 		[QDF_MODULE_ID_ASSOC] = QDF_TRACE_LEVEL_NONE,
3788 		[QDF_MODULE_ID_NODE] = QDF_TRACE_LEVEL_NONE,
3789 		[QDF_MODULE_ID_ELEMID] = QDF_TRACE_LEVEL_NONE,
3790 		[QDF_MODULE_ID_XRATE] = QDF_TRACE_LEVEL_NONE,
3791 		[QDF_MODULE_ID_INPUT] = QDF_TRACE_LEVEL_NONE,
3792 		[QDF_MODULE_ID_CRYPTO] = QDF_TRACE_LEVEL_NONE,
3793 		[QDF_MODULE_ID_DUMPPKTS] = QDF_TRACE_LEVEL_NONE,
3794 		[QDF_MODULE_ID_DEBUG] = QDF_TRACE_LEVEL_NONE,
3795 		[QDF_MODULE_ID_MLME] = QDF_TRACE_LEVEL_ERROR,
3796 		[QDF_MODULE_ID_RRM] = QDF_TRACE_LEVEL_NONE,
3797 		[QDF_MODULE_ID_WNM] = QDF_TRACE_LEVEL_NONE,
3798 		[QDF_MODULE_ID_P2P_PROT] = QDF_TRACE_LEVEL_NONE,
3799 		[QDF_MODULE_ID_PROXYARP] = QDF_TRACE_LEVEL_NONE,
3800 		[QDF_MODULE_ID_L2TIF] = QDF_TRACE_LEVEL_NONE,
3801 		[QDF_MODULE_ID_WIFIPOS] = QDF_TRACE_LEVEL_NONE,
3802 		[QDF_MODULE_ID_WRAP] = QDF_TRACE_LEVEL_NONE,
3803 		[QDF_MODULE_ID_DFS] = QDF_TRACE_LEVEL_NONE,
3804 		[QDF_MODULE_ID_ATF] = QDF_TRACE_LEVEL_ERROR,
3805 		[QDF_MODULE_ID_SPLITMAC] = QDF_TRACE_LEVEL_NONE,
3806 		[QDF_MODULE_ID_IOCTL] = QDF_TRACE_LEVEL_NONE,
3807 		[QDF_MODULE_ID_NAC] = QDF_TRACE_LEVEL_NONE,
3808 		[QDF_MODULE_ID_MESH] = QDF_TRACE_LEVEL_NONE,
3809 		[QDF_MODULE_ID_MBO] = QDF_TRACE_LEVEL_NONE,
3810 		[QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = QDF_TRACE_LEVEL_NONE,
3811 		[QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = QDF_TRACE_LEVEL_NONE,
3812 		[QDF_MODULE_ID_TLSHIM] = QDF_TRACE_LEVEL_NONE,
3813 		[QDF_MODULE_ID_WMI] = QDF_TRACE_LEVEL_ERROR,
3814 		[QDF_MODULE_ID_HTT] = QDF_TRACE_LEVEL_NONE,
3815 		[QDF_MODULE_ID_HDD] = QDF_TRACE_LEVEL_NONE,
3816 		[QDF_MODULE_ID_SME] = QDF_TRACE_LEVEL_NONE,
3817 		[QDF_MODULE_ID_PE] = QDF_TRACE_LEVEL_NONE,
3818 		[QDF_MODULE_ID_WMA] = QDF_TRACE_LEVEL_NONE,
3819 		[QDF_MODULE_ID_SYS] = QDF_TRACE_LEVEL_NONE,
3820 		[QDF_MODULE_ID_QDF] = QDF_TRACE_LEVEL_ERROR,
3821 		[QDF_MODULE_ID_SAP] = QDF_TRACE_LEVEL_NONE,
3822 		[QDF_MODULE_ID_HDD_SOFTAP] = QDF_TRACE_LEVEL_NONE,
3823 		[QDF_MODULE_ID_HDD_DATA] = QDF_TRACE_LEVEL_NONE,
3824 		[QDF_MODULE_ID_HDD_SAP_DATA] = QDF_TRACE_LEVEL_NONE,
3825 		[QDF_MODULE_ID_HIF] = QDF_TRACE_LEVEL_ERROR,
3826 		[QDF_MODULE_ID_HTC] = QDF_TRACE_LEVEL_NONE,
3827 		[QDF_MODULE_ID_TXRX] = QDF_TRACE_LEVEL_NONE,
3828 		[QDF_MODULE_ID_QDF_DEVICE] = QDF_TRACE_LEVEL_NONE,
3829 		[QDF_MODULE_ID_CFG] = QDF_TRACE_LEVEL_NONE,
3830 		[QDF_MODULE_ID_BMI] = QDF_TRACE_LEVEL_NONE,
3831 		[QDF_MODULE_ID_EPPING] = QDF_TRACE_LEVEL_NONE,
3832 		[QDF_MODULE_ID_QVIT] = QDF_TRACE_LEVEL_NONE,
3833 		[QDF_MODULE_ID_DP] = QDF_TRACE_LEVEL_FATAL,
3834 		[QDF_MODULE_ID_HAL] = QDF_TRACE_LEVEL_NONE,
3835 		[QDF_MODULE_ID_SOC] = QDF_TRACE_LEVEL_NONE,
3836 		[QDF_MODULE_ID_OS_IF] = QDF_TRACE_LEVEL_NONE,
3837 		[QDF_MODULE_ID_TARGET_IF] = QDF_TRACE_LEVEL_INFO,
3838 		[QDF_MODULE_ID_SCHEDULER] = QDF_TRACE_LEVEL_FATAL,
3839 		[QDF_MODULE_ID_MGMT_TXRX] = QDF_TRACE_LEVEL_NONE,
3840 		[QDF_MODULE_ID_SERIALIZATION] = QDF_TRACE_LEVEL_ERROR,
3841 		[QDF_MODULE_ID_PMO] = QDF_TRACE_LEVEL_NONE,
3842 		[QDF_MODULE_ID_P2P] = QDF_TRACE_LEVEL_NONE,
3843 		[QDF_MODULE_ID_POLICY_MGR] = QDF_TRACE_LEVEL_NONE,
3844 		[QDF_MODULE_ID_CONFIG] = QDF_TRACE_LEVEL_ERROR,
3845 		[QDF_MODULE_ID_REGULATORY] = QDF_TRACE_LEVEL_NONE,
3846 		[QDF_MODULE_ID_SA_API] = QDF_TRACE_LEVEL_NONE,
3847 		[QDF_MODULE_ID_NAN] = QDF_TRACE_LEVEL_NONE,
3848 		[QDF_MODULE_ID_OFFCHAN_TXRX] = QDF_TRACE_LEVEL_NONE,
3849 		[QDF_MODULE_ID_SON] = QDF_TRACE_LEVEL_NONE,
3850 		[QDF_MODULE_ID_SPECTRAL] = QDF_TRACE_LEVEL_ERROR,
3851 		[QDF_MODULE_ID_OBJ_MGR] = QDF_TRACE_LEVEL_FATAL,
3852 		[QDF_MODULE_ID_NSS] = QDF_TRACE_LEVEL_ERROR,
3853 		[QDF_MODULE_ID_ROAM_DEBUG] = QDF_TRACE_LEVEL_ERROR,
3854 		[QDF_MODULE_ID_CDP] = QDF_TRACE_LEVEL_NONE,
3855 		[QDF_MODULE_ID_DIRECT_BUF_RX] = QDF_TRACE_LEVEL_ERROR,
3856 		[QDF_MODULE_ID_DISA] = QDF_TRACE_LEVEL_NONE,
3857 		[QDF_MODULE_ID_GREEN_AP] = QDF_TRACE_LEVEL_ERROR,
3858 		[QDF_MODULE_ID_FTM] = QDF_TRACE_LEVEL_ERROR,
3859 		[QDF_MODULE_ID_FD] = QDF_TRACE_LEVEL_ERROR,
3860 		[QDF_MODULE_ID_OCB] = QDF_TRACE_LEVEL_ERROR,
3861 		[QDF_MODULE_ID_IPA] = QDF_TRACE_LEVEL_NONE,
3862 		[QDF_MODULE_ID_ACTION_OUI] = QDF_TRACE_LEVEL_NONE,
3863 		[QDF_MODULE_ID_CP_STATS] = QDF_TRACE_LEVEL_ERROR,
3864 		[QDF_MODULE_ID_DCS] = QDF_TRACE_LEVEL_ERROR,
3865 		[QDF_MODULE_ID_MBSSIE] = QDF_TRACE_LEVEL_INFO,
3866 		[QDF_MODULE_ID_FWOL] = QDF_TRACE_LEVEL_NONE,
3867 		[QDF_MODULE_ID_SM_ENGINE] = QDF_TRACE_LEVEL_ERROR,
3868 		[QDF_MODULE_ID_CMN_MLME] = QDF_TRACE_LEVEL_INFO,
3869 		[QDF_MODULE_ID_BSSCOLOR] = QDF_TRACE_LEVEL_ERROR,
3870 		[QDF_MODULE_ID_CFR] = QDF_TRACE_LEVEL_ERROR,
3871 		[QDF_MODULE_ID_DP_TX_CAPTURE] = QDF_TRACE_LEVEL_FATAL,
3872 		[QDF_MODULE_ID_INTEROP_ISSUES_AP] = QDF_TRACE_LEVEL_NONE,
3873 		[QDF_MODULE_ID_DENYLIST_MGR] = QDF_TRACE_LEVEL_NONE,
3874 		[QDF_MODULE_ID_QLD] = QDF_TRACE_LEVEL_ERROR,
3875 		[QDF_MODULE_ID_DYNAMIC_MODE_CHG] = QDF_TRACE_LEVEL_INFO,
3876 		[QDF_MODULE_ID_COEX] = QDF_TRACE_LEVEL_ERROR,
3877 		[QDF_MODULE_ID_MON_FILTER] = QDF_TRACE_LEVEL_INFO,
3878 		[QDF_MODULE_ID_PKT_CAPTURE] = QDF_TRACE_LEVEL_NONE,
3879 		[QDF_MODULE_ID_RPTR] = QDF_TRACE_LEVEL_INFO,
3880 		[QDF_MODULE_ID_6GHZ] = QDF_TRACE_LEVEL_ERROR,
3881 		[QDF_MODULE_ID_IOT_SIM] = QDF_TRACE_LEVEL_ERROR,
3882 		[QDF_MODULE_ID_MSCS] = QDF_TRACE_LEVEL_INFO,
3883 		[QDF_MODULE_ID_GPIO] = QDF_TRACE_LEVEL_NONE,
3884 		[QDF_MODULE_ID_IFMGR] = QDF_TRACE_LEVEL_ERROR,
3885 		[QDF_MODULE_ID_DIAG] = QDF_TRACE_LEVEL_ERROR,
3886 		[QDF_MODULE_ID_DP_INIT] = QDF_TRACE_LEVEL_FATAL,
3887 		[QDF_MODULE_ID_DP_TX] = QDF_TRACE_LEVEL_FATAL,
3888 		[QDF_MODULE_ID_DP_RX] = QDF_TRACE_LEVEL_FATAL,
3889 		[QDF_MODULE_ID_DP_STATS] = QDF_TRACE_LEVEL_FATAL,
3890 		[QDF_MODULE_ID_DP_HTT] = QDF_TRACE_LEVEL_FATAL,
3891 		[QDF_MODULE_ID_DP_PEER] = QDF_TRACE_LEVEL_FATAL,
3892 		[QDF_MODULE_ID_DP_RX_ERROR] = QDF_TRACE_LEVEL_FATAL,
3893 		[QDF_MODULE_ID_DP_HTT_TX_STATS] = QDF_TRACE_LEVEL_FATAL,
3894 		[QDF_MODULE_ID_DP_RX_MON_STATUS] = QDF_TRACE_LEVEL_FATAL,
3895 		[QDF_MODULE_ID_DP_RX_MON_DEST] = QDF_TRACE_LEVEL_FATAL,
3896 		[QDF_MODULE_ID_DP_REO] = QDF_TRACE_LEVEL_FATAL,
3897 		[QDF_MODULE_ID_DP_TX_COMP] = QDF_TRACE_LEVEL_FATAL,
3898 		[QDF_MODULE_ID_DP_VDEV] = QDF_TRACE_LEVEL_FATAL,
3899 		[QDF_MODULE_ID_DP_CDP] = QDF_TRACE_LEVEL_FATAL,
3900 		[QDF_MODULE_ID_TSO] = QDF_TRACE_LEVEL_FATAL,
3901 		[QDF_MODULE_ID_ME] = QDF_TRACE_LEVEL_INFO,
3902 		[QDF_MODULE_ID_QWRAP] = QDF_TRACE_LEVEL_FATAL,
3903 		[QDF_MODULE_ID_DBDC_REP] = QDF_TRACE_LEVEL_FATAL,
3904 		[QDF_MODULE_ID_EXT_AP] = QDF_TRACE_LEVEL_NONE,
3905 		[QDF_MODULE_ID_MLO] = QDF_TRACE_LEVEL_INFO,
3906 		[QDF_MODULE_ID_MLOIE] = QDF_TRACE_LEVEL_INFO,
3907 		[QDF_MODULE_ID_MBSS] = QDF_TRACE_LEVEL_ERROR,
3908 		[QDF_MODULE_ID_MON] = QDF_TRACE_LEVEL_ERROR,
3909 		[QDF_MODULE_ID_MGMT_RX_REO] = QDF_TRACE_LEVEL_WARN,
3910 		[QDF_MODULE_ID_TWT] = QDF_TRACE_LEVEL_ERROR,
3911 		[QDF_MODULE_ID_WLAN_PRE_CAC] = QDF_TRACE_LEVEL_ERROR,
3912 		[QDF_MODULE_ID_T2LM] = QDF_TRACE_LEVEL_ERROR,
3913 		[QDF_MODULE_ID_DP_SAWF] = QDF_TRACE_LEVEL_ERROR,
3914 		[QDF_MODULE_ID_SCS] = QDF_TRACE_LEVEL_ERROR,
3915 		[QDF_MODULE_ID_DP_UMAC_RESET] = QDF_TRACE_LEVEL_ERROR,
3916 		[QDF_MODULE_ID_COAP] = QDF_TRACE_LEVEL_ERROR,
3917 		[QDF_MODULE_ID_FTM_TIME_SYNC] = QDF_TRACE_LEVEL_NONE,
3918 		[QDF_MODULE_ID_AFC] = QDF_TRACE_LEVEL_NONE,
3919 		[QDF_MODULE_ID_WIFI_RADAR] = QDF_TRACE_LEVEL_NONE,
3920 		[QDF_MODULE_ID_TARGET] = QDF_TRACE_LEVEL_NONE,
3921 		[QDF_MODULE_ID_QMI] = QDF_TRACE_LEVEL_ERROR,
3922 		[QDF_MODULE_ID_SOUNDING] = QDF_TRACE_LEVEL_ERROR,
3923 		[QDF_MODULE_ID_SAWF] = QDF_TRACE_LEVEL_INFO,
3924 		[QDF_MODULE_ID_EPCS] = QDF_TRACE_LEVEL_INFO,
3925 		[QDF_MODULE_ID_LL_SAP] = QDF_TRACE_LEVEL_NONE,
3926 		[QDF_MODULE_ID_COHOSTED_BSS] = QDF_TRACE_LEVEL_INFO,
3927 		[QDF_MODULE_ID_TELEMETRY_AGENT] = QDF_TRACE_LEVEL_ERROR,
3928 		[QDF_MODULE_ID_RF_PATH_SWITCH] = QDF_TRACE_LEVEL_INFO,
3929 		[QDF_MODULE_ID_ANY] = QDF_TRACE_LEVEL_INFO,
3930 	};
3931 
3932 	for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3933 		cinfo[i].category_verbose_mask = set_cumulative_verbose_mask(
3934 				module_trace_default_level[i]);
3935 	}
3936 }
3937 
3938 void qdf_shared_print_ctrl_init(void)
3939 {
3940 	int i;
3941 	struct category_info cinfo[MAX_SUPPORTED_CATEGORY];
3942 
3943 	set_default_trace_levels(cinfo);
3944 
3945 	/*
3946 	 * User specified across-module single debug level
3947 	 */
3948 	if ((qdf_dbg_mask >= 0) && (qdf_dbg_mask < QDF_TRACE_LEVEL_MAX)) {
3949 		pr_info("User specified module debug level of %d\n",
3950 			qdf_dbg_mask);
3951 		for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3952 			cinfo[i].category_verbose_mask =
3953 			set_cumulative_verbose_mask(qdf_dbg_mask);
3954 		}
3955 	} else if (qdf_dbg_mask != QDF_TRACE_LEVEL_MAX) {
3956 		pr_info("qdf_dbg_mask value is invalid\n");
3957 		pr_info("Using the default module debug levels instead\n");
3958 	}
3959 
3960 	/*
3961 	 * Module ID-Level specified as array during module load
3962 	 */
3963 	for (i = 0; i < qdf_dbg_arr_cnt; i++) {
3964 		process_qdf_dbg_arr_param(cinfo, i);
3965 	}
3966 	qdf_pidx = qdf_print_ctrl_register(cinfo, NULL, NULL,
3967 			"LOG_SHARED_OBJ");
3968 }
3969 qdf_export_symbol(qdf_shared_print_ctrl_init);
3970 #endif
3971 
3972 #ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI
3973 QDF_STATUS qdf_module_param_handler(void *context, const char *str_param,
3974 				    const char *str)
3975 {
3976 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
3977 	uint16_t param = 0;
3978 	uint32_t flush_tmr_prd;
3979 	bool dump_flag;
3980 
3981 	while (param < QDF_PARAM_MAX) {
3982 		if (qdf_str_eq(qdf_module_param[param], str_param)) {
3983 			switch (param) {
3984 			case MEM_DEBUG_DISABLED:
3985 				status = qdf_mem_debug_disabled_config_set(str);
3986 				break;
3987 			case QDF_DBG_MASK:
3988 				status = qdf_int32_parse(str, &qdf_dbg_mask);
3989 				break;
3990 			case PREALLOC_DISABLED:
3991 				status = qdf_prealloc_disabled_config_set(str);
3992 				break;
3993 			case QDF_LOG_DUMP_AT_KERNEL_ENABLE:
3994 				status = qdf_bool_parse(str, &dump_flag);
3995 				qdf_log_dump_at_kernel_enable = dump_flag;
3996 				break;
3997 			case QDF_DBG_ARR:
3998 				qdf_dbg_arr[0] = (char *)str;
3999 				status = QDF_STATUS_SUCCESS;
4000 				break;
4001 			case QDF_LOG_FLUSH_TIMER_PERIOD:
4002 				status = qdf_uint32_parse(str, &flush_tmr_prd);
4003 				qdf_log_flush_timer_period = flush_tmr_prd;
4004 				break;
4005 			default:
4006 				break;
4007 			}
4008 			return status;
4009 		}
4010 		param++;
4011 	}
4012 
4013 	return QDF_STATUS_SUCCESS;
4014 }
4015 
4016 void qdf_initialize_module_param_from_ini(void)
4017 {
4018 	QDF_STATUS status;
4019 	char *path = QDF_WIFI_MODULE_PARAMS_FILE;
4020 
4021 	status = qdf_ini_parse(path, NULL, qdf_module_param_handler, NULL);
4022 	if (QDF_IS_STATUS_ERROR(status)) {
4023 		QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
4024 				"Failed to parse *.ini file @ %s; status:%d",
4025 				path, status);
4026 		return;
4027 	}
4028 }
4029 #endif
4030 
4031 QDF_STATUS qdf_print_set_category_verbose(unsigned int idx,
4032 						QDF_MODULE_ID category,
4033 						QDF_TRACE_LEVEL verbose,
4034 						bool is_set)
4035 {
4036 	/* Check if index passed is valid */
4037 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4038 		pr_err("%s: Invalid index - %d\n", __func__, idx);
4039 		return QDF_STATUS_E_FAILURE;
4040 	}
4041 
4042 	/* Check if print control object is in use */
4043 	if (!print_ctrl_obj[idx].in_use) {
4044 		pr_err("%s: Invalid print control object\n", __func__);
4045 		return QDF_STATUS_E_FAILURE;
4046 	}
4047 
4048 	/* Check if category passed is valid */
4049 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
4050 		pr_err("%s: Invalid category: %d\n", __func__, category);
4051 		return QDF_STATUS_E_FAILURE;
4052 	}
4053 
4054 	/* Check if verbose mask is valid */
4055 	if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
4056 		pr_err("%s: Invalid verbose level %d\n", __func__, verbose);
4057 		return QDF_STATUS_E_FAILURE;
4058 	}
4059 
4060 	if (verbose == QDF_TRACE_LEVEL_ALL) {
4061 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
4062 				0xFFFF;
4063 		return QDF_STATUS_SUCCESS;
4064 	}
4065 
4066 	if (verbose == QDF_TRACE_LEVEL_NONE) {
4067 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
4068 				QDF_TRACE_LEVEL_NONE;
4069 		return QDF_STATUS_SUCCESS;
4070 	}
4071 
4072 	if (!is_set) {
4073 		if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask
4074 		    & QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
4075 			print_ctrl_obj[idx].cat_info[category]
4076 				.category_verbose_mask &=
4077 				~QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
4078 		}
4079 	} else {
4080 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask |=
4081 				QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
4082 	}
4083 
4084 	pr_debug("%s: Print control object %d, Category %d, Verbose level %d\n",
4085 		__func__,
4086 		idx,
4087 		category,
4088 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask);
4089 
4090 	return QDF_STATUS_SUCCESS;
4091 }
4092 qdf_export_symbol(qdf_print_set_category_verbose);
4093 
4094 void qdf_log_dump_at_kernel_level(bool enable)
4095 {
4096 	if (qdf_log_dump_at_kernel_enable == enable) {
4097 		QDF_TRACE_INFO(QDF_MODULE_ID_QDF,
4098 			       "qdf_log_dump_at_kernel_enable is already %d\n",
4099 			       enable);
4100 	}
4101 	qdf_log_dump_at_kernel_enable = enable;
4102 }
4103 
4104 qdf_export_symbol(qdf_log_dump_at_kernel_level);
4105 
4106 QDF_TRACE_LEVEL qdf_print_get_category_verbose(unsigned int idx,
4107 					       QDF_MODULE_ID category)
4108 {
4109 	/* Check if index passed is valid */
4110 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4111 		pr_info("%s: Invalid index - %d\n", __func__, idx);
4112 		return false;
4113 	}
4114 
4115 	/* Check if print control object is in use */
4116 	if (!print_ctrl_obj[idx].in_use) {
4117 		pr_info("%s: Invalid print control object\n", __func__);
4118 		return false;
4119 	}
4120 
4121 	/* Check if category passed is valid */
4122 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
4123 		pr_info("%s: Invalid category: %d\n", __func__, category);
4124 		return false;
4125 	}
4126 
4127 	return print_ctrl_obj[idx].cat_info[category].category_verbose_mask;
4128 }
4129 
4130 qdf_export_symbol(qdf_print_get_category_verbose);
4131 
4132 bool qdf_print_is_category_enabled(unsigned int idx, QDF_MODULE_ID category)
4133 {
4134 	QDF_TRACE_LEVEL verbose_mask;
4135 
4136 	verbose_mask = qdf_print_get_category_verbose(idx, category);
4137 
4138 	if (verbose_mask == QDF_TRACE_LEVEL_NONE)
4139 		return false;
4140 	else
4141 		return true;
4142 }
4143 
4144 qdf_export_symbol(qdf_print_is_category_enabled);
4145 
4146 bool qdf_print_is_verbose_enabled(unsigned int idx, QDF_MODULE_ID category,
4147 				  QDF_TRACE_LEVEL verbose)
4148 {
4149 	bool verbose_enabled = false;
4150 
4151 	/* Check if index passed is valid */
4152 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4153 		pr_info("%s: Invalid index - %d\n", __func__, idx);
4154 		return verbose_enabled;
4155 	}
4156 
4157 	/* Check if print control object is in use */
4158 	if (!print_ctrl_obj[idx].in_use) {
4159 		pr_info("%s: Invalid print control object\n", __func__);
4160 		return verbose_enabled;
4161 	}
4162 
4163 	/* Check if category passed is valid */
4164 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
4165 		pr_info("%s: Invalid category: %d\n", __func__, category);
4166 		return verbose_enabled;
4167 	}
4168 
4169 	if ((verbose == QDF_TRACE_LEVEL_NONE) ||
4170 	    (verbose >= QDF_TRACE_LEVEL_MAX)) {
4171 		verbose_enabled = false;
4172 	} else if (verbose == QDF_TRACE_LEVEL_ALL) {
4173 		if (print_ctrl_obj[idx].cat_info[category]
4174 					.category_verbose_mask == 0xFFFF)
4175 			verbose_enabled = true;
4176 	} else {
4177 		verbose_enabled =
4178 		(print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
4179 		 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) ? true : false;
4180 	}
4181 
4182 	return verbose_enabled;
4183 }
4184 qdf_export_symbol(qdf_print_is_verbose_enabled);
4185 
4186 #ifdef DBG_LVL_MAC_FILTERING
4187 
4188 QDF_STATUS qdf_print_set_node_flag(unsigned int idx, uint8_t enable)
4189 {
4190 	/* Check if index passed is valid */
4191 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4192 		pr_info("%s: Invalid index - %d\n", __func__, idx);
4193 		return QDF_STATUS_E_FAILURE;
4194 	}
4195 
4196 	/* Check if print control object is in use */
4197 	if (!print_ctrl_obj[idx].in_use) {
4198 		pr_info("%s: Invalid print control object\n", __func__);
4199 		return QDF_STATUS_E_FAILURE;
4200 	}
4201 
4202 	if (enable > 1) {
4203 		pr_info("%s: Incorrect input: Use 1 or 0 to enable or disable\n",
4204 			__func__);
4205 		return QDF_STATUS_E_FAILURE;
4206 	}
4207 
4208 	print_ctrl_obj[idx].dbglvlmac_on = enable;
4209 	pr_info("%s: DbgLVLmac feature %s\n",
4210 		__func__,
4211 		((enable) ? "enabled" : "disabled"));
4212 
4213 	return QDF_STATUS_SUCCESS;
4214 }
4215 qdf_export_symbol(qdf_print_set_node_flag);
4216 
4217 bool qdf_print_get_node_flag(unsigned int idx)
4218 {
4219 	bool node_flag = false;
4220 
4221 	/* Check if index passed is valid */
4222 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4223 		pr_info("%s: Invalid index - %d\n", __func__, idx);
4224 		return node_flag;
4225 	}
4226 
4227 	/* Check if print control object is in use */
4228 	if (!print_ctrl_obj[idx].in_use) {
4229 		pr_info("%s: Invalid print control object\n", __func__);
4230 		return node_flag;
4231 	}
4232 
4233 	if (print_ctrl_obj[idx].dbglvlmac_on)
4234 		node_flag = true;
4235 
4236 	return node_flag;
4237 }
4238 qdf_export_symbol(qdf_print_get_node_flag);
4239 
4240 void qdf_print_clean_node_flag(unsigned int idx)
4241 {
4242 	/* Disable dbglvlmac_on during cleanup */
4243 	print_ctrl_obj[idx].dbglvlmac_on = 0;
4244 }
4245 
4246 #else
4247 
4248 void qdf_print_clean_node_flag(unsigned int idx)
4249 {
4250 	/* No operation in case of no support for DBG_LVL_MAC_FILTERING */
4251 	return;
4252 }
4253 #endif
4254 
4255 void QDF_PRINT_INFO(unsigned int idx, QDF_MODULE_ID module,
4256 		    QDF_TRACE_LEVEL level,
4257 		    char *str_format, ...)
4258 {
4259 	va_list args;
4260 
4261 	/* Generic wrapper API will compile qdf_vprint in order to
4262 	 * log the message. Once QDF converged debug framework is in
4263 	 * place, this will be changed to adapt to the framework, compiling
4264 	 * call to converged tracing API
4265 	 */
4266 	va_start(args, str_format);
4267 	qdf_vprint(str_format, args);
4268 	va_end(args);
4269 }
4270 qdf_export_symbol(QDF_PRINT_INFO);
4271 
4272 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
4273 void qdf_logging_init(void)
4274 {
4275 	wlan_logging_sock_init_svc();
4276 	nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY);
4277 	wlan_logging_notifier_init(qdf_log_dump_at_kernel_enable);
4278 	wlan_logging_set_flush_timer(qdf_log_flush_timer_period);
4279 }
4280 
4281 void qdf_logging_exit(void)
4282 {
4283 	wlan_logging_notifier_deinit(qdf_log_dump_at_kernel_enable);
4284 	nl_srv_exit();
4285 	wlan_logging_sock_deinit_svc();
4286 }
4287 
4288 int qdf_logging_set_flush_timer(uint32_t milliseconds)
4289 {
4290 	if (wlan_logging_set_flush_timer(milliseconds) == 0)
4291 		return QDF_STATUS_SUCCESS;
4292 	else
4293 		return QDF_STATUS_E_FAILURE;
4294 }
4295 
4296 void qdf_logging_flush_logs(void)
4297 {
4298 	wlan_flush_host_logs_for_fatal();
4299 }
4300 
4301 #else
4302 void qdf_logging_init(void)
4303 {
4304 	nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY);
4305 }
4306 
4307 void qdf_logging_exit(void)
4308 {
4309 	nl_srv_exit();
4310 }
4311 
4312 int qdf_logging_set_flush_timer(uint32_t milliseconds)
4313 {
4314 	return QDF_STATUS_E_FAILURE;
4315 }
4316 
4317 void qdf_logging_flush_logs(void)
4318 {
4319 }
4320 #endif
4321 
4322 qdf_export_symbol(qdf_logging_set_flush_timer);
4323 qdf_export_symbol(qdf_logging_flush_logs);
4324 
4325 #ifdef CONFIG_KALLSYMS
4326 inline int qdf_sprint_symbol(char *buffer, void *addr)
4327 {
4328 	return sprint_symbol(buffer, (unsigned long)addr);
4329 }
4330 #else
4331 int qdf_sprint_symbol(char *buffer, void *addr)
4332 {
4333 	if (!buffer)
4334 		return 0;
4335 
4336 	buffer[0] = '\0';
4337 	return 1;
4338 }
4339 #endif
4340 qdf_export_symbol(qdf_sprint_symbol);
4341 
4342 void qdf_set_pidx(int pidx)
4343 {
4344 	qdf_pidx = pidx;
4345 }
4346 qdf_export_symbol(qdf_set_pidx);
4347 
4348 int qdf_get_pidx(void)
4349 {
4350 	return qdf_pidx;
4351 }
4352 qdf_export_symbol(qdf_get_pidx);
4353 
4354 #ifdef PANIC_ON_BUG
4355 #ifdef CONFIG_SLUB_DEBUG
4356 void __qdf_bug(void)
4357 {
4358 	BUG();
4359 }
4360 qdf_export_symbol(__qdf_bug);
4361 #endif /* CONFIG_SLUB_DEBUG */
4362 #endif /* PANIC_ON_BUG */
4363 
4364 #ifdef WLAN_QCOM_VA_MINIDUMP
4365 static bool qdf_va_md_initialized;
4366 static qdf_list_t qdf_va_md_list;
4367 static qdf_spinlock_t qdf_va_md_list_lock;
4368 #define QDF_MINIDUMP_LIST_SIZE 128
4369 
4370 struct qdf_va_md_entry {
4371 	qdf_list_node_t node;
4372 	struct va_md_entry data;
4373 };
4374 
4375 static int qdf_va_md_notif_handler(struct notifier_block *this,
4376 				   unsigned long event, void *ptr)
4377 {
4378 	struct qdf_va_md_entry *entry;
4379 	struct qdf_va_md_entry *next;
4380 
4381 	qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4382 	qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) {
4383 		qcom_va_md_add_region(&entry->data);
4384 	}
4385 
4386 	qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4387 	return NOTIFY_OK;
4388 }
4389 
4390 static struct notifier_block qdf_va_md_notif_blk = {
4391 	.notifier_call = qdf_va_md_notif_handler,
4392 	.priority = INT_MAX,
4393 };
4394 
4395 void __qdf_minidump_init(void)
4396 {
4397 	int ret;
4398 
4399 	if (qdf_va_md_initialized)
4400 		return;
4401 
4402 	qdf_spinlock_create(&qdf_va_md_list_lock);
4403 	qdf_list_create(&qdf_va_md_list, QDF_MINIDUMP_LIST_SIZE);
4404 	ret = qcom_va_md_register(qdf_trace_wlan_modname(),
4405 				  &qdf_va_md_notif_blk);
4406 	qdf_va_md_initialized = !ret;
4407 }
4408 
4409 qdf_export_symbol(__qdf_minidump_init);
4410 
4411 void __qdf_minidump_deinit(void)
4412 {
4413 	struct qdf_va_md_entry *entry;
4414 	struct qdf_va_md_entry *next;
4415 
4416 	if (!qdf_va_md_initialized)
4417 		return;
4418 
4419 	qdf_va_md_initialized = false;
4420 	qcom_va_md_unregister(qdf_trace_wlan_modname(),
4421 			      &qdf_va_md_notif_blk);
4422 	qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4423 	qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) {
4424 		qdf_list_remove_node(&qdf_va_md_list, &entry->node);
4425 		qdf_mem_free(entry);
4426 	}
4427 
4428 	qdf_list_destroy(&qdf_va_md_list);
4429 	qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4430 	qdf_spinlock_destroy(&qdf_va_md_list_lock);
4431 }
4432 
4433 qdf_export_symbol(__qdf_minidump_deinit);
4434 
4435 void __qdf_minidump_log(void *start_addr, size_t size, const char *name)
4436 {
4437 	struct qdf_va_md_entry *entry;
4438 	QDF_STATUS status;
4439 
4440 	if (!qdf_va_md_initialized)
4441 		return;
4442 
4443 	entry = qdf_mem_malloc(sizeof(*entry));
4444 	if (!entry) {
4445 		qdf_err("malloc failed for %s: %pK, %zu",
4446 			name, start_addr, size);
4447 		return;
4448 	}
4449 
4450 	qdf_str_lcopy(entry->data.owner, name, sizeof(entry->data.owner));
4451 	entry->data.vaddr = (unsigned long)start_addr;
4452 	entry->data.size = size;
4453 
4454 	qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4455 	status = qdf_list_insert_front(&qdf_va_md_list, &entry->node);
4456 	qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4457 	if (QDF_IS_STATUS_ERROR(status)) {
4458 		qdf_err("Failed to insert qdf va md entry, status %d", status);
4459 		qdf_mem_free(entry);
4460 	}
4461 }
4462 
4463 qdf_export_symbol(__qdf_minidump_log);
4464 
4465 void __qdf_minidump_remove(void *addr, size_t size, const char *name)
4466 {
4467 	struct qdf_va_md_entry *entry;
4468 	struct qdf_va_md_entry *next;
4469 
4470 	if (!qdf_va_md_initialized)
4471 		return;
4472 
4473 	qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4474 	qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) {
4475 		if (entry->data.vaddr == (unsigned long)addr &&
4476 		    entry->data.size == size &&
4477 		    !qdf_str_cmp(entry->data.owner, name)) {
4478 			qdf_list_remove_node(&qdf_va_md_list, &entry->node);
4479 			qdf_mem_free(entry);
4480 			break;
4481 		}
4482 	}
4483 
4484 	qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4485 }
4486 
4487 qdf_export_symbol(__qdf_minidump_remove);
4488 #endif
4489