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