xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/qdf_trace.c (revision c8039e3fa439b838b525783fb76d6bdc0259257c) !
1 /*
2  * Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
3  *
4  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5  *
6  *
7  * Permission to use, copy, modify, and/or distribute this software for
8  * any purpose with or without fee is hereby granted, provided that the
9  * above copyright notice and this permission notice appear in all
10  * copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19  * PERFORMANCE OF THIS SOFTWARE.
20  */
21 
22 /*
23  * This file was originally distributed by Qualcomm Atheros, Inc.
24  * under proprietary terms before Copyright ownership was assigned
25  * to the Linux Foundation.
26  */
27 
28 /**
29  *  DOC:  qdf_trace
30  *  QCA driver framework (QDF) trace APIs
31  *  Trace, logging, and debugging definitions and APIs
32  */
33 
34 /* Include Files */
35 #include <qdf_trace.h>
36 #include <linux/export.h>
37 
38 /* macro to map qdf trace levels into the bitmask */
39 #define QDF_TRACE_LEVEL_TO_MODULE_BITMASK(_level) ((1 << (_level)))
40 
41 #include <wlan_logging_sock_svc.h>
42 static int qdf_pidx = -1;
43 #ifdef CONFIG_MCL
44 
45 #include "qdf_time.h"
46 #include "qdf_mc_timer.h"
47 
48 /* Global qdf print id */
49 
50 /* Preprocessor definitions and constants */
51 
52 enum qdf_timestamp_unit qdf_log_timestamp_type = QDF_LOG_TIMESTAMP_UNIT;
53 
54 /**
55  * typedef struct module_trace_info - Trace level for a module, as a bitmask.
56  * The bits in this mask are ordered by QDF_TRACE_LEVEL.  For example,
57  * each bit represents one of the bits in QDF_TRACE_LEVEL that may be turned
58  * on to have traces at that level logged, i.e. if QDF_TRACE_LEVEL_ERROR is
59  * == 2, then if bit 2 (low order) is turned ON, then ERROR traces will be
60  * printed to the trace log. Note that all bits turned OFF means no traces
61  * @module_trace_level: trace level
62  * @module_name_str: 3 character string name for the module
63  */
64 typedef struct {
65 	uint16_t module_trace_level;
66 	unsigned char module_name_str[4];
67 } module_trace_info;
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 /* Static and Global variables */
95 static spinlock_t ltrace_lock;
96 
97 static qdf_trace_record_t g_qdf_trace_tbl[MAX_QDF_TRACE_RECORDS];
98 /* global qdf trace data */
99 static t_qdf_trace_data g_qdf_trace_data;
100 /*
101  * all the call back functions for dumping MTRACE messages from ring buffer
102  * are stored in qdf_trace_cb_table,these callbacks are initialized during init
103  * only so, we will make a copy of these call back functions and maintain in to
104  * qdf_trace_restore_cb_table. Incase if we make modifications to
105  * qdf_trace_cb_table, we can certainly retrieve all the call back functions
106  * back from Restore Table
107  */
108 static tp_qdf_trace_cb qdf_trace_cb_table[QDF_MODULE_ID_MAX];
109 static tp_qdf_trace_cb qdf_trace_restore_cb_table[QDF_MODULE_ID_MAX];
110 static tp_qdf_state_info_cb qdf_state_info_table[QDF_MODULE_ID_MAX];
111 
112 #ifdef FEATURE_DP_TRACE
113 /* Static and Global variables */
114 static spinlock_t l_dp_trace_lock;
115 
116 static struct qdf_dp_trace_record_s
117 			g_qdf_dp_trace_tbl[MAX_QDF_DP_TRACE_RECORDS];
118 
119 /*
120  * all the options to configure/control DP trace are
121  * defined in this structure
122  */
123 static struct s_qdf_dp_trace_data g_qdf_dp_trace_data;
124 /*
125  * all the call back functions for dumping DPTRACE messages from ring buffer
126  * are stored in qdf_dp_trace_cb_table, callbacks are initialized during init
127  */
128 static tp_qdf_dp_trace_cb qdf_dp_trace_cb_table[QDF_DP_TRACE_MAX+1];
129 #endif
130 
131 void qdf_set_pidx(int pidx)
132 {
133 	qdf_pidx = pidx;
134 }
135 EXPORT_SYMBOL(qdf_set_pidx);
136 
137 int qdf_get_pidx(void)
138 {
139 	return qdf_pidx;
140 }
141 EXPORT_SYMBOL(qdf_get_pidx);
142 
143 /**
144  * qdf_trace_set_level() - Set the trace level for a particular module
145  * @module: Module id
146  * @level : trace level
147  *
148  * Trace level is a member of the QDF_TRACE_LEVEL enumeration indicating
149  * the severity of the condition causing the trace message to be issued.
150  * More severe conditions are more likely to be logged.
151  *
152  * This is an external API that allows trace levels to be set for each module.
153  *
154  * Return:  None
155  */
156 void qdf_trace_set_level(QDF_MODULE_ID module, QDF_TRACE_LEVEL level)
157 {
158 	/* make sure the caller is passing in a valid LEVEL */
159 	if (level >= QDF_TRACE_LEVEL_MAX) {
160 		pr_err("%s: Invalid trace level %d passed in!\n", __func__,
161 		       level);
162 		return;
163 	}
164 
165 	/* Treat 'none' differently.  NONE means we have to run off all
166 	 * the bits in the bit mask so none of the traces appear. Anything
167 	 * other than 'none' means we need to turn ON a bit in the bitmask
168 	 */
169 	if (QDF_TRACE_LEVEL_NONE == level)
170 		g_qdf_trace_info[module].module_trace_level =
171 			QDF_TRACE_LEVEL_NONE;
172 	else
173 		/* set the desired bit in the bit mask for the module trace
174 		 * level */
175 		g_qdf_trace_info[module].module_trace_level |=
176 			QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level);
177 }
178 EXPORT_SYMBOL(qdf_trace_set_level);
179 
180 /**
181  * qdf_trace_set_module_trace_level() - Set module trace level
182  * @module: Module id
183  * @level: Trace level for a module, as a bitmask as per 'module_trace_info'
184  *
185  * Sets the module trace level where the trace level is given as a bit mask
186  *
187  * Return: None
188  */
189 void qdf_trace_set_module_trace_level(QDF_MODULE_ID module, uint32_t level)
190 {
191 	if (module < 0 || module >= QDF_MODULE_ID_MAX) {
192 		pr_err("%s: Invalid module id %d passed\n", __func__, module);
193 		return;
194 	}
195 	g_qdf_trace_info[module].module_trace_level = level;
196 }
197 EXPORT_SYMBOL(qdf_trace_set_module_trace_level);
198 
199 /**
200  * qdf_trace_set_value() - Set module trace value
201  * @module: Module id
202  * @level: Trace level for a module, as a bitmask as per 'module_trace_info'
203  * @on: set/clear the desired bit in the bit mask
204  *
205  * Return: None
206  */
207 void qdf_trace_set_value(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
208 			 uint8_t on)
209 {
210 	/* make sure the caller is passing in a valid LEVEL */
211 	if (level < 0 || level >= QDF_TRACE_LEVEL_MAX) {
212 		pr_err("%s: Invalid trace level %d passed in!\n", __func__,
213 		       level);
214 		return;
215 	}
216 
217 	/* make sure the caller is passing in a valid module */
218 	if (module < 0 || module >= QDF_MODULE_ID_MAX) {
219 		pr_err("%s: Invalid module id %d passed in!\n", __func__,
220 		       module);
221 		return;
222 	}
223 
224 	/* Treat 'none' differently.  NONE means we have to turn off all
225 	   the bits in the bit mask so none of the traces appear */
226 	if (QDF_TRACE_LEVEL_NONE == level) {
227 		g_qdf_trace_info[module].module_trace_level =
228 			QDF_TRACE_LEVEL_NONE;
229 	}
230 	/* Treat 'All' differently.  All means we have to turn on all
231 	   the bits in the bit mask so all of the traces appear */
232 	else if (QDF_TRACE_LEVEL_ALL == level) {
233 		g_qdf_trace_info[module].module_trace_level = 0xFFFF;
234 	} else {
235 		if (on)
236 			/* set the desired bit in the bit mask for the module
237 			   trace level */
238 			g_qdf_trace_info[module].module_trace_level |=
239 				QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level);
240 		else
241 			/* clear the desired bit in the bit mask for the module
242 			   trace level */
243 			g_qdf_trace_info[module].module_trace_level &=
244 				~(QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level));
245 	}
246 }
247 EXPORT_SYMBOL(qdf_trace_set_value);
248 
249 /**
250  * qdf_trace_get_level() - get the trace level
251  * @module: module Id
252  * @level: trace level
253  *
254  * This is an external API that returns a bool value to signify if a
255  * particular trace level is set for the specified module.
256  * A member of the QDF_TRACE_LEVEL enumeration indicating the severity
257  * of the condition causing the trace message to be issued.
258  *
259  * Note that individual trace levels are the only valid values
260  * for this API.  QDF_TRACE_LEVEL_NONE and QDF_TRACE_LEVEL_ALL
261  * are not valid input and will return false
262  *
263  * Return:
264  * false - the specified trace level for the specified module is OFF
265  * true - the specified trace level for the specified module is ON
266  */
267 bool qdf_trace_get_level(QDF_MODULE_ID module, QDF_TRACE_LEVEL level)
268 {
269 	bool trace_on = false;
270 
271 	if ((QDF_TRACE_LEVEL_NONE == level) ||
272 	    (QDF_TRACE_LEVEL_ALL == level) || (level >= QDF_TRACE_LEVEL_MAX)) {
273 		trace_on = false;
274 	} else {
275 		trace_on = (level & g_qdf_trace_info[module].module_trace_level)
276 			  ? true : false;
277 	}
278 
279 	return trace_on;
280 }
281 EXPORT_SYMBOL(qdf_trace_get_level);
282 
283 /**
284  * qdf_snprintf() - wrapper function to snprintf
285  * @str_buffer: string Buffer
286  * @size: defines the size of the data record
287  * @str_format: Format string in which the message to be logged. This format
288  * string contains printf-like replacement parameters, which follow
289  * this parameter in the variable argument list.
290  *
291  * Return: None
292  */
293 void qdf_snprintf(char *str_buffer, unsigned int size, char *str_format, ...)
294 {
295 	va_list val;
296 
297 	va_start(val, str_format);
298 	snprintf(str_buffer, size, str_format, val);
299 	va_end(val);
300 }
301 EXPORT_SYMBOL(qdf_snprintf);
302 
303 #ifdef QDF_ENABLE_TRACING
304 
305 /**
306  * qdf_trace_msg() - externally called trace function
307  * @module: Module identifier a member of the QDF_MODULE_ID
308  * enumeration that identifies the module issuing the trace message.
309  * @level: Trace level a member of the QDF_TRACE_LEVEL enumeration
310  * indicating the severity of the condition causing the trace message
311  * to be issued. More severe conditions are more likely to be logged.
312  * @str_format: Format string in which the message to be logged. This format
313  * string contains printf-like replacement parameters, which follow
314  * this parameter in the variable argument list.
315  *
316  * Checks the level of severity and accordingly prints the trace messages
317  *
318  * Return: None
319  */
320 void qdf_trace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
321 		   char *str_format, ...)
322 {
323 	va_list val;
324 
325 	va_start(val, str_format);
326 	qdf_trace_msg_cmn(qdf_pidx, module, level, str_format, val);
327 	va_end(val);
328 }
329 EXPORT_SYMBOL(qdf_trace_msg);
330 
331 /**
332  * qdf_trace_display() - Display trace
333  *
334  * Return:  None
335  */
336 void qdf_trace_display(void)
337 {
338 	QDF_MODULE_ID module_id;
339 
340 	pr_err
341 		("     1)FATAL  2)ERROR  3)WARN  4)INFO  5)INFO_H  6)INFO_M  7)INFO_L 8)DEBUG\n");
342 	for (module_id = 0; module_id < QDF_MODULE_ID_MAX; ++module_id) {
343 		pr_err
344 			("%2d)%s    %s        %s       %s       %s        %s         %s         %s        %s\n",
345 			(int)module_id, g_qdf_trace_info[module_id].module_name_str,
346 			(g_qdf_trace_info[module_id].
347 			 module_trace_level & (1 << QDF_TRACE_LEVEL_FATAL)) ? "X" :
348 			" ",
349 			(g_qdf_trace_info[module_id].
350 			 module_trace_level & (1 << QDF_TRACE_LEVEL_ERROR)) ? "X" :
351 			" ",
352 			(g_qdf_trace_info[module_id].
353 			 module_trace_level & (1 << QDF_TRACE_LEVEL_WARN)) ? "X" :
354 			" ",
355 			(g_qdf_trace_info[module_id].
356 			 module_trace_level & (1 << QDF_TRACE_LEVEL_INFO)) ? "X" :
357 			" ",
358 			(g_qdf_trace_info[module_id].
359 			 module_trace_level & (1 << QDF_TRACE_LEVEL_INFO_HIGH)) ? "X"
360 			: " ",
361 			(g_qdf_trace_info[module_id].
362 			 module_trace_level & (1 << QDF_TRACE_LEVEL_INFO_MED)) ? "X"
363 			: " ",
364 			(g_qdf_trace_info[module_id].
365 			 module_trace_level & (1 << QDF_TRACE_LEVEL_INFO_LOW)) ? "X"
366 			: " ",
367 			(g_qdf_trace_info[module_id].
368 			 module_trace_level & (1 << QDF_TRACE_LEVEL_DEBUG)) ? "X" :
369 			" ");
370 	}
371 }
372 EXPORT_SYMBOL(qdf_trace_display);
373 
374 #define ROW_SIZE 16
375 /* Buffer size = data bytes(2 hex chars plus space) + NULL */
376 #define BUFFER_SIZE ((ROW_SIZE * 3) + 1)
377 
378 /**
379  * qdf_trace_hex_dump() - externally called hex dump function
380  * @module: Module identifier a member of the QDF_MODULE_ID enumeration that
381  * identifies the module issuing the trace message.
382  * @level: Trace level a member of the QDF_TRACE_LEVEL enumeration indicating
383  * the severity of the condition causing the trace message to be
384  * issued. More severe conditions are more likely to be logged.
385  * @data: The base address of the buffer to be logged.
386  * @buf_len: The size of the buffer to be logged.
387  *
388  * Checks the level of severity and accordingly prints the trace messages
389  *
390  * Return:  None
391  */
392 void qdf_trace_hex_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
393 			void *data, int buf_len)
394 {
395 	const u8 *ptr = data;
396 	int i, linelen, remaining = buf_len;
397 	unsigned char linebuf[BUFFER_SIZE];
398 
399 	if (!(g_qdf_trace_info[module].module_trace_level &
400 		QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level)))
401 		return;
402 
403 	for (i = 0; i < buf_len; i += ROW_SIZE) {
404 		linelen = min(remaining, ROW_SIZE);
405 		remaining -= ROW_SIZE;
406 
407 		hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1,
408 				linebuf, sizeof(linebuf), false);
409 
410 		qdf_trace_msg(module, level, "%.8x: %s", i, linebuf);
411 	}
412 }
413 EXPORT_SYMBOL(qdf_trace_hex_dump);
414 
415 #endif
416 
417 /**
418  * qdf_trace_enable() - Enable MTRACE for specific modules
419  * @bitmask_of_module_id: Bitmask according to enum of the modules.
420  *  32[dec] = 0010 0000 [bin] <enum of HDD is 5>
421  *  64[dec] = 0100 0000 [bin] <enum of SME is 6>
422  *  128[dec] = 1000 0000 [bin] <enum of PE is 7>
423  * @enable: can be true or false true implies enabling MTRACE false implies
424  *		disabling MTRACE.
425  *
426  * Enable MTRACE for specific modules whose bits are set in bitmask and enable
427  * is true. if enable is false it disables MTRACE for that module. set the
428  * bitmask according to enum value of the modules.
429  * This functions will be called when you issue ioctl as mentioned following
430  * [iwpriv wlan0 setdumplog <value> <enable>].
431  * <value> - Decimal number, i.e. 64 decimal value shows only SME module,
432  * 128 decimal value shows only PE module, 192 decimal value shows PE and SME.
433  *
434  * Return: None
435  */
436 void qdf_trace_enable(uint32_t bitmask_of_module_id, uint8_t enable)
437 {
438 	int i;
439 	if (bitmask_of_module_id) {
440 		for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
441 			if (((bitmask_of_module_id >> i) & 1)) {
442 				if (enable) {
443 					if (NULL !=
444 					    qdf_trace_restore_cb_table[i]) {
445 						qdf_trace_cb_table[i] =
446 						qdf_trace_restore_cb_table[i];
447 					}
448 				} else {
449 					qdf_trace_restore_cb_table[i] =
450 						qdf_trace_cb_table[i];
451 					qdf_trace_cb_table[i] = NULL;
452 				}
453 			}
454 		}
455 	} else {
456 		if (enable) {
457 			for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
458 				if (NULL != qdf_trace_restore_cb_table[i]) {
459 					qdf_trace_cb_table[i] =
460 						qdf_trace_restore_cb_table[i];
461 				}
462 			}
463 		} else {
464 			for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
465 				qdf_trace_restore_cb_table[i] =
466 					qdf_trace_cb_table[i];
467 				qdf_trace_cb_table[i] = NULL;
468 			}
469 		}
470 	}
471 }
472 EXPORT_SYMBOL(qdf_trace_enable);
473 
474 /**
475  * qdf_trace_init() - initializes qdf trace structures and variables
476  *
477  * Called immediately after cds_preopen, so that we can start recording HDD
478  * events ASAP.
479  *
480  * Return: None
481  */
482 void qdf_trace_init(void)
483 {
484 	uint8_t i;
485 	g_qdf_trace_data.head = INVALID_QDF_TRACE_ADDR;
486 	g_qdf_trace_data.tail = INVALID_QDF_TRACE_ADDR;
487 	g_qdf_trace_data.num = 0;
488 	g_qdf_trace_data.enable = true;
489 	g_qdf_trace_data.dump_count = DEFAULT_QDF_TRACE_DUMP_COUNT;
490 	g_qdf_trace_data.num_since_last_dump = 0;
491 
492 	for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
493 		qdf_trace_cb_table[i] = NULL;
494 		qdf_trace_restore_cb_table[i] = NULL;
495 	}
496 }
497 EXPORT_SYMBOL(qdf_trace_init);
498 
499 /**
500  * qdf_trace() - puts the messages in to ring-buffer
501  * @module: Enum of module, basically module id.
502  * @param: Code to be recorded
503  * @session: Session ID of the log
504  * @data: Actual message contents
505  *
506  * This function will be called from each module who wants record the messages
507  * in circular queue. Before calling this functions make sure you have
508  * registered your module with qdf through qdf_trace_register function.
509  *
510  * Return: None
511  */
512 void qdf_trace(uint8_t module, uint8_t code, uint16_t session, uint32_t data)
513 {
514 	tp_qdf_trace_record rec = NULL;
515 	unsigned long flags;
516 	char time[18];
517 
518 	if (!g_qdf_trace_data.enable)
519 		return;
520 
521 	/* if module is not registered, don't record for that module */
522 	if (NULL == qdf_trace_cb_table[module])
523 		return;
524 
525 	qdf_get_time_of_the_day_in_hr_min_sec_usec(time, sizeof(time));
526 	/* Aquire the lock so that only one thread at a time can fill the ring
527 	 * buffer
528 	 */
529 	spin_lock_irqsave(&ltrace_lock, flags);
530 
531 	g_qdf_trace_data.num++;
532 
533 	if (g_qdf_trace_data.num > MAX_QDF_TRACE_RECORDS)
534 		g_qdf_trace_data.num = MAX_QDF_TRACE_RECORDS;
535 
536 	if (INVALID_QDF_TRACE_ADDR == g_qdf_trace_data.head) {
537 		/* first record */
538 		g_qdf_trace_data.head = 0;
539 		g_qdf_trace_data.tail = 0;
540 	} else {
541 		/* queue is not empty */
542 		uint32_t tail = g_qdf_trace_data.tail + 1;
543 
544 		if (MAX_QDF_TRACE_RECORDS == tail)
545 			tail = 0;
546 
547 		if (g_qdf_trace_data.head == tail) {
548 			/* full */
549 			if (MAX_QDF_TRACE_RECORDS == ++g_qdf_trace_data.head)
550 				g_qdf_trace_data.head = 0;
551 		}
552 		g_qdf_trace_data.tail = tail;
553 	}
554 
555 	rec = &g_qdf_trace_tbl[g_qdf_trace_data.tail];
556 	rec->code = code;
557 	rec->session = session;
558 	rec->data = data;
559 	rec->qtime = qdf_get_log_timestamp();
560 	scnprintf(rec->time, sizeof(rec->time), "%s", time);
561 	rec->module = module;
562 	rec->pid = (in_interrupt() ? 0 : current->pid);
563 	g_qdf_trace_data.num_since_last_dump++;
564 	spin_unlock_irqrestore(&ltrace_lock, flags);
565 }
566 EXPORT_SYMBOL(qdf_trace);
567 
568 /**
569  * qdf_trace_spin_lock_init() - initializes the lock variable before use
570  *
571  * This function will be called from cds_alloc_global_context, we will have lock
572  * available to use ASAP
573  *
574  * Return: None
575  */
576 QDF_STATUS qdf_trace_spin_lock_init(void)
577 {
578 	spin_lock_init(&ltrace_lock);
579 
580 	return QDF_STATUS_SUCCESS;
581 }
582 EXPORT_SYMBOL(qdf_trace_spin_lock_init);
583 
584 /**
585  * qdf_trace_register() - registers the call back functions
586  * @module_iD: enum value of module
587  * @qdf_trace_callback: call back functions to display the messages in
588  * particular format.
589  *
590  * Registers the call back functions to display the messages in particular
591  * format mentioned in these call back functions. This functions should be
592  * called by interested module in their init part as we will be ready to
593  * register as soon as modules are up.
594  *
595  * Return: None
596  */
597 void qdf_trace_register(QDF_MODULE_ID module_iD,
598 			tp_qdf_trace_cb qdf_trace_callback)
599 {
600 	qdf_trace_cb_table[module_iD] = qdf_trace_callback;
601 }
602 EXPORT_SYMBOL(qdf_trace_register);
603 
604 /**
605  * qdf_trace_dump_all() - Dump data from ring buffer via call back functions
606  * registered with QDF
607  * @p_mac: Context of particular module
608  * @code: Reason code
609  * @session: Session id of log
610  * @count: Number of lines to dump starting from tail to head
611  *
612  * This function will be called up on issueing ioctl call as mentioned following
613  * [iwpriv wlan0 dumplog 0 0 <n> <bitmask_of_module>]
614  *
615  * <n> - number lines to dump starting from tail to head.
616  *
617  * <bitmask_of_module> - if anybody wants to know how many messages were
618  * recorded for particular module/s mentioned by setbit in bitmask from last
619  * <n> messages. It is optional, if you don't provide then it will dump
620  * everything from buffer.
621  *
622  * Return: None
623  */
624 void qdf_trace_dump_all(void *p_mac, uint8_t code, uint8_t session,
625 			uint32_t count, uint32_t bitmask_of_module)
626 {
627 	qdf_trace_record_t p_record;
628 	int32_t i, tail;
629 
630 	if (!g_qdf_trace_data.enable) {
631 		QDF_TRACE(QDF_MODULE_ID_SYS,
632 			  QDF_TRACE_LEVEL_ERROR, "Tracing Disabled");
633 		return;
634 	}
635 
636 	QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_INFO,
637 		  "Total Records: %d, Head: %d, Tail: %d",
638 		  g_qdf_trace_data.num, g_qdf_trace_data.head,
639 		  g_qdf_trace_data.tail);
640 
641 	/* aquire the lock so that only one thread at a time can read
642 	 * the ring buffer
643 	 */
644 	spin_lock(&ltrace_lock);
645 
646 	if (g_qdf_trace_data.head != INVALID_QDF_TRACE_ADDR) {
647 		i = g_qdf_trace_data.head;
648 		tail = g_qdf_trace_data.tail;
649 
650 		if (count) {
651 			if (count > g_qdf_trace_data.num)
652 				count = g_qdf_trace_data.num;
653 			if (tail >= (count - 1))
654 				i = tail - count + 1;
655 			else if (count != MAX_QDF_TRACE_RECORDS)
656 				i = MAX_QDF_TRACE_RECORDS - ((count - 1) -
657 							     tail);
658 		}
659 
660 		p_record = g_qdf_trace_tbl[i];
661 		/* right now we are not using num_since_last_dump member but
662 		 * in future we might re-visit and use this member to track
663 		 * how many latest messages got added while we were dumping
664 		 * from ring buffer
665 		 */
666 		g_qdf_trace_data.num_since_last_dump = 0;
667 		spin_unlock(&ltrace_lock);
668 		for (;; ) {
669 			if ((code == 0 || (code == p_record.code)) &&
670 			    (qdf_trace_cb_table[p_record.module] != NULL)) {
671 				if (0 == bitmask_of_module) {
672 					qdf_trace_cb_table[p_record.
673 							   module] (p_mac,
674 								    &p_record,
675 								    (uint16_t)
676 								    i);
677 				} else {
678 					if (bitmask_of_module &
679 					    (1 << p_record.module)) {
680 						qdf_trace_cb_table[p_record.
681 								   module]
682 							(p_mac, &p_record,
683 							(uint16_t) i);
684 					}
685 				}
686 			}
687 
688 			if (i == tail)
689 				break;
690 			i += 1;
691 
692 			spin_lock(&ltrace_lock);
693 			if (MAX_QDF_TRACE_RECORDS == i) {
694 				i = 0;
695 				p_record = g_qdf_trace_tbl[0];
696 			} else {
697 				p_record = g_qdf_trace_tbl[i];
698 			}
699 			spin_unlock(&ltrace_lock);
700 		}
701 	} else {
702 		spin_unlock(&ltrace_lock);
703 	}
704 }
705 EXPORT_SYMBOL(qdf_trace_dump_all);
706 
707 /**
708  * qdf_register_debugcb_init() - initializes debug callbacks
709  * to NULL
710  *
711  * Return: None
712  */
713 void qdf_register_debugcb_init(void)
714 {
715 	uint8_t i;
716 
717 	for (i = 0; i < QDF_MODULE_ID_MAX; i++)
718 		qdf_state_info_table[i] = NULL;
719 }
720 EXPORT_SYMBOL(qdf_register_debugcb_init);
721 
722 /**
723  * qdf_register_debug_callback() - stores callback handlers to print
724  * state information
725  * @module_id: module id of layer
726  * @qdf_state_infocb: callback to be registered
727  *
728  * This function is used to store callback handlers to print
729  * state information
730  *
731  * Return: None
732  */
733 void qdf_register_debug_callback(QDF_MODULE_ID module_id,
734 					tp_qdf_state_info_cb qdf_state_infocb)
735 {
736 	qdf_state_info_table[module_id] = qdf_state_infocb;
737 }
738 EXPORT_SYMBOL(qdf_register_debug_callback);
739 
740 /**
741  * qdf_state_info_dump_all() - it invokes callback of layer which registered
742  * its callback to print its state information.
743  * @buf:  buffer pointer to be passed
744  * @size:  size of buffer to be filled
745  * @driver_dump_size: actual size of buffer used
746  *
747  * Return: QDF_STATUS_SUCCESS on success
748  */
749 QDF_STATUS qdf_state_info_dump_all(char *buf, uint16_t size,
750 			uint16_t *driver_dump_size)
751 {
752 	uint8_t module, ret = QDF_STATUS_SUCCESS;
753 	uint16_t buf_len = size;
754 	char *buf_ptr = buf;
755 
756 	for (module = 0; module < QDF_MODULE_ID_MAX; module++) {
757 		if (NULL != qdf_state_info_table[module]) {
758 			qdf_state_info_table[module](&buf_ptr, &buf_len);
759 			if (!buf_len) {
760 				ret = QDF_STATUS_E_NOMEM;
761 				break;
762 			}
763 		}
764 	}
765 
766 	*driver_dump_size = size - buf_len;
767 	return ret;
768 }
769 EXPORT_SYMBOL(qdf_state_info_dump_all);
770 
771 #ifdef FEATURE_DP_TRACE
772 static void qdf_dp_unused(struct qdf_dp_trace_record_s *record,
773 			  uint16_t index)
774 {
775 	qdf_print("%s: QDF_DP_TRACE_MAX event should not be generated",
776 		  __func__);
777 }
778 
779 /**
780  * qdf_dp_trace_init() - enables the DP trace
781  * Called during driver load and it enables DP trace
782  *
783  * Return: None
784  */
785 void qdf_dp_trace_init(void)
786 {
787 	uint8_t i;
788 
789 	qdf_dp_trace_spin_lock_init();
790 	g_qdf_dp_trace_data.head = INVALID_QDF_DP_TRACE_ADDR;
791 	g_qdf_dp_trace_data.tail = INVALID_QDF_DP_TRACE_ADDR;
792 	g_qdf_dp_trace_data.num = 0;
793 	g_qdf_dp_trace_data.proto_bitmap = QDF_NBUF_PKT_TRAC_TYPE_EAPOL |
794 					   QDF_NBUF_PKT_TRAC_TYPE_DHCP |
795 					   QDF_NBUF_PKT_TRAC_TYPE_MGMT_ACTION |
796 					   QDF_NBUF_PKT_TRAC_TYPE_ARP;
797 	g_qdf_dp_trace_data.no_of_record = 0;
798 	g_qdf_dp_trace_data.verbosity    = QDF_DP_TRACE_VERBOSITY_HIGH;
799 	g_qdf_dp_trace_data.enable = true;
800 	g_qdf_dp_trace_data.tx_count = 0;
801 	g_qdf_dp_trace_data.rx_count = 0;
802 	g_qdf_dp_trace_data.live_mode = 0;
803 
804 	for (i = 0; i < ARRAY_SIZE(qdf_dp_trace_cb_table); i++)
805 		qdf_dp_trace_cb_table[i] = qdf_dp_display_record;
806 
807 	qdf_dp_trace_cb_table[QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD] =
808 	qdf_dp_trace_cb_table[QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD] =
809 	qdf_dp_trace_cb_table[QDF_DP_TRACE_FREE_PACKET_PTR_RECORD] =
810 						qdf_dp_display_ptr_record;
811 	qdf_dp_trace_cb_table[QDF_DP_TRACE_EAPOL_PACKET_RECORD] =
812 	qdf_dp_trace_cb_table[QDF_DP_TRACE_DHCP_PACKET_RECORD] =
813 	qdf_dp_trace_cb_table[QDF_DP_TRACE_ARP_PACKET_RECORD] =
814 						qdf_dp_display_proto_pkt;
815 	qdf_dp_trace_cb_table[QDF_DP_TRACE_MGMT_PACKET_RECORD] =
816 					qdf_dp_display_mgmt_pkt;
817 	qdf_dp_trace_cb_table[QDF_DP_TRACE_EVENT_RECORD] =
818 					qdf_dp_display_event_record;
819 
820 	qdf_dp_trace_cb_table[QDF_DP_TRACE_MAX] = qdf_dp_unused;
821 }
822 EXPORT_SYMBOL(qdf_dp_trace_init);
823 
824 /**
825  * qdf_dp_trace_set_value() - Configure the value to control DP trace
826  * @proto_bitmap: defines the protocol to be tracked
827  * @no_of_records: defines the nth packet which is traced
828  * @verbosity: defines the verbosity level
829  *
830  * Return: None
831  */
832 void qdf_dp_trace_set_value(uint8_t proto_bitmap, uint8_t no_of_record,
833 			    uint8_t verbosity)
834 {
835 	g_qdf_dp_trace_data.proto_bitmap = proto_bitmap;
836 	g_qdf_dp_trace_data.no_of_record = no_of_record;
837 	g_qdf_dp_trace_data.verbosity    = verbosity;
838 	return;
839 }
840 EXPORT_SYMBOL(qdf_dp_trace_set_value);
841 
842 /**
843  * qdf_dp_trace_enable_track() - enable the tracing for netbuf
844  * @code: defines the event
845  *
846  * In High verbosity all codes are logged.
847  * For Med/Low and Default case code which has
848  * less value than corresponding verbosity codes
849  * are logged.
850  *
851  * Return: true or false depends on whether tracing enabled
852  */
853 static bool qdf_dp_trace_enable_track(enum QDF_DP_TRACE_ID code)
854 {
855 	switch (g_qdf_dp_trace_data.verbosity) {
856 	case QDF_DP_TRACE_VERBOSITY_HIGH:
857 		return true;
858 	case QDF_DP_TRACE_VERBOSITY_MEDIUM:
859 		if (code <= QDF_DP_TRACE_MED_VERBOSITY)
860 			return true;
861 		return false;
862 	case QDF_DP_TRACE_VERBOSITY_LOW:
863 		if (code <= QDF_DP_TRACE_LOW_VERBOSITY)
864 			return true;
865 		return false;
866 	case QDF_DP_TRACE_VERBOSITY_DEFAULT:
867 		if (code <= QDF_DP_TRACE_DEFAULT_VERBOSITY)
868 			return true;
869 		return false;
870 	default:
871 		return false;
872 	}
873 }
874 EXPORT_SYMBOL(qdf_dp_trace_enable_track);
875 
876 /**
877  * qdf_dp_get_proto_bitmap() - get dp trace proto bitmap
878  *
879  * Return: proto bitmap
880  */
881 uint8_t qdf_dp_get_proto_bitmap(void)
882 {
883 	if (g_qdf_dp_trace_data.enable)
884 		return g_qdf_dp_trace_data.proto_bitmap;
885 	else
886 		return 0;
887 }
888 
889 /**
890  * qdf_dp_trace_set_track() - Marks whether the packet needs to be traced
891  * @nbuf: defines the netbuf
892  * @dir: direction
893  *
894  * Return: None
895  */
896 void qdf_dp_trace_set_track(qdf_nbuf_t nbuf, enum qdf_proto_dir dir)
897 {
898 	uint32_t count = 0;
899 
900 	spin_lock_bh(&l_dp_trace_lock);
901 	if (QDF_TX == dir)
902 		count = ++g_qdf_dp_trace_data.tx_count;
903 	else if (QDF_RX == dir)
904 		count = ++g_qdf_dp_trace_data.rx_count;
905 
906 	if ((g_qdf_dp_trace_data.no_of_record != 0) &&
907 		(count % g_qdf_dp_trace_data.no_of_record == 0)) {
908 		if (QDF_TX == dir)
909 			QDF_NBUF_CB_TX_DP_TRACE(nbuf) = 1;
910 		else if (QDF_RX == dir)
911 			QDF_NBUF_CB_RX_DP_TRACE(nbuf) = 1;
912 	}
913 	spin_unlock_bh(&l_dp_trace_lock);
914 	return;
915 }
916 EXPORT_SYMBOL(qdf_dp_trace_set_track);
917 
918 #define DPTRACE_PRINT(args...) \
919 	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, ## args)
920 
921 /**
922  * dump_hex_trace() - Display the data in buffer
923  * @str:     string to prepend the hexdump with.
924  * @buf:     buffer which contains data to be displayed
925  * @buf_len: defines the size of the data to be displayed
926  *
927  * Return: None
928  */
929 static void dump_hex_trace(char *str, uint8_t *buf, uint8_t buf_len)
930 {
931 	unsigned char linebuf[BUFFER_SIZE];
932 	const u8 *ptr = buf;
933 	int i, linelen, remaining = buf_len;
934 
935 	/* Dump the bytes in the last line */
936 	for (i = 0; i < buf_len; i += ROW_SIZE) {
937 		linelen = min(remaining, ROW_SIZE);
938 		remaining -= ROW_SIZE;
939 
940 		hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1,
941 				linebuf, sizeof(linebuf), false);
942 
943 		DPTRACE_PRINT("DPT: %s: %s", str, linebuf);
944 	}
945 }
946 
947 /**
948  * qdf_dp_code_to_string() - convert dptrace code to string
949  * @code: dptrace code
950  *
951  * Return: string version of code
952  */
953 static
954 const char *qdf_dp_code_to_string(enum QDF_DP_TRACE_ID code)
955 {
956 	switch (code) {
957 	case QDF_DP_TRACE_DROP_PACKET_RECORD:
958 		return "DROP:";
959 	case QDF_DP_TRACE_EAPOL_PACKET_RECORD:
960 		return "EAPOL:";
961 	case QDF_DP_TRACE_DHCP_PACKET_RECORD:
962 		return "DHCP:";
963 	case QDF_DP_TRACE_ARP_PACKET_RECORD:
964 		return "ARP:";
965 	case QDF_DP_TRACE_MGMT_PACKET_RECORD:
966 		return "MGMT:";
967 	case QDF_DP_TRACE_EVENT_RECORD:
968 		return "EVENT:";
969 	case QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD:
970 		return "HDD: TX: PTR:";
971 	case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
972 		return "HDD: TX: DATA:";
973 	case QDF_DP_TRACE_CE_PACKET_PTR_RECORD:
974 		return "CE: TX: PTR:";
975 	case QDF_DP_TRACE_CE_FAST_PACKET_PTR_RECORD:
976 		return "CE: TX: FAST: PTR:";
977 	case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD:
978 		return "FREE: TX: PTR:";
979 	case QDF_DP_TRACE_RX_HTT_PACKET_PTR_RECORD:
980 		return "HTT: RX: PTR:";
981 	case QDF_DP_TRACE_RX_OFFLOAD_HTT_PACKET_PTR_RECORD:
982 		return "HTT: RX: OF: PTR:";
983 	case QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD:
984 		return "HDD: RX: PTR:";
985 	case QDF_DP_TRACE_HDD_RX_PACKET_RECORD:
986 		return "HDD: RX: DATA:";
987 	case QDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD:
988 		return "TXRX: TX: Q: PTR:";
989 	case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD:
990 		return "TXRX: TX: PTR:";
991 	case QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD:
992 		return "TXRX: TX: FAST: PTR:";
993 	case QDF_DP_TRACE_HTT_PACKET_PTR_RECORD:
994 		return "HTT: TX: PTR:";
995 	case QDF_DP_TRACE_HTC_PACKET_PTR_RECORD:
996 		return "HTC: TX: PTR:";
997 	case QDF_DP_TRACE_HIF_PACKET_PTR_RECORD:
998 		return "HIF: TX: PTR:";
999 	case QDF_DP_TRACE_RX_TXRX_PACKET_PTR_RECORD:
1000 		return "TXRX: RX: PTR:";
1001 	case QDF_DP_TRACE_HDD_TX_TIMEOUT:
1002 		return "HDD: STA: TO:";
1003 	case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
1004 		return "HDD: SAP: TO:";
1005 	default:
1006 		return "Invalid";
1007 	}
1008 }
1009 
1010 /**
1011  * qdf_dp_dir_to_str() - convert direction to string
1012  * @dir: direction
1013  *
1014  * Return: string version of direction
1015  */
1016 static const char *qdf_dp_dir_to_str(enum qdf_proto_dir dir)
1017 {
1018 	switch (dir) {
1019 	case QDF_TX:
1020 		return " --> ";
1021 	case QDF_RX:
1022 		return " <-- ";
1023 	default:
1024 		return "invalid";
1025 	}
1026 }
1027 
1028 /**
1029  * qdf_dp_type_to_str() - convert packet type to string
1030  * @type: type
1031  *
1032  * Return: string version of packet type
1033  */
1034 static const char *qdf_dp_type_to_str(enum qdf_proto_type type)
1035 {
1036 	switch (type) {
1037 	case QDF_PROTO_TYPE_DHCP:
1038 		return "DHCP";
1039 	case QDF_PROTO_TYPE_EAPOL:
1040 		return "EAPOL";
1041 	case QDF_PROTO_TYPE_ARP:
1042 		return "ARP";
1043 	case QDF_PROTO_TYPE_MGMT:
1044 		return "MGMT";
1045 	case QDF_PROTO_TYPE_EVENT:
1046 		return "EVENT";
1047 	default:
1048 		return "invalid";
1049 	}
1050 }
1051 
1052 /**
1053  * qdf_dp_subtype_to_str() - convert packet subtype to string
1054  * @type: type
1055  *
1056  * Return: string version of packet subtype
1057  */
1058 static const char *qdf_dp_subtype_to_str(enum qdf_proto_subtype subtype)
1059 {
1060 	switch (subtype) {
1061 	case QDF_PROTO_EAPOL_M1:
1062 		return "M1";
1063 	case QDF_PROTO_EAPOL_M2:
1064 		return "M2";
1065 	case QDF_PROTO_EAPOL_M3:
1066 		return "M3";
1067 	case QDF_PROTO_EAPOL_M4:
1068 		return "M4";
1069 	case QDF_PROTO_DHCP_DISCOVER:
1070 		return "DISCOVER";
1071 	case QDF_PROTO_DHCP_REQUEST:
1072 		return "REQUEST";
1073 	case QDF_PROTO_DHCP_OFFER:
1074 		return "OFFER";
1075 	case QDF_PROTO_DHCP_ACK:
1076 		return "ACK";
1077 	case QDF_PROTO_DHCP_NACK:
1078 		return "NACK";
1079 	case QDF_PROTO_DHCP_RELEASE:
1080 		return "RELEASE";
1081 	case QDF_PROTO_DHCP_INFORM:
1082 		return "INFORM";
1083 	case QDF_PROTO_DHCP_DECLINE:
1084 		return "DECLINE";
1085 	case QDF_PROTO_ARP_REQ:
1086 		return "REQUEST";
1087 	case QDF_PROTO_ARP_RES:
1088 		return "RESPONSE";
1089 	case QDF_PROTO_MGMT_ASSOC:
1090 		return "ASSOC";
1091 	case QDF_PROTO_MGMT_DISASSOC:
1092 		return "DISASSOC";
1093 	case QDF_PROTO_MGMT_AUTH:
1094 		return "AUTH";
1095 	case QDF_PROTO_MGMT_DEAUTH:
1096 		return "DEAUTH";
1097 	case QDF_ROAM_SYNCH:
1098 		return "ROAM SYNCH";
1099 	case QDF_ROAM_COMPLETE:
1100 		return "ROAM COMPLETE";
1101 	case QDF_ROAM_EVENTID:
1102 		return "ROAM EVENTID";
1103 	default:
1104 		return "invalid";
1105 	}
1106 }
1107 
1108 /**
1109  * qdf_dp_enable_check() - check if dptrace is enable or not
1110  * @nbuf: nbuf
1111  * @code: dptrace code
1112  *
1113  * Return: true/false
1114  */
1115 static bool qdf_dp_enable_check(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
1116 				enum qdf_proto_dir dir)
1117 {
1118 	/* Return when Dp trace is not enabled */
1119 	if (!g_qdf_dp_trace_data.enable)
1120 		return false;
1121 
1122 	if (qdf_dp_trace_enable_track(code) == false)
1123 		return false;
1124 
1125 	if ((nbuf) && ((QDF_NBUF_CB_TX_PACKET_TRACK(nbuf) !=
1126 		 QDF_NBUF_TX_PKT_DATA_TRACK) ||
1127 		 ((dir == QDF_TX) && (QDF_NBUF_CB_TX_DP_TRACE(nbuf) == 0)) ||
1128 		 ((dir == QDF_RX) && (QDF_NBUF_CB_RX_DP_TRACE(nbuf) == 0))))
1129 		return false;
1130 
1131 	return true;
1132 }
1133 
1134 /**
1135  * qdf_dp_add_record() - add dp trace record
1136  * @code: dptrace code
1137  * @data: data pointer
1138  * @size: size of buffer
1139  * @print: true to print it in kmsg
1140  *
1141  * Return: none
1142  */
1143 static void qdf_dp_add_record(enum QDF_DP_TRACE_ID code,
1144 			      uint8_t *data, uint8_t size, bool print)
1145 {
1146 	struct qdf_dp_trace_record_s *rec = NULL;
1147 	int index;
1148 	spin_lock_bh(&l_dp_trace_lock);
1149 
1150 	g_qdf_dp_trace_data.num++;
1151 
1152 	if (g_qdf_dp_trace_data.num > MAX_QDF_DP_TRACE_RECORDS)
1153 		g_qdf_dp_trace_data.num = MAX_QDF_DP_TRACE_RECORDS;
1154 
1155 	if (INVALID_QDF_DP_TRACE_ADDR == g_qdf_dp_trace_data.head) {
1156 		/* first record */
1157 		g_qdf_dp_trace_data.head = 0;
1158 		g_qdf_dp_trace_data.tail = 0;
1159 	} else {
1160 		/* queue is not empty */
1161 		g_qdf_dp_trace_data.tail++;
1162 
1163 		if (MAX_QDF_DP_TRACE_RECORDS == g_qdf_dp_trace_data.tail)
1164 			g_qdf_dp_trace_data.tail = 0;
1165 
1166 		if (g_qdf_dp_trace_data.head == g_qdf_dp_trace_data.tail) {
1167 			/* full */
1168 			if (MAX_QDF_DP_TRACE_RECORDS ==
1169 				++g_qdf_dp_trace_data.head)
1170 				g_qdf_dp_trace_data.head = 0;
1171 		}
1172 	}
1173 
1174 	rec = &g_qdf_dp_trace_tbl[g_qdf_dp_trace_data.tail];
1175 	index = g_qdf_dp_trace_data.tail;
1176 	rec->code = code;
1177 	rec->size = 0;
1178 	if (data != NULL && size > 0) {
1179 		if (size > QDF_DP_TRACE_RECORD_SIZE)
1180 			size = QDF_DP_TRACE_RECORD_SIZE;
1181 
1182 		rec->size = size;
1183 		qdf_mem_copy(rec->data, data, size);
1184 	}
1185 	qdf_get_time_of_the_day_in_hr_min_sec_usec(rec->time,
1186 						   sizeof(rec->time));
1187 	rec->pid = (in_interrupt() ? 0 : current->pid);
1188 	spin_unlock_bh(&l_dp_trace_lock);
1189 
1190 	if ((g_qdf_dp_trace_data.live_mode || (print == true)) &&
1191 	    (rec->code < QDF_DP_TRACE_MAX))
1192 		qdf_dp_trace_cb_table[rec->code] (rec, index);
1193 }
1194 
1195 
1196 /**
1197  * qdf_log_eapol_pkt() - log EAPOL packet
1198  * @session_id: vdev_id
1199  * @skb: skb pointer
1200  * @dir: direction
1201  *
1202  * Return: true/false
1203  */
1204 static bool qdf_log_eapol_pkt(uint8_t session_id, struct sk_buff *skb,
1205 			      enum qdf_proto_dir dir)
1206 {
1207 	enum qdf_proto_subtype subtype;
1208 
1209 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_EAPOL) &&
1210 		((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_EAPOL ==
1211 			QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1212 		 (dir == QDF_RX && qdf_nbuf_is_ipv4_eapol_pkt(skb) == true))) {
1213 
1214 		subtype = qdf_nbuf_get_eapol_subtype(skb);
1215 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_EAPOL_PACKET_RECORD,
1216 			session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
1217 			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
1218 			QDF_PROTO_TYPE_EAPOL, subtype, dir));
1219 		if (QDF_TX == dir)
1220 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1221 		else if (QDF_RX == dir)
1222 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1223 
1224 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
1225 		return true;
1226 	}
1227 	return false;
1228 }
1229 
1230 /**
1231  * qdf_log_dhcp_pkt() - log DHCP packet
1232  * @session_id: vdev_id
1233  * @skb: skb pointer
1234  * @dir: direction
1235  *
1236  * Return: true/false
1237  */
1238 static bool qdf_log_dhcp_pkt(uint8_t session_id, struct sk_buff *skb,
1239 			     enum qdf_proto_dir dir)
1240 {
1241 	enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
1242 
1243 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_DHCP) &&
1244 		((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_DHCP ==
1245 				QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1246 		 (dir == QDF_RX && qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true))) {
1247 
1248 		subtype = qdf_nbuf_get_dhcp_subtype(skb);
1249 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_DHCP_PACKET_RECORD,
1250 			session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
1251 			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
1252 			QDF_PROTO_TYPE_DHCP, subtype, dir));
1253 		if (QDF_TX == dir)
1254 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1255 		else if (QDF_RX == dir)
1256 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1257 
1258 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
1259 		return true;
1260 	}
1261 	return false;
1262 }
1263 
1264 /**
1265  * qdf_log_arp_pkt() - log ARP packet
1266  * @session_id: vdev_id
1267  * @skb: skb pointer
1268  * @dir: direction
1269  *
1270  * Return: true/false
1271  */
1272 static bool qdf_log_arp_pkt(uint8_t session_id, struct sk_buff *skb,
1273 			    enum qdf_proto_dir dir)
1274 {
1275 	enum qdf_proto_subtype proto_subtype;
1276 
1277 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ARP) &&
1278 		((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ARP ==
1279 			QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1280 		 (dir == QDF_RX && qdf_nbuf_is_ipv4_arp_pkt(skb) == true))) {
1281 
1282 		proto_subtype = qdf_nbuf_get_arp_subtype(skb);
1283 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ARP_PACKET_RECORD,
1284 			session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
1285 			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
1286 			QDF_PROTO_TYPE_ARP, proto_subtype, dir));
1287 		if (QDF_TX == dir)
1288 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1289 		else if (QDF_RX == dir)
1290 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1291 
1292 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
1293 		return true;
1294 	}
1295 	return false;
1296 }
1297 
1298 /**
1299  * qdf_dp_trace_log_pkt() - log packet type enabled through iwpriv
1300  * @session_id: vdev_id
1301  * @skb: skb pointer
1302  * @dir: direction
1303  *
1304  * Return: none
1305  */
1306 void qdf_dp_trace_log_pkt(uint8_t session_id, struct sk_buff *skb,
1307 			  enum qdf_proto_dir dir)
1308 {
1309 	if (qdf_dp_get_proto_bitmap()) {
1310 		if (qdf_log_arp_pkt(session_id,
1311 			skb, dir) == false) {
1312 			if (qdf_log_dhcp_pkt(session_id,
1313 				skb, dir) == false) {
1314 				if (qdf_log_eapol_pkt(session_id,
1315 					skb, dir) == false) {
1316 					return;
1317 				}
1318 			}
1319 		}
1320 	}
1321 }
1322 EXPORT_SYMBOL(qdf_dp_trace_log_pkt);
1323 
1324 /**
1325  * qdf_dp_display_mgmt_pkt() - display proto packet
1326  * @record: dptrace record
1327  * @index: index
1328  *
1329  * Return: none
1330  */
1331 void qdf_dp_display_mgmt_pkt(struct qdf_dp_trace_record_s *record,
1332 			      uint16_t index)
1333 {
1334 	struct qdf_dp_trace_mgmt_buf *buf =
1335 		(struct qdf_dp_trace_mgmt_buf *)record->data;
1336 
1337 	DPTRACE_PRINT("DPT: %04d: %s: %s vdev_id %d", index,
1338 		record->time, qdf_dp_code_to_string(record->code),
1339 		buf->vdev_id);
1340 	DPTRACE_PRINT("DPT: Type %s Subtype %s", qdf_dp_type_to_str(buf->type),
1341 		qdf_dp_subtype_to_str(buf->subtype));
1342 }
1343 EXPORT_SYMBOL(qdf_dp_display_mgmt_pkt);
1344 
1345 /**
1346  * qdf_dp_trace_mgmt_pkt() - record mgmt packet
1347  * @code: dptrace code
1348  * @vdev_id: vdev id
1349  * @type: proto type
1350  * @subtype: proto subtype
1351  *
1352  * Return: none
1353  */
1354 void qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
1355 		enum qdf_proto_type type, enum qdf_proto_subtype subtype)
1356 {
1357 	struct qdf_dp_trace_mgmt_buf buf;
1358 	int buf_size = sizeof(struct qdf_dp_trace_mgmt_buf);
1359 
1360 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
1361 		return;
1362 
1363 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
1364 		QDF_BUG(0);
1365 
1366 	buf.type = type;
1367 	buf.subtype = subtype;
1368 	buf.vdev_id = vdev_id;
1369 	qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, true);
1370 }
1371 EXPORT_SYMBOL(qdf_dp_trace_mgmt_pkt);
1372 
1373 /**
1374  * qdf_dp_display_event_record() - display event records
1375  * @record: dptrace record
1376  * @index: index
1377  *
1378  * Return: none
1379  */
1380 void qdf_dp_display_event_record(struct qdf_dp_trace_record_s *record,
1381 			      uint16_t index)
1382 {
1383 	struct qdf_dp_trace_event_buf *buf =
1384 		(struct qdf_dp_trace_event_buf *)record->data;
1385 
1386 	DPTRACE_PRINT("DPT: %04d: %s: %s vdev_id %d", index,
1387 		record->time, qdf_dp_code_to_string(record->code),
1388 		buf->vdev_id);
1389 	DPTRACE_PRINT("DPT: Type %s Subtype %s", qdf_dp_type_to_str(buf->type),
1390 		qdf_dp_subtype_to_str(buf->subtype));
1391 }
1392 EXPORT_SYMBOL(qdf_dp_display_event_record);
1393 
1394 /**
1395  * qdf_dp_trace_record_event() - record events
1396  * @code: dptrace code
1397  * @vdev_id: vdev id
1398  * @type: proto type
1399  * @subtype: proto subtype
1400  *
1401  * Return: none
1402  */
1403 void qdf_dp_trace_record_event(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
1404 		enum qdf_proto_type type, enum qdf_proto_subtype subtype)
1405 {
1406 	struct qdf_dp_trace_event_buf buf;
1407 	int buf_size = sizeof(struct qdf_dp_trace_event_buf);
1408 
1409 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
1410 		return;
1411 
1412 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
1413 		QDF_BUG(0);
1414 
1415 	buf.type = type;
1416 	buf.subtype = subtype;
1417 	buf.vdev_id = vdev_id;
1418 	qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, true);
1419 }
1420 EXPORT_SYMBOL(qdf_dp_trace_record_event);
1421 
1422 /**
1423  * qdf_dp_display_proto_pkt() - display proto packet
1424  * @record: dptrace record
1425  * @index: index
1426  *
1427  * Return: none
1428  */
1429 void qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s *record,
1430 			      uint16_t index)
1431 {
1432 	struct qdf_dp_trace_proto_buf *buf =
1433 		(struct qdf_dp_trace_proto_buf *)record->data;
1434 
1435 	DPTRACE_PRINT("DPT: %04d: %s: %s vdev_id %d", index,
1436 		record->time, qdf_dp_code_to_string(record->code),
1437 		buf->vdev_id);
1438 	DPTRACE_PRINT("DPT: SA: " QDF_MAC_ADDRESS_STR " %s DA: "
1439 		  QDF_MAC_ADDRESS_STR " Type %s Subtype %s",
1440 		QDF_MAC_ADDR_ARRAY(buf->sa.bytes), qdf_dp_dir_to_str(buf->dir),
1441 		QDF_MAC_ADDR_ARRAY(buf->da.bytes),
1442 		qdf_dp_type_to_str(buf->type),
1443 		qdf_dp_subtype_to_str(buf->subtype));
1444 }
1445 EXPORT_SYMBOL(qdf_dp_display_proto_pkt);
1446 
1447 /**
1448  * qdf_dp_trace_proto_pkt() - record proto packet
1449  * @code: dptrace code
1450  * @vdev_id: vdev id
1451  * @sa: source mac address
1452  * @da: destination mac address
1453  * @type: proto type
1454  * @subtype: proto subtype
1455  * @dir: direction
1456  *
1457  * Return: none
1458  */
1459 void qdf_dp_trace_proto_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
1460 		uint8_t *sa, uint8_t *da, enum qdf_proto_type type,
1461 		enum qdf_proto_subtype subtype, enum qdf_proto_dir dir)
1462 {
1463 	struct qdf_dp_trace_proto_buf buf;
1464 	int buf_size = sizeof(struct qdf_dp_trace_ptr_buf);
1465 
1466 	if (qdf_dp_enable_check(NULL, code, dir) == false)
1467 		return;
1468 
1469 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
1470 		QDF_BUG(0);
1471 
1472 	memcpy(&buf.sa, sa, QDF_NET_ETH_LEN);
1473 	memcpy(&buf.da, da, QDF_NET_ETH_LEN);
1474 	buf.dir = dir;
1475 	buf.type = type;
1476 	buf.subtype = subtype;
1477 	buf.vdev_id = vdev_id;
1478 	qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, true);
1479 }
1480 EXPORT_SYMBOL(qdf_dp_trace_proto_pkt);
1481 
1482 /**
1483  * qdf_dp_display_ptr_record() - display record
1484  * @record: dptrace record
1485  * @index: index
1486  *
1487  * Return: none
1488  */
1489 void qdf_dp_display_ptr_record(struct qdf_dp_trace_record_s *record,
1490 				uint16_t index)
1491 {
1492 	struct qdf_dp_trace_ptr_buf *buf =
1493 		(struct qdf_dp_trace_ptr_buf *)record->data;
1494 
1495 	if (record->code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD)
1496 		DPTRACE_PRINT("DPT: %04d: %s: %s msdu_id: %d, status: %d",
1497 			 index, record->time,
1498 			 qdf_dp_code_to_string(record->code), buf->msdu_id,
1499 			 buf->status);
1500 	else
1501 		DPTRACE_PRINT("DPT: %04d: %s: %s msdu_id: %d, vdev_id: %d",
1502 			 index,
1503 			 record->time, qdf_dp_code_to_string(record->code),
1504 			 buf->msdu_id, buf->status);
1505 	dump_hex_trace("cookie", (uint8_t *)&buf->cookie, sizeof(buf->cookie));
1506 }
1507 EXPORT_SYMBOL(qdf_dp_display_ptr_record);
1508 
1509 /**
1510  * qdf_dp_trace_ptr() - record dptrace
1511  * @code: dptrace code
1512  * @data: data
1513  * @size: size of data
1514  * @msdu_id: msdu_id
1515  * @status: return status
1516  *
1517  * Return: none
1518  */
1519 void qdf_dp_trace_ptr(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
1520 		uint8_t *data, uint8_t size, uint16_t msdu_id, uint16_t status)
1521 {
1522 	struct qdf_dp_trace_ptr_buf buf;
1523 	int buf_size = sizeof(struct qdf_dp_trace_ptr_buf);
1524 
1525 	if (qdf_dp_enable_check(nbuf, code, QDF_TX) == false)
1526 		return;
1527 
1528 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
1529 		QDF_BUG(0);
1530 
1531 	qdf_mem_copy(&buf.cookie, data, size);
1532 	buf.msdu_id = msdu_id;
1533 	buf.status = status;
1534 	qdf_dp_add_record(code, (uint8_t *)&buf, buf_size,
1535 				QDF_NBUF_CB_DP_TRACE_PRINT(nbuf));
1536 }
1537 EXPORT_SYMBOL(qdf_dp_trace_ptr);
1538 
1539 /**
1540  * qdf_dp_display_trace() - Displays a record in DP trace
1541  * @pRecord  : pointer to a record in DP trace
1542  * @recIndex : record index
1543  *
1544  * Return: None
1545  */
1546 void qdf_dp_display_record(struct qdf_dp_trace_record_s *pRecord,
1547 				uint16_t recIndex)
1548 {
1549 	DPTRACE_PRINT("DPT: %04d: %s: %s", recIndex,
1550 		pRecord->time, qdf_dp_code_to_string(pRecord->code));
1551 	switch (pRecord->code) {
1552 	case  QDF_DP_TRACE_HDD_TX_TIMEOUT:
1553 		DPTRACE_PRINT("DPT: HDD TX Timeout\n");
1554 		break;
1555 	case  QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
1556 		DPTRACE_PRINT("DPT: HDD SoftAP TX Timeout\n");
1557 		break;
1558 	case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
1559 	case QDF_DP_TRACE_HDD_RX_PACKET_RECORD:
1560 		dump_hex_trace("DATA", pRecord->data, pRecord->size);
1561 		break;
1562 	default:
1563 		dump_hex_trace("cookie", pRecord->data, pRecord->size);
1564 	}
1565 }
1566 EXPORT_SYMBOL(qdf_dp_display_record);
1567 
1568 
1569 /**
1570  * qdf_dp_trace() - Stores the data in buffer
1571  * @nbuf  : defines the netbuf
1572  * @code : defines the event
1573  * @data : defines the data to be stored
1574  * @size : defines the size of the data record
1575  *
1576  * Return: None
1577  */
1578 void qdf_dp_trace(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
1579 			uint8_t *data, uint8_t size, enum qdf_proto_dir dir)
1580 {
1581 
1582 	if (qdf_dp_enable_check(nbuf, code, dir) == false)
1583 		return;
1584 
1585 	qdf_dp_add_record(code, data, size,
1586 		(nbuf != NULL) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false);
1587 }
1588 EXPORT_SYMBOL(qdf_dp_trace);
1589 
1590 /**
1591  * qdf_dp_trace_spin_lock_init() - initializes the lock variable before use
1592  * This function will be called from cds_alloc_global_context, we will have lock
1593  * available to use ASAP
1594  *
1595  * Return: None
1596  */
1597 void qdf_dp_trace_spin_lock_init(void)
1598 {
1599 	spin_lock_init(&l_dp_trace_lock);
1600 }
1601 EXPORT_SYMBOL(qdf_dp_trace_spin_lock_init);
1602 
1603 /**
1604  * qdf_dp_trace_enable_live_mode() - enable live mode for dptrace
1605  *
1606  * Return: none
1607  */
1608 void qdf_dp_trace_enable_live_mode(void)
1609 {
1610 	g_qdf_dp_trace_data.live_mode = 1;
1611 
1612 }
1613 EXPORT_SYMBOL(qdf_dp_trace_enable_live_mode);
1614 
1615 
1616 /**
1617  * qdf_dp_trace_clear_buffer() - clear dp trace buffer
1618  *
1619  * Return: none
1620  */
1621 void qdf_dp_trace_clear_buffer(void)
1622 {
1623 	g_qdf_dp_trace_data.head = INVALID_QDF_DP_TRACE_ADDR;
1624 	g_qdf_dp_trace_data.tail = INVALID_QDF_DP_TRACE_ADDR;
1625 	g_qdf_dp_trace_data.num = 0;
1626 	g_qdf_dp_trace_data.proto_bitmap = QDF_NBUF_PKT_TRAC_TYPE_EAPOL |
1627 					   QDF_NBUF_PKT_TRAC_TYPE_DHCP |
1628 					   QDF_NBUF_PKT_TRAC_TYPE_MGMT_ACTION |
1629 					   QDF_NBUF_PKT_TRAC_TYPE_ARP;
1630 	g_qdf_dp_trace_data.no_of_record = 0;
1631 	g_qdf_dp_trace_data.verbosity    = QDF_DP_TRACE_VERBOSITY_HIGH;
1632 	g_qdf_dp_trace_data.enable = true;
1633 	g_qdf_dp_trace_data.tx_count = 0;
1634 	g_qdf_dp_trace_data.rx_count = 0;
1635 	g_qdf_dp_trace_data.live_mode = 0;
1636 
1637 	memset(g_qdf_dp_trace_tbl, 0,
1638 	   MAX_QDF_DP_TRACE_RECORDS * sizeof(struct qdf_dp_trace_record_s));
1639 }
1640 EXPORT_SYMBOL(qdf_dp_trace_clear_buffer);
1641 
1642 /**
1643  * qdf_dp_trace_dump_all() - Dump data from ring buffer via call back functions
1644  * registered with QDF
1645  * @code: Reason code
1646  * @count: Number of lines to dump starting from tail to head
1647  *
1648  * Return: None
1649  */
1650 void qdf_dp_trace_dump_all(uint32_t count)
1651 {
1652 	struct qdf_dp_trace_record_s p_record;
1653 	int32_t i, tail;
1654 
1655 	if (!g_qdf_dp_trace_data.enable) {
1656 		QDF_TRACE(QDF_MODULE_ID_SYS,
1657 			  QDF_TRACE_LEVEL_ERROR, "Tracing Disabled");
1658 		return;
1659 	}
1660 
1661 	QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_ERROR,
1662 		  "Total Records: %d, Head: %d, Tail: %d",
1663 		  g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head,
1664 		  g_qdf_dp_trace_data.tail);
1665 
1666 	/* aquire the lock so that only one thread at a time can read
1667 	 * the ring buffer
1668 	 */
1669 	spin_lock_bh(&l_dp_trace_lock);
1670 
1671 	if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) {
1672 		i = g_qdf_dp_trace_data.head;
1673 		tail = g_qdf_dp_trace_data.tail;
1674 
1675 		if (count) {
1676 			if (count > g_qdf_dp_trace_data.num)
1677 				count = g_qdf_dp_trace_data.num;
1678 			if (tail >= (count - 1))
1679 				i = tail - count + 1;
1680 			else if (count != MAX_QDF_DP_TRACE_RECORDS)
1681 				i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) -
1682 							     tail);
1683 		}
1684 
1685 		p_record = g_qdf_dp_trace_tbl[i];
1686 		spin_unlock_bh(&l_dp_trace_lock);
1687 		for (;; ) {
1688 
1689 			qdf_dp_trace_cb_table[p_record.
1690 					   code] (&p_record, (uint16_t)i);
1691 			if (i == tail)
1692 				break;
1693 			i += 1;
1694 
1695 			spin_lock_bh(&l_dp_trace_lock);
1696 			if (MAX_QDF_DP_TRACE_RECORDS == i)
1697 				i = 0;
1698 
1699 			p_record = g_qdf_dp_trace_tbl[i];
1700 			spin_unlock_bh(&l_dp_trace_lock);
1701 		}
1702 	} else {
1703 		spin_unlock_bh(&l_dp_trace_lock);
1704 	}
1705 }
1706 EXPORT_SYMBOL(qdf_dp_trace_dump_all);
1707 
1708 #endif
1709 
1710 #else /* CONFIG_MCL */
1711 
1712 void qdf_trace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
1713 		char *str_format, ...)
1714 {
1715 	va_list val;
1716 
1717 	va_start(val, str_format);
1718 	/*
1719 	 * TODO: remove this hack when modules start using the qdf_print_ctrl
1720 	 * framework.
1721 	 * Any newly added code that wishes to use QDF_TRACE needs to adapt
1722 	 * to the framework, and using it this way is not encouraged.
1723 	 */
1724 	qdf_trace_msg_cmn(qdf_pidx, module, level, str_format, val);
1725 	va_end(val);
1726 }
1727 EXPORT_SYMBOL(qdf_trace_msg);
1728 #endif /* CONFIG_MCL */
1729 
1730 struct qdf_print_ctrl print_ctrl_obj[MAX_PRINT_CONFIG_SUPPORTED];
1731 
1732 struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = {
1733 	[QDF_MODULE_ID_TDLS] = {"tdls"},
1734 	[QDF_MODULE_ID_ACS] = {"ACS"},
1735 	[QDF_MODULE_ID_SCAN_SM] = {"scan state machine"},
1736 	[QDF_MODULE_ID_SCANENTRY] = {"scan entry"},
1737 	[QDF_MODULE_ID_WDS] = {"WDS"},
1738 	[QDF_MODULE_ID_ACTION] = {"action"},
1739 	[QDF_MODULE_ID_ROAM] = {"STA roaming"},
1740 	[QDF_MODULE_ID_INACT] = {"inactivity"},
1741 	[QDF_MODULE_ID_DOTH] = {"11h"},
1742 	[QDF_MODULE_ID_IQUE] = {"IQUE"},
1743 	[QDF_MODULE_ID_WME] = {"WME"},
1744 	[QDF_MODULE_ID_ACL] = {"ACL"},
1745 	[QDF_MODULE_ID_WPA] = {"WPA/RSN"},
1746 	[QDF_MODULE_ID_RADKEYS] = {"dump 802.1x keys"},
1747 	[QDF_MODULE_ID_RADDUMP] = {"dump radius packet"},
1748 	[QDF_MODULE_ID_RADIUS] = {"802.1x radius client"},
1749 	[QDF_MODULE_ID_DOT1XSM] = {"802.1x state machine"},
1750 	[QDF_MODULE_ID_DOT1X] = {"802.1x authenticator"},
1751 	[QDF_MODULE_ID_POWER] = {"power save"},
1752 	[QDF_MODULE_ID_STATE] = {"state"},
1753 	[QDF_MODULE_ID_OUTPUT] = {"output"},
1754 	[QDF_MODULE_ID_SCAN] = {"scan"},
1755 	[QDF_MODULE_ID_AUTH] = {"authentication"},
1756 	[QDF_MODULE_ID_ASSOC] = {"association"},
1757 	[QDF_MODULE_ID_NODE] = {"node"},
1758 	[QDF_MODULE_ID_ELEMID] = {"element ID"},
1759 	[QDF_MODULE_ID_XRATE] = {"rate"},
1760 	[QDF_MODULE_ID_INPUT] = {"input"},
1761 	[QDF_MODULE_ID_CRYPTO] = {"crypto"},
1762 	[QDF_MODULE_ID_DUMPPKTS] = {"dump packet"},
1763 	[QDF_MODULE_ID_DEBUG] = {"debug"},
1764 	[QDF_MODULE_ID_MLME] = {"mlme"},
1765 	[QDF_MODULE_ID_RRM] = {"rrm"},
1766 	[QDF_MODULE_ID_WNM] = {"wnm"},
1767 	[QDF_MODULE_ID_P2P_PROT] = {"p2p_prot"},
1768 	[QDF_MODULE_ID_PROXYARP] = {"proxyarp"},
1769 	[QDF_MODULE_ID_L2TIF] = {"l2tif"},
1770 	[QDF_MODULE_ID_WIFIPOS] = {"wifipos"},
1771 	[QDF_MODULE_ID_WRAP] = {"wrap"},
1772 	[QDF_MODULE_ID_DFS] = {"dfs"},
1773 	[QDF_MODULE_ID_ATF] = {"atf"},
1774 	[QDF_MODULE_ID_SPLITMAC] = {"splitmac"},
1775 	[QDF_MODULE_ID_IOCTL] = {"ioctl"},
1776 	[QDF_MODULE_ID_NAC] = {"nac"},
1777 	[QDF_MODULE_ID_MESH] = {"mesh"},
1778 	[QDF_MODULE_ID_MBO] = {"mbo"},
1779 	[QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = {"extchanswitch"},
1780 	[QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = {"extchanscan"},
1781 	[QDF_MODULE_ID_TLSHIM] = {"tlshim"},
1782 	[QDF_MODULE_ID_WMI] = {"WMI"},
1783 	[QDF_MODULE_ID_HTT] = {"HTT"},
1784 	[QDF_MODULE_ID_HDD] = {"HDD"},
1785 	[QDF_MODULE_ID_SME] = {"SME"},
1786 	[QDF_MODULE_ID_PE] = {"PE"},
1787 	[QDF_MODULE_ID_WMA] = {"WMA"},
1788 	[QDF_MODULE_ID_SYS] = {"SYS"},
1789 	[QDF_MODULE_ID_QDF] = {"QDF"},
1790 	[QDF_MODULE_ID_SAP] = {"SAP"},
1791 	[QDF_MODULE_ID_HDD_SOFTAP] = {"HDD_SAP"},
1792 	[QDF_MODULE_ID_HDD_DATA] = {"DATA"},
1793 	[QDF_MODULE_ID_HDD_SAP_DATA] = {"SAP_DATA"},
1794 	[QDF_MODULE_ID_HIF] = {"HIF"},
1795 	[QDF_MODULE_ID_HTC] = {"HTC"},
1796 	[QDF_MODULE_ID_TXRX] = {"TXRX"},
1797 	[QDF_MODULE_ID_QDF_DEVICE] = {"QDF_DEV"},
1798 	[QDF_MODULE_ID_CFG] = {"CFG"},
1799 	[QDF_MODULE_ID_BMI] = {"BMI"},
1800 	[QDF_MODULE_ID_EPPING] = {"EPPING"},
1801 	[QDF_MODULE_ID_QVIT] = {"QVIT"},
1802 	[QDF_MODULE_ID_DP] = {"DP"},
1803 	[QDF_MODULE_ID_SOC] = {"SOC"},
1804 	[QDF_MODULE_ID_OS_IF] = {"OSIF"},
1805 	[QDF_MODULE_ID_TARGET_IF] = {"TIF"},
1806 	[QDF_MODULE_ID_SCHEDULER] = {"SCH"},
1807 	[QDF_MODULE_ID_MGMT_TXRX] = {"MGMT_TXRX"},
1808 	[QDF_MODULE_ID_PMO] = {"PMO"},
1809 	[QDF_MODULE_ID_POLICY_MGR] = {"POLICY_MGR"},
1810 	[QDF_MODULE_ID_NAN] = {"NAN"},
1811 	[QDF_MODULE_ID_P2P] = {"P2P"},
1812 	[QDF_MODULE_ID_OFFCHAN_TXRX] = {"OFFCHAN"},
1813 	[QDF_MODULE_ID_ANY] = {"ANY"},
1814 };
1815 
1816 #ifdef CONFIG_MCL
1817 #define print_to_console(str)
1818 #else
1819 static inline void print_to_console(char *str_buffer)
1820 {
1821 	pr_err("%s\n", str_buffer);
1822 }
1823 #endif
1824 
1825 void qdf_trace_msg_cmn(unsigned int idx,
1826 			QDF_MODULE_ID category,
1827 			QDF_TRACE_LEVEL verbose,
1828 			const char *str_format, va_list val)
1829 {
1830 	char str_buffer[QDF_TRACE_BUFFER_SIZE];
1831 	int n;
1832 
1833 	/* Check if index passed is valid */
1834 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
1835 		pr_info("%s: Invalid index - %d\n", __func__, idx);
1836 		return;
1837 	}
1838 
1839 	/* Check if print control object is in use */
1840 	if (!print_ctrl_obj[idx].in_use) {
1841 		pr_info("%s: Invalid print control object\n", __func__);
1842 		return;
1843 	}
1844 
1845 	/* Check if category passed is valid */
1846 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
1847 		pr_info("%s: Invalid category: %d\n", __func__, category);
1848 		return;
1849 	}
1850 
1851 	/* Check if verbose mask is valid */
1852 	if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
1853 		pr_info("%s: Invalid verbose level %d\n", __func__, verbose);
1854 		return;
1855 	}
1856 
1857 	/*
1858 	 * Print the trace message when the desired verbose level is set in
1859 	 * the desired category for the print control object
1860 	 */
1861 	if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
1862 	    QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
1863 		/*
1864 		 * The verbose strings are in an array. These are ordered in
1865 		 * the same order as the verbose levels are defined in the enum
1866 		 * (see QDF_TRACE_LEVEL) so we can index into this array with
1867 		 * the level and get the right string. The qdf verbose
1868 		 * are... Off, Fatal, Error, Warning, Info, Info_high,
1869 		 * Info_med, Info_low, Debug
1870 		 */
1871 		static const char * const VERBOSE_STR[] = { "  ", "F", "E", "W",
1872 							"I", "IH", "IM", "IL",
1873 							"D" };
1874 
1875 		/* print the prefix string into the string buffer... */
1876 		n = scnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE,
1877 			     "wlan: [%d:%2s:%s] ",
1878 			     in_interrupt() ? 0 : current->pid,
1879 			     VERBOSE_STR[verbose],
1880 			     g_qdf_category_name[category].category_name_str);
1881 
1882 		/* print the formatted log message after the prefix string */
1883 		vscnprintf(str_buffer + n, QDF_TRACE_BUFFER_SIZE - n,
1884 			   str_format, val);
1885 #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE)
1886 		wlan_log_to_user(verbose, (char *)str_buffer,
1887 				 strlen(str_buffer));
1888 		print_to_console(str_buffer);
1889 #else
1890 		pr_err("%s\n", str_buffer);
1891 #endif
1892 		va_end(val);
1893 	}
1894 }
1895 EXPORT_SYMBOL(qdf_trace_msg_cmn);
1896 
1897 QDF_STATUS qdf_print_setup(void)
1898 {
1899 	int i;
1900 
1901 	/* Loop through all print ctrl objects */
1902 	for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
1903 		if (qdf_print_ctrl_cleanup(i))
1904 			return QDF_STATUS_E_FAILURE;
1905 	}
1906 	return QDF_STATUS_SUCCESS;
1907 }
1908 EXPORT_SYMBOL(qdf_print_setup);
1909 
1910 QDF_STATUS qdf_print_ctrl_cleanup(unsigned int idx)
1911 {
1912 	int i = 0;
1913 
1914 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
1915 		pr_info("%s: Invalid index - %d\n", __func__, idx);
1916 		return QDF_STATUS_E_FAILURE;
1917 	}
1918 
1919 	/* Clean up the print control object corresponding to that index
1920 	 * If success, callee to change print control index to -1
1921 	 */
1922 
1923 	for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
1924 		print_ctrl_obj[idx].cat_info[i].category_verbose_mask =
1925 							QDF_TRACE_LEVEL_NONE;
1926 	}
1927 	print_ctrl_obj[idx].custom_print = NULL;
1928 	print_ctrl_obj[idx].custom_ctxt = NULL;
1929 	qdf_print_clean_node_flag(idx);
1930 	print_ctrl_obj[idx].in_use = false;
1931 
1932 	pr_info("%s: Print control object %d cleaned up\n", __func__, idx);
1933 
1934 	return QDF_STATUS_SUCCESS;
1935 }
1936 EXPORT_SYMBOL(qdf_print_ctrl_cleanup);
1937 
1938 int qdf_print_ctrl_register(const struct category_info *cinfo,
1939 			    void *custom_print_handler,
1940 			    void *custom_ctx,
1941 			    const char *pctrl_name)
1942 {
1943 	int idx = -1;
1944 	int i = 0;
1945 
1946 	for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
1947 		if (!print_ctrl_obj[i].in_use) {
1948 			idx = i;
1949 			break;
1950 		}
1951 	}
1952 
1953 	/* Callee to handle idx -1 appropriately */
1954 	if (idx == -1) {
1955 		pr_info("%s: Allocation failed! No print control object free\n",
1956 			__func__);
1957 		return idx;
1958 	}
1959 
1960 	print_ctrl_obj[idx].in_use = true;
1961 
1962 	/*
1963 	 * In case callee does not pass category info,
1964 	 * custom print handler, custom context and print control name,
1965 	 * we do not set any value here. Clean up for the print control
1966 	 * getting allocated would have taken care of initializing
1967 	 * default values.
1968 	 *
1969 	 * We need to only set in_use to 1 in such a case
1970 	 */
1971 
1972 	if (pctrl_name) {
1973 		qdf_str_lcopy(print_ctrl_obj[idx].name, pctrl_name,
1974 			      qdf_str_len(pctrl_name) + 1);
1975 	}
1976 
1977 	if (custom_print_handler)
1978 		print_ctrl_obj[idx].custom_print = custom_print_handler;
1979 
1980 	if (custom_ctx)
1981 		print_ctrl_obj[idx].custom_ctxt = custom_ctx;
1982 
1983 	if (cinfo) {
1984 		for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
1985 			if (cinfo[i].category_verbose_mask ==
1986 			    QDF_TRACE_LEVEL_ALL) {
1987 				print_ctrl_obj[idx].cat_info[i]
1988 				.category_verbose_mask = 0xFFFF;
1989 			} else {
1990 				print_ctrl_obj[idx].cat_info[i]
1991 				.category_verbose_mask =
1992 				cinfo[i].category_verbose_mask;
1993 			}
1994 		}
1995 	}
1996 
1997 	pr_info("%s: Allocated print control object %d\n",
1998 		__func__, idx);
1999 	return idx;
2000 }
2001 EXPORT_SYMBOL(qdf_print_ctrl_register);
2002 
2003 #ifndef CONFIG_MCL
2004 void qdf_shared_print_ctrl_cleanup(void)
2005 {
2006 	qdf_print_ctrl_cleanup(qdf_pidx);
2007 }
2008 EXPORT_SYMBOL(qdf_shared_print_ctrl_cleanup);
2009 
2010 extern int qdf_dbg_mask;
2011 void qdf_shared_print_ctrl_init(void)
2012 {
2013 	int i;
2014 	QDF_TRACE_LEVEL level;
2015 	struct category_info *cinfo = qdf_mem_malloc((sizeof(*cinfo))*
2016 			MAX_SUPPORTED_CATEGORY);
2017 	if (cinfo == NULL) {
2018 		pr_info("ERROR!! qdf_mem_malloc failed. \
2019 				Shared Print Ctrl object not initialized \
2020 				\nQDF_TRACE messages may not be logged/displayed");
2021 		return;
2022 	}
2023 	for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
2024 		cinfo[i].category_verbose_mask = 0;
2025 		for (level = QDF_TRACE_LEVEL_NONE; level <= qdf_dbg_mask; level++) {
2026 			cinfo[i].category_verbose_mask |=
2027 				QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level);
2028 		}
2029 	}
2030 	qdf_pidx = qdf_print_ctrl_register(cinfo, NULL, NULL,
2031 			"LOG_SHARED_OBJ");
2032 	qdf_mem_free(cinfo);
2033 }
2034 EXPORT_SYMBOL(qdf_shared_print_ctrl_init);
2035 #endif
2036 
2037 QDF_STATUS qdf_print_set_category_verbose(unsigned int idx,
2038 						QDF_MODULE_ID category,
2039 						QDF_TRACE_LEVEL verbose,
2040 						bool is_set)
2041 {
2042 	/* Check if index passed is valid */
2043 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
2044 		pr_info("%s: Invalid index - %d\n", __func__, idx);
2045 		return QDF_STATUS_E_FAILURE;
2046 	}
2047 
2048 	/* Check if print control object is in use */
2049 	if (!print_ctrl_obj[idx].in_use) {
2050 		pr_info("%s: Invalid print control object\n", __func__);
2051 		return QDF_STATUS_E_FAILURE;
2052 	}
2053 
2054 	/* Check if category passed is valid */
2055 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
2056 		pr_info("%s: Invalid category: %d\n", __func__, category);
2057 		return QDF_STATUS_E_FAILURE;
2058 	}
2059 
2060 	/* Check if verbose mask is valid */
2061 	if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
2062 		pr_info("%s: Invalid verbose level %d\n", __func__, verbose);
2063 		return QDF_STATUS_E_FAILURE;
2064 	}
2065 
2066 	if (verbose == QDF_TRACE_LEVEL_ALL) {
2067 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
2068 				0xFFFF;
2069 		return QDF_STATUS_SUCCESS;
2070 	}
2071 
2072 	if (verbose == QDF_TRACE_LEVEL_NONE) {
2073 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
2074 				QDF_TRACE_LEVEL_NONE;
2075 		return QDF_STATUS_SUCCESS;
2076 	}
2077 
2078 	if (!is_set) {
2079 		if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask
2080 		    & QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
2081 			print_ctrl_obj[idx].cat_info[category]
2082 				.category_verbose_mask &=
2083 				~QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
2084 		}
2085 	} else {
2086 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask |=
2087 				QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
2088 	}
2089 
2090 	pr_info("%s: Print control object %d, Category %d, Verbose level %d\n",
2091 		__func__,
2092 		idx,
2093 		category,
2094 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask);
2095 
2096 	return QDF_STATUS_SUCCESS;
2097 }
2098 EXPORT_SYMBOL(qdf_print_set_category_verbose);
2099 
2100 bool qdf_print_is_category_enabled(unsigned int idx, QDF_MODULE_ID category)
2101 {
2102 	QDF_TRACE_LEVEL verbose_mask;
2103 
2104 	/* Check if index passed is valid */
2105 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
2106 		pr_info("%s: Invalid index - %d\n", __func__, idx);
2107 		return false;
2108 	}
2109 
2110 	/* Check if print control object is in use */
2111 	if (!print_ctrl_obj[idx].in_use) {
2112 		pr_info("%s: Invalid print control object\n", __func__);
2113 		return false;
2114 	}
2115 
2116 	/* Check if category passed is valid */
2117 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
2118 		pr_info("%s: Invalid category: %d\n", __func__, category);
2119 		return false;
2120 	}
2121 
2122 	verbose_mask =
2123 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask;
2124 
2125 	if (verbose_mask == QDF_TRACE_LEVEL_NONE)
2126 		return false;
2127 	else
2128 		return true;
2129 }
2130 EXPORT_SYMBOL(qdf_print_is_category_enabled);
2131 
2132 bool qdf_print_is_verbose_enabled(unsigned int idx, QDF_MODULE_ID category,
2133 				  QDF_TRACE_LEVEL verbose)
2134 {
2135 	bool verbose_enabled = false;
2136 
2137 	/* Check if index passed is valid */
2138 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
2139 		pr_info("%s: Invalid index - %d\n", __func__, idx);
2140 		return verbose_enabled;
2141 	}
2142 
2143 	/* Check if print control object is in use */
2144 	if (!print_ctrl_obj[idx].in_use) {
2145 		pr_info("%s: Invalid print control object\n", __func__);
2146 		return verbose_enabled;
2147 	}
2148 
2149 	/* Check if category passed is valid */
2150 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
2151 		pr_info("%s: Invalid category: %d\n", __func__, category);
2152 		return verbose_enabled;
2153 	}
2154 
2155 	if ((verbose == QDF_TRACE_LEVEL_NONE) ||
2156 	    (verbose >= QDF_TRACE_LEVEL_MAX)) {
2157 		verbose_enabled = false;
2158 	} else if (verbose == QDF_TRACE_LEVEL_ALL) {
2159 		if (print_ctrl_obj[idx].cat_info[category]
2160 					.category_verbose_mask == 0xFFFF)
2161 			verbose_enabled = true;
2162 	} else {
2163 		verbose_enabled =
2164 		(print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
2165 		 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) ? true : false;
2166 	}
2167 
2168 	return verbose_enabled;
2169 }
2170 EXPORT_SYMBOL(qdf_print_is_verbose_enabled);
2171 
2172 #ifdef DBG_LVL_MAC_FILTERING
2173 
2174 QDF_STATUS qdf_print_set_node_flag(unsigned int idx, uint8_t enable)
2175 {
2176 	/* Check if index passed is valid */
2177 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
2178 		pr_info("%s: Invalid index - %d\n", __func__, idx);
2179 		return QDF_STATUS_E_FAILURE;
2180 	}
2181 
2182 	/* Check if print control object is in use */
2183 	if (!print_ctrl_obj[idx].in_use) {
2184 		pr_info("%s: Invalid print control object\n", __func__);
2185 		return QDF_STATUS_E_FAILURE;
2186 	}
2187 
2188 	if (enable > 1) {
2189 		pr_info("%s: Incorrect input: Use 1 or 0 to enable or disable\n",
2190 			__func__);
2191 		return QDF_STATUS_E_FAILURE;
2192 	}
2193 
2194 	print_ctrl_obj[idx].dbglvlmac_on = enable;
2195 	pr_info("%s: DbgLVLmac feature %s\n",
2196 		__func__,
2197 		((enable) ? "enabled" : "disabled"));
2198 
2199 	return QDF_STATUS_SUCCESS;
2200 }
2201 EXPORT_SYMBOL(qdf_print_set_node_flag);
2202 
2203 bool qdf_print_get_node_flag(unsigned int idx)
2204 {
2205 	bool node_flag = false;
2206 
2207 	/* Check if index passed is valid */
2208 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
2209 		pr_info("%s: Invalid index - %d\n", __func__, idx);
2210 		return node_flag;
2211 	}
2212 
2213 	/* Check if print control object is in use */
2214 	if (!print_ctrl_obj[idx].in_use) {
2215 		pr_info("%s: Invalid print control object\n", __func__);
2216 		return node_flag;
2217 	}
2218 
2219 	if (print_ctrl_obj[idx].dbglvlmac_on)
2220 		node_flag = true;
2221 
2222 	return node_flag;
2223 }
2224 EXPORT_SYMBOL(qdf_print_get_node_flag);
2225 
2226 void qdf_print_clean_node_flag(unsigned int idx)
2227 {
2228 	/* Disable dbglvlmac_on during cleanup */
2229 	print_ctrl_obj[idx].dbglvlmac_on = 0;
2230 }
2231 
2232 #else
2233 
2234 void qdf_print_clean_node_flag(unsigned int idx)
2235 {
2236 	/* No operation in case of no support for DBG_LVL_MAC_FILTERING */
2237 	return;
2238 }
2239 #endif
2240 
2241 void QDF_PRINT_INFO(unsigned int idx, QDF_MODULE_ID module,
2242 		    QDF_TRACE_LEVEL level,
2243 		    char *str_format, ...)
2244 {
2245 	va_list args;
2246 
2247 	/* Generic wrapper API will compile qdf_vprint in order to
2248 	 * log the message. Once QDF converged debug framework is in
2249 	 * place, this will be changed to adapt to the framework, compiling
2250 	 * call to converged tracing API
2251 	 */
2252 	va_start(args, str_format);
2253 	qdf_vprint(str_format, args);
2254 	va_end(args);
2255 }
2256 EXPORT_SYMBOL(QDF_PRINT_INFO);
2257 
2258 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
2259 void qdf_logging_init(void)
2260 {
2261 	wlan_logging_sock_init_svc();
2262 	wlan_logging_sock_activate_svc(1, 10);
2263 	nl_srv_init(NULL);
2264 }
2265 
2266 void qdf_logging_exit(void)
2267 {
2268 	nl_srv_exit();
2269 	wlan_logging_sock_deactivate_svc();
2270 	wlan_logging_sock_deinit_svc();
2271 }
2272 #else
2273 void qdf_logging_init(void)
2274 {
2275 }
2276 
2277 void qdf_logging_exit(void)
2278 {
2279 }
2280 #endif
2281 
2282