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