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