xref: /wlan-dirver/qca-wifi-host-cmn/qdf/linux/src/qdf_trace.c (revision 7b32946958ccd00534989da3a4b46d0af59a5b5c)
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 #include <qdf_module.h>
43 static int qdf_pidx = -1;
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 CONFIG_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 /**
132  * qdf_trace_set_level() - Set the trace level for a particular module
133  * @module: Module id
134  * @level : trace level
135  *
136  * Trace level is a member of the QDF_TRACE_LEVEL enumeration indicating
137  * the severity of the condition causing the trace message to be issued.
138  * More severe conditions are more likely to be logged.
139  *
140  * This is an external API that allows trace levels to be set for each module.
141  *
142  * Return:  None
143  */
144 void qdf_trace_set_level(QDF_MODULE_ID module, QDF_TRACE_LEVEL level)
145 {
146 	/* make sure the caller is passing in a valid LEVEL */
147 	if (level >= QDF_TRACE_LEVEL_MAX) {
148 		pr_err("%s: Invalid trace level %d passed in!\n", __func__,
149 		       level);
150 		return;
151 	}
152 
153 	/* Treat 'none' differently.  NONE means we have to run off all
154 	 * the bits in the bit mask so none of the traces appear. Anything
155 	 * other than 'none' means we need to turn ON a bit in the bitmask
156 	 */
157 	if (QDF_TRACE_LEVEL_NONE == level)
158 		g_qdf_trace_info[module].module_trace_level =
159 			QDF_TRACE_LEVEL_NONE;
160 	else
161 		/* set the desired bit in the bit mask for the module trace
162 		 * level
163 		 */
164 		g_qdf_trace_info[module].module_trace_level |=
165 			QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level);
166 }
167 EXPORT_SYMBOL(qdf_trace_set_level);
168 
169 /**
170  * qdf_trace_set_module_trace_level() - Set module trace level
171  * @module: Module id
172  * @level: Trace level for a module, as a bitmask as per 'module_trace_info'
173  *
174  * Sets the module trace level where the trace level is given as a bit mask
175  *
176  * Return: None
177  */
178 void qdf_trace_set_module_trace_level(QDF_MODULE_ID module, uint32_t level)
179 {
180 	if (module < 0 || module >= QDF_MODULE_ID_MAX) {
181 		pr_err("%s: Invalid module id %d passed\n", __func__, module);
182 		return;
183 	}
184 	g_qdf_trace_info[module].module_trace_level = level;
185 }
186 EXPORT_SYMBOL(qdf_trace_set_module_trace_level);
187 
188 /**
189  * qdf_trace_set_value() - Set module trace value
190  * @module: Module id
191  * @level: Trace level for a module, as a bitmask as per 'module_trace_info'
192  * @on: set/clear the desired bit in the bit mask
193  *
194  * Return: None
195  */
196 void qdf_trace_set_value(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
197 			 uint8_t on)
198 {
199 	/* make sure the caller is passing in a valid LEVEL */
200 	if (level < 0 || level >= QDF_TRACE_LEVEL_MAX) {
201 		pr_err("%s: Invalid trace level %d passed in!\n", __func__,
202 		       level);
203 		return;
204 	}
205 
206 	/* make sure the caller is passing in a valid module */
207 	if (module < 0 || module >= QDF_MODULE_ID_MAX) {
208 		pr_err("%s: Invalid module id %d passed in!\n", __func__,
209 		       module);
210 		return;
211 	}
212 
213 	/* Treat 'none' differently.  NONE means we have to turn off all
214 	 * the bits in the bit mask so none of the traces appear
215 	 */
216 	if (QDF_TRACE_LEVEL_NONE == level) {
217 		g_qdf_trace_info[module].module_trace_level =
218 			QDF_TRACE_LEVEL_NONE;
219 	}
220 	/* Treat 'All' differently.  All means we have to turn on all
221 	 * the bits in the bit mask so all of the traces appear
222 	 */
223 	else if (QDF_TRACE_LEVEL_ALL == level) {
224 		g_qdf_trace_info[module].module_trace_level = 0xFFFF;
225 	} else {
226 		if (on)
227 			/* set the desired bit in the bit mask for the module
228 			 * trace level
229 			 */
230 			g_qdf_trace_info[module].module_trace_level |=
231 				QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level);
232 		else
233 			/* clear the desired bit in the bit mask for the module
234 			 * trace level
235 			 */
236 			g_qdf_trace_info[module].module_trace_level &=
237 				~(QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level));
238 	}
239 }
240 EXPORT_SYMBOL(qdf_trace_set_value);
241 
242 /**
243  * qdf_trace_get_level() - get the trace level
244  * @module: module Id
245  * @level: trace level
246  *
247  * This is an external API that returns a bool value to signify if a
248  * particular trace level is set for the specified module.
249  * A member of the QDF_TRACE_LEVEL enumeration indicating the severity
250  * of the condition causing the trace message to be issued.
251  *
252  * Note that individual trace levels are the only valid values
253  * for this API.  QDF_TRACE_LEVEL_NONE and QDF_TRACE_LEVEL_ALL
254  * are not valid input and will return false
255  *
256  * Return:
257  * false - the specified trace level for the specified module is OFF
258  * true - the specified trace level for the specified module is ON
259  */
260 bool qdf_trace_get_level(QDF_MODULE_ID module, QDF_TRACE_LEVEL level)
261 {
262 	bool trace_on = false;
263 
264 	if ((QDF_TRACE_LEVEL_NONE == level) ||
265 	    (QDF_TRACE_LEVEL_ALL == level) || (level >= QDF_TRACE_LEVEL_MAX)) {
266 		trace_on = false;
267 	} else {
268 		trace_on = (level & g_qdf_trace_info[module].module_trace_level)
269 			  ? true : false;
270 	}
271 
272 	return trace_on;
273 }
274 EXPORT_SYMBOL(qdf_trace_get_level);
275 
276 /**
277  * qdf_snprintf() - wrapper function to snprintf
278  * @str_buffer: string Buffer
279  * @size: defines the size of the data record
280  * @str_format: Format string in which the message to be logged. This format
281  * string contains printf-like replacement parameters, which follow
282  * this parameter in the variable argument list.
283  *
284  * Return: None
285  */
286 void qdf_snprintf(char *str_buffer, unsigned int size, char *str_format, ...)
287 {
288 	va_list val;
289 
290 	va_start(val, str_format);
291 	snprintf(str_buffer, size, str_format, val);
292 	va_end(val);
293 }
294 EXPORT_SYMBOL(qdf_snprintf);
295 
296 #ifdef QDF_ENABLE_TRACING
297 
298 /**
299  * qdf_trace_msg() - externally called trace function
300  * @module: Module identifier a member of the QDF_MODULE_ID
301  * enumeration that identifies the module issuing the trace message.
302  * @level: Trace level a member of the QDF_TRACE_LEVEL enumeration
303  * indicating the severity of the condition causing the trace message
304  * to be issued. More severe conditions are more likely to be logged.
305  * @str_format: Format string in which the message to be logged. This format
306  * string contains printf-like replacement parameters, which follow
307  * this parameter in the variable argument list.
308  *
309  * Checks the level of severity and accordingly prints the trace messages
310  *
311  * Return: None
312  */
313 void qdf_trace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
314 		   char *str_format, ...)
315 {
316 	va_list val;
317 
318 	va_start(val, str_format);
319 	qdf_trace_msg_cmn(qdf_pidx, module, level, str_format, val);
320 	va_end(val);
321 }
322 EXPORT_SYMBOL(qdf_trace_msg);
323 
324 #define ROW_SIZE 16
325 /* Buffer size = data bytes(2 hex chars plus space) + NULL */
326 #define BUFFER_SIZE ((ROW_SIZE * 3) + 1)
327 
328 /**
329  * qdf_trace_hex_dump() - externally called hex dump function
330  * @module: Module identifier a member of the QDF_MODULE_ID enumeration that
331  * identifies the module issuing the trace message.
332  * @level: Trace level a member of the QDF_TRACE_LEVEL enumeration indicating
333  * the severity of the condition causing the trace message to be
334  * issued. More severe conditions are more likely to be logged.
335  * @data: The base address of the buffer to be logged.
336  * @buf_len: The size of the buffer to be logged.
337  *
338  * Checks the level of severity and accordingly prints the trace messages
339  *
340  * Return:  None
341  */
342 void qdf_trace_hex_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
343 			void *data, int buf_len)
344 {
345 	const u8 *ptr = data;
346 	int i = 0;
347 
348 	if (!qdf_print_is_verbose_enabled(qdf_pidx, module, level))
349 		return;
350 
351 	while (buf_len > 0) {
352 		unsigned char linebuf[BUFFER_SIZE];
353 		int linelen = min(buf_len, ROW_SIZE);
354 
355 		buf_len -= ROW_SIZE;
356 
357 		hex_dump_to_buffer(ptr, linelen, ROW_SIZE, 1,
358 				linebuf, sizeof(linebuf), false);
359 
360 		qdf_trace_msg(module, level, "%.8x: %s", i, linebuf);
361 		ptr += ROW_SIZE;
362 		i += ROW_SIZE;
363 	}
364 }
365 EXPORT_SYMBOL(qdf_trace_hex_dump);
366 
367 #endif
368 
369 /**
370  * qdf_trace_enable() - Enable MTRACE for specific modules
371  * @bitmask_of_module_id: Bitmask according to enum of the modules.
372  *  32[dec] = 0010 0000 [bin] <enum of HDD is 5>
373  *  64[dec] = 0100 0000 [bin] <enum of SME is 6>
374  *  128[dec] = 1000 0000 [bin] <enum of PE is 7>
375  * @enable: can be true or false true implies enabling MTRACE false implies
376  *		disabling MTRACE.
377  *
378  * Enable MTRACE for specific modules whose bits are set in bitmask and enable
379  * is true. if enable is false it disables MTRACE for that module. set the
380  * bitmask according to enum value of the modules.
381  * This functions will be called when you issue ioctl as mentioned following
382  * [iwpriv wlan0 setdumplog <value> <enable>].
383  * <value> - Decimal number, i.e. 64 decimal value shows only SME module,
384  * 128 decimal value shows only PE module, 192 decimal value shows PE and SME.
385  *
386  * Return: None
387  */
388 void qdf_trace_enable(uint32_t bitmask_of_module_id, uint8_t enable)
389 {
390 	int i;
391 
392 	if (bitmask_of_module_id) {
393 		for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
394 			if (((bitmask_of_module_id >> i) & 1)) {
395 				if (enable) {
396 					if (NULL !=
397 					    qdf_trace_restore_cb_table[i]) {
398 						qdf_trace_cb_table[i] =
399 						qdf_trace_restore_cb_table[i];
400 					}
401 				} else {
402 					qdf_trace_restore_cb_table[i] =
403 						qdf_trace_cb_table[i];
404 					qdf_trace_cb_table[i] = NULL;
405 				}
406 			}
407 		}
408 	} else {
409 		if (enable) {
410 			for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
411 				if (NULL != qdf_trace_restore_cb_table[i]) {
412 					qdf_trace_cb_table[i] =
413 						qdf_trace_restore_cb_table[i];
414 				}
415 			}
416 		} else {
417 			for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
418 				qdf_trace_restore_cb_table[i] =
419 					qdf_trace_cb_table[i];
420 				qdf_trace_cb_table[i] = NULL;
421 			}
422 		}
423 	}
424 }
425 EXPORT_SYMBOL(qdf_trace_enable);
426 
427 /**
428  * qdf_trace_init() - initializes qdf trace structures and variables
429  *
430  * Called immediately after cds_preopen, so that we can start recording HDD
431  * events ASAP.
432  *
433  * Return: None
434  */
435 void qdf_trace_init(void)
436 {
437 	uint8_t i;
438 
439 	g_qdf_trace_data.head = INVALID_QDF_TRACE_ADDR;
440 	g_qdf_trace_data.tail = INVALID_QDF_TRACE_ADDR;
441 	g_qdf_trace_data.num = 0;
442 	g_qdf_trace_data.enable = true;
443 	g_qdf_trace_data.dump_count = DEFAULT_QDF_TRACE_DUMP_COUNT;
444 	g_qdf_trace_data.num_since_last_dump = 0;
445 
446 	for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
447 		qdf_trace_cb_table[i] = NULL;
448 		qdf_trace_restore_cb_table[i] = NULL;
449 	}
450 }
451 EXPORT_SYMBOL(qdf_trace_init);
452 
453 #ifdef CONFIG_MCL
454 
455 /**
456  * qdf_trace() - puts the messages in to ring-buffer
457  * @module: Enum of module, basically module id.
458  * @param: Code to be recorded
459  * @session: Session ID of the log
460  * @data: Actual message contents
461  *
462  * This function will be called from each module who wants record the messages
463  * in circular queue. Before calling this functions make sure you have
464  * registered your module with qdf through qdf_trace_register function.
465  *
466  * Return: None
467  */
468 void qdf_trace(uint8_t module, uint8_t code, uint16_t session, uint32_t data)
469 {
470 	tp_qdf_trace_record rec = NULL;
471 	unsigned long flags;
472 	char time[18];
473 
474 	if (!g_qdf_trace_data.enable)
475 		return;
476 
477 	/* if module is not registered, don't record for that module */
478 	if (NULL == qdf_trace_cb_table[module])
479 		return;
480 
481 	qdf_get_time_of_the_day_in_hr_min_sec_usec(time, sizeof(time));
482 	/* Aquire the lock so that only one thread at a time can fill the ring
483 	 * buffer
484 	 */
485 	spin_lock_irqsave(&ltrace_lock, flags);
486 
487 	g_qdf_trace_data.num++;
488 
489 	if (g_qdf_trace_data.num > MAX_QDF_TRACE_RECORDS)
490 		g_qdf_trace_data.num = MAX_QDF_TRACE_RECORDS;
491 
492 	if (INVALID_QDF_TRACE_ADDR == g_qdf_trace_data.head) {
493 		/* first record */
494 		g_qdf_trace_data.head = 0;
495 		g_qdf_trace_data.tail = 0;
496 	} else {
497 		/* queue is not empty */
498 		uint32_t tail = g_qdf_trace_data.tail + 1;
499 
500 		if (MAX_QDF_TRACE_RECORDS == tail)
501 			tail = 0;
502 
503 		if (g_qdf_trace_data.head == tail) {
504 			/* full */
505 			if (MAX_QDF_TRACE_RECORDS == ++g_qdf_trace_data.head)
506 				g_qdf_trace_data.head = 0;
507 		}
508 		g_qdf_trace_data.tail = tail;
509 	}
510 
511 	rec = &g_qdf_trace_tbl[g_qdf_trace_data.tail];
512 	rec->code = code;
513 	rec->session = session;
514 	rec->data = data;
515 	rec->qtime = qdf_get_log_timestamp();
516 	scnprintf(rec->time, sizeof(rec->time), "%s", time);
517 	rec->module = module;
518 	rec->pid = (in_interrupt() ? 0 : current->pid);
519 	g_qdf_trace_data.num_since_last_dump++;
520 	spin_unlock_irqrestore(&ltrace_lock, flags);
521 }
522 EXPORT_SYMBOL(qdf_trace);
523 
524 #endif
525 
526 /**
527  * qdf_trace_spin_lock_init() - initializes the lock variable before use
528  *
529  * This function will be called from cds_alloc_global_context, we will have lock
530  * available to use ASAP
531  *
532  * Return: None
533  */
534 QDF_STATUS qdf_trace_spin_lock_init(void)
535 {
536 	spin_lock_init(&ltrace_lock);
537 
538 	return QDF_STATUS_SUCCESS;
539 }
540 EXPORT_SYMBOL(qdf_trace_spin_lock_init);
541 
542 /**
543  * qdf_trace_register() - registers the call back functions
544  * @module_iD: enum value of module
545  * @qdf_trace_callback: call back functions to display the messages in
546  * particular format.
547  *
548  * Registers the call back functions to display the messages in particular
549  * format mentioned in these call back functions. This functions should be
550  * called by interested module in their init part as we will be ready to
551  * register as soon as modules are up.
552  *
553  * Return: None
554  */
555 void qdf_trace_register(QDF_MODULE_ID module_iD,
556 			tp_qdf_trace_cb qdf_trace_callback)
557 {
558 	qdf_trace_cb_table[module_iD] = qdf_trace_callback;
559 }
560 EXPORT_SYMBOL(qdf_trace_register);
561 
562 /**
563  * qdf_trace_dump_all() - Dump data from ring buffer via call back functions
564  * registered with QDF
565  * @p_mac: Context of particular module
566  * @code: Reason code
567  * @session: Session id of log
568  * @count: Number of lines to dump starting from tail to head
569  *
570  * This function will be called up on issueing ioctl call as mentioned following
571  * [iwpriv wlan0 dumplog 0 0 <n> <bitmask_of_module>]
572  *
573  * <n> - number lines to dump starting from tail to head.
574  *
575  * <bitmask_of_module> - if anybody wants to know how many messages were
576  * recorded for particular module/s mentioned by setbit in bitmask from last
577  * <n> messages. It is optional, if you don't provide then it will dump
578  * everything from buffer.
579  *
580  * Return: None
581  */
582 void qdf_trace_dump_all(void *p_mac, uint8_t code, uint8_t session,
583 	uint32_t count, uint32_t bitmask_of_module)
584 {
585 	qdf_trace_record_t p_record;
586 	int32_t i, tail;
587 
588 	if (!g_qdf_trace_data.enable) {
589 		QDF_TRACE(QDF_MODULE_ID_SYS,
590 			  QDF_TRACE_LEVEL_ERROR, "Tracing Disabled");
591 		return;
592 	}
593 
594 	QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_INFO,
595 		  "DPT: Total Records: %d, Head: %d, Tail: %d",
596 		  g_qdf_trace_data.num, g_qdf_trace_data.head,
597 		  g_qdf_trace_data.tail);
598 
599 	/* aquire the lock so that only one thread at a time can read
600 	 * the ring buffer
601 	 */
602 	spin_lock(&ltrace_lock);
603 
604 	if (g_qdf_trace_data.head != INVALID_QDF_TRACE_ADDR) {
605 		i = g_qdf_trace_data.head;
606 		tail = g_qdf_trace_data.tail;
607 
608 		if (count) {
609 			if (count > g_qdf_trace_data.num)
610 				count = g_qdf_trace_data.num;
611 			if (tail >= (count - 1))
612 				i = tail - count + 1;
613 			else if (count != MAX_QDF_TRACE_RECORDS)
614 				i = MAX_QDF_TRACE_RECORDS - ((count - 1) -
615 							     tail);
616 		}
617 
618 		p_record = g_qdf_trace_tbl[i];
619 		/* right now we are not using num_since_last_dump member but
620 		 * in future we might re-visit and use this member to track
621 		 * how many latest messages got added while we were dumping
622 		 * from ring buffer
623 		 */
624 		g_qdf_trace_data.num_since_last_dump = 0;
625 		spin_unlock(&ltrace_lock);
626 		for (;; ) {
627 			if ((code == 0 || (code == p_record.code)) &&
628 			    (qdf_trace_cb_table[p_record.module] != NULL)) {
629 				if (0 == bitmask_of_module) {
630 					qdf_trace_cb_table[p_record.
631 							   module] (p_mac,
632 								    &p_record,
633 								    (uint16_t)
634 								    i);
635 				} else {
636 					if (bitmask_of_module &
637 					    (1 << p_record.module)) {
638 						qdf_trace_cb_table[p_record.
639 								   module]
640 							(p_mac, &p_record,
641 							(uint16_t) i);
642 					}
643 				}
644 			}
645 
646 			if (i == tail)
647 				break;
648 			i += 1;
649 
650 			spin_lock(&ltrace_lock);
651 			if (MAX_QDF_TRACE_RECORDS == i) {
652 				i = 0;
653 				p_record = g_qdf_trace_tbl[0];
654 			} else {
655 				p_record = g_qdf_trace_tbl[i];
656 			}
657 			spin_unlock(&ltrace_lock);
658 		}
659 	} else {
660 		spin_unlock(&ltrace_lock);
661 	}
662 }
663 EXPORT_SYMBOL(qdf_trace_dump_all);
664 
665 /**
666  * qdf_register_debugcb_init() - initializes debug callbacks
667  * to NULL
668  *
669  * Return: None
670  */
671 void qdf_register_debugcb_init(void)
672 {
673 	uint8_t i;
674 
675 	for (i = 0; i < QDF_MODULE_ID_MAX; i++)
676 		qdf_state_info_table[i] = NULL;
677 }
678 EXPORT_SYMBOL(qdf_register_debugcb_init);
679 
680 /**
681  * qdf_register_debug_callback() - stores callback handlers to print
682  * state information
683  * @module_id: module id of layer
684  * @qdf_state_infocb: callback to be registered
685  *
686  * This function is used to store callback handlers to print
687  * state information
688  *
689  * Return: None
690  */
691 void qdf_register_debug_callback(QDF_MODULE_ID module_id,
692 					tp_qdf_state_info_cb qdf_state_infocb)
693 {
694 	qdf_state_info_table[module_id] = qdf_state_infocb;
695 }
696 EXPORT_SYMBOL(qdf_register_debug_callback);
697 
698 /**
699  * qdf_state_info_dump_all() - it invokes callback of layer which registered
700  * its callback to print its state information.
701  * @buf:  buffer pointer to be passed
702  * @size:  size of buffer to be filled
703  * @driver_dump_size: actual size of buffer used
704  *
705  * Return: QDF_STATUS_SUCCESS on success
706  */
707 QDF_STATUS qdf_state_info_dump_all(char *buf, uint16_t size,
708 			uint16_t *driver_dump_size)
709 {
710 	uint8_t module, ret = QDF_STATUS_SUCCESS;
711 	uint16_t buf_len = size;
712 	char *buf_ptr = buf;
713 
714 	for (module = 0; module < QDF_MODULE_ID_MAX; module++) {
715 		if (NULL != qdf_state_info_table[module]) {
716 			qdf_state_info_table[module](&buf_ptr, &buf_len);
717 			if (!buf_len) {
718 				ret = QDF_STATUS_E_NOMEM;
719 				break;
720 			}
721 		}
722 	}
723 
724 	*driver_dump_size = size - buf_len;
725 	return ret;
726 }
727 EXPORT_SYMBOL(qdf_state_info_dump_all);
728 
729 #ifdef CONFIG_DP_TRACE
730 static void qdf_dp_unused(struct qdf_dp_trace_record_s *record,
731 			  uint16_t index, uint8_t pdev_id, bool live)
732 {
733 	qdf_print("%s: QDF_DP_TRACE_MAX event should not be generated",
734 		  __func__);
735 }
736 
737 /**
738  * qdf_dp_trace_init() - enables the DP trace
739  * @live_mode_config: live mode configuration
740  * @thresh: high throughput threshold for disabling live mode
741  * @thresh_time_limit: max time to wait before deciding if thresh is crossed
742  * @verbosity: dptrace verbosity level
743  * @proto_bitmap: bitmap to enable/disable specific protocols
744  *
745  * Called during driver load to init dptrace
746  *
747  * A brief note on the 'thresh' param -
748  * Total # of packets received in a bandwidth timer interval beyond which
749  * DP Trace logging for data packets (including ICMP) will be disabled.
750  * In memory logging will still continue for these packets. Other packets for
751  * which proto.bitmap is set will continue to be recorded in logs and in memory.
752 
753  * Return: None
754  */
755 void qdf_dp_trace_init(bool live_mode_config, uint8_t thresh,
756 				uint16_t time_limit, uint8_t verbosity,
757 				uint8_t proto_bitmap)
758 {
759 	uint8_t i;
760 
761 	qdf_dp_trace_spin_lock_init();
762 	qdf_dp_trace_clear_buffer();
763 	g_qdf_dp_trace_data.enable = true;
764 	g_qdf_dp_trace_data.no_of_record = 1;
765 
766 	g_qdf_dp_trace_data.live_mode_config = live_mode_config;
767 	g_qdf_dp_trace_data.live_mode = live_mode_config;
768 	g_qdf_dp_trace_data.high_tput_thresh = thresh;
769 	g_qdf_dp_trace_data.thresh_time_limit = time_limit;
770 	g_qdf_dp_trace_data.proto_bitmap = proto_bitmap;
771 	g_qdf_dp_trace_data.verbosity = verbosity;
772 
773 	for (i = 0; i < ARRAY_SIZE(qdf_dp_trace_cb_table); i++)
774 		qdf_dp_trace_cb_table[i] = qdf_dp_display_record;
775 
776 	qdf_dp_trace_cb_table[QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD] =
777 	qdf_dp_trace_cb_table[QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD] =
778 	qdf_dp_trace_cb_table[QDF_DP_TRACE_FREE_PACKET_PTR_RECORD] =
779 						qdf_dp_display_ptr_record;
780 	qdf_dp_trace_cb_table[QDF_DP_TRACE_EAPOL_PACKET_RECORD] =
781 	qdf_dp_trace_cb_table[QDF_DP_TRACE_DHCP_PACKET_RECORD] =
782 	qdf_dp_trace_cb_table[QDF_DP_TRACE_ARP_PACKET_RECORD] =
783 	qdf_dp_trace_cb_table[QDF_DP_TRACE_ICMP_PACKET_RECORD] =
784 						qdf_dp_display_proto_pkt;
785 	qdf_dp_trace_cb_table[QDF_DP_TRACE_MGMT_PACKET_RECORD] =
786 					qdf_dp_display_mgmt_pkt;
787 	qdf_dp_trace_cb_table[QDF_DP_TRACE_EVENT_RECORD] =
788 					qdf_dp_display_event_record;
789 
790 	qdf_dp_trace_cb_table[QDF_DP_TRACE_MAX] = qdf_dp_unused;
791 }
792 EXPORT_SYMBOL(qdf_dp_trace_init);
793 
794 /**
795  * qdf_dp_trace_set_value() - Configure the value to control DP trace
796  * @proto_bitmap: defines the protocol to be tracked
797  * @no_of_records: defines the nth packet which is traced
798  * @verbosity: defines the verbosity level
799  *
800  * Return: None
801  */
802 void qdf_dp_trace_set_value(uint8_t proto_bitmap, uint8_t no_of_record,
803 			    uint8_t verbosity)
804 {
805 	g_qdf_dp_trace_data.proto_bitmap = proto_bitmap;
806 	g_qdf_dp_trace_data.no_of_record = no_of_record;
807 	g_qdf_dp_trace_data.verbosity    = verbosity;
808 }
809 EXPORT_SYMBOL(qdf_dp_trace_set_value);
810 
811 /**
812  * qdf_dp_trace_set_verbosity() - set verbosity value
813  *
814  * @val: Value to set
815  *
816  * Return: Null
817  */
818 void qdf_dp_trace_set_verbosity(uint32_t val)
819 {
820 	g_qdf_dp_trace_data.verbosity = val;
821 }
822 EXPORT_SYMBOL(qdf_dp_trace_set_verbosity);
823 
824 /**
825  * qdf_dp_get_verbosity) - get verbosity value
826  *
827  * Return: int
828  */
829 uint8_t qdf_dp_get_verbosity(void)
830 {
831 	return g_qdf_dp_trace_data.verbosity;
832 }
833 EXPORT_SYMBOL(qdf_dp_get_verbosity);
834 
835 /**
836  * qdf_dp_set_proto_bitmap() - set dp trace proto bitmap
837  *
838  * @val         : unsigned bitmap to set
839  *
840  * Return: proto bitmap
841  */
842 void qdf_dp_set_proto_bitmap(uint32_t val)
843 {
844 	g_qdf_dp_trace_data.proto_bitmap = val;
845 }
846 EXPORT_SYMBOL(qdf_dp_set_proto_bitmap);
847 
848 /**
849  * qdf_dp_set_no_of_record() - set dp trace no_of_record
850  *
851  * @val         : unsigned no_of_record to set
852  *
853  * Return: null
854  */
855 void qdf_dp_set_no_of_record(uint32_t val)
856 {
857 	g_qdf_dp_trace_data.no_of_record = val;
858 }
859 EXPORT_SYMBOL(qdf_dp_set_no_of_record);
860 
861 /**
862  * qdf_dp_get_no_of_record() - get dp trace no_of_record
863  *
864  * Return: number of records
865  */
866 uint8_t qdf_dp_get_no_of_record(void)
867 {
868 	return g_qdf_dp_trace_data.no_of_record;
869 }
870 EXPORT_SYMBOL(qdf_dp_get_no_of_record);
871 
872 
873 /**
874  * qdf_dp_trace_enable_track() - enable the tracing for netbuf
875  * @code: defines the event
876  *
877  * In High verbosity all codes are logged.
878  * For Med/Low and Default case code which has
879  * less value than corresponding verbosity codes
880  * are logged.
881  *
882  * Return: true or false depends on whether tracing enabled
883  */
884 static bool qdf_dp_trace_enable_track(enum QDF_DP_TRACE_ID code)
885 {
886 	switch (g_qdf_dp_trace_data.verbosity) {
887 	case QDF_DP_TRACE_VERBOSITY_HIGH:
888 		return true;
889 	case QDF_DP_TRACE_VERBOSITY_MEDIUM:
890 		if (code <= QDF_DP_TRACE_MED_VERBOSITY)
891 			return true;
892 		return false;
893 	case QDF_DP_TRACE_VERBOSITY_LOW:
894 		if (code <= QDF_DP_TRACE_LOW_VERBOSITY)
895 			return true;
896 		return false;
897 	case QDF_DP_TRACE_VERBOSITY_BASE:
898 		if (code <= QDF_DP_TRACE_BASE_VERBOSITY)
899 			return true;
900 		return false;
901 	default:
902 		return false;
903 	}
904 }
905 EXPORT_SYMBOL(qdf_dp_trace_enable_track);
906 
907 /**
908  * qdf_dp_get_proto_bitmap() - get dp trace proto bitmap
909  *
910  * Return: proto bitmap
911  */
912 uint8_t qdf_dp_get_proto_bitmap(void)
913 {
914 	if (g_qdf_dp_trace_data.enable)
915 		return g_qdf_dp_trace_data.proto_bitmap;
916 	else
917 		return 0;
918 }
919 
920 /**
921  * qdf_dp_trace_set_track() - Marks whether the packet needs to be traced
922  * @nbuf: defines the netbuf
923  * @dir: direction
924  *
925  * Return: None
926  */
927 void qdf_dp_trace_set_track(qdf_nbuf_t nbuf, enum qdf_proto_dir dir)
928 {
929 	uint32_t count = 0;
930 
931 	if (!g_qdf_dp_trace_data.enable)
932 		return;
933 
934 	spin_lock_bh(&l_dp_trace_lock);
935 	if (QDF_TX == dir)
936 		count = ++g_qdf_dp_trace_data.tx_count;
937 	else if (QDF_RX == dir)
938 		count = ++g_qdf_dp_trace_data.rx_count;
939 
940 	if ((g_qdf_dp_trace_data.no_of_record != 0) &&
941 		(count % g_qdf_dp_trace_data.no_of_record == 0)) {
942 		if (QDF_TX == dir)
943 			QDF_NBUF_CB_TX_DP_TRACE(nbuf) = 1;
944 		else if (QDF_RX == dir)
945 			QDF_NBUF_CB_RX_DP_TRACE(nbuf) = 1;
946 	}
947 	spin_unlock_bh(&l_dp_trace_lock);
948 }
949 EXPORT_SYMBOL(qdf_dp_trace_set_track);
950 
951 #define DPTRACE_PRINT(args...) \
952 	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, ## args)
953 
954 /**
955  * dump_hex_trace() - Display the data in buffer
956  * @str:     string to prepend the hexdump with.
957  * @buf:     buffer which contains data to be displayed
958  * @buf_len: defines the size of the data to be displayed
959  *
960  * Return: None
961  */
962 static void dump_dp_hex_trace(char *str, uint8_t *buf, uint8_t buf_len)
963 {
964 	unsigned char linebuf[BUFFER_SIZE];
965 	const u8 *ptr = buf;
966 	int i, linelen, remaining = buf_len;
967 
968 	/* Dump the bytes in the last line */
969 	for (i = 0; i < buf_len; i += ROW_SIZE) {
970 		linelen = min(remaining, ROW_SIZE);
971 		remaining -= ROW_SIZE;
972 
973 		hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1,
974 				linebuf, sizeof(linebuf), false);
975 
976 		DPTRACE_PRINT("DPT: %s %s", str, linebuf);
977 	}
978 }
979 
980 /**
981  * qdf_dp_code_to_string() - convert dptrace code to string
982  * @code: dptrace code
983  *
984  * Return: string version of code
985  */
986 static
987 const char *qdf_dp_code_to_string(enum QDF_DP_TRACE_ID code)
988 {
989 	switch (code) {
990 	case QDF_DP_TRACE_DROP_PACKET_RECORD:
991 		return "DROP:";
992 	case QDF_DP_TRACE_EAPOL_PACKET_RECORD:
993 		return "EAPOL:";
994 	case QDF_DP_TRACE_DHCP_PACKET_RECORD:
995 		return "DHCP:";
996 	case QDF_DP_TRACE_ARP_PACKET_RECORD:
997 		return "ARP:";
998 	case QDF_DP_TRACE_ICMP_PACKET_RECORD:
999 		return "ICMP:";
1000 	case QDF_DP_TRACE_MGMT_PACKET_RECORD:
1001 		return "MGMT:";
1002 	case QDF_DP_TRACE_EVENT_RECORD:
1003 		return "EVENT:";
1004 	case QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD:
1005 		return "HDD: TX: PTR:";
1006 	case QDF_DP_TRACE_LI_DP_TX_PACKET_PTR_RECORD:
1007 		return "LI_DP: TX: PTR:";
1008 	case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
1009 		return "HDD: TX: DATA:";
1010 	case QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD:
1011 		return "LI_DP: TX: DATA:";
1012 	case QDF_DP_TRACE_CE_PACKET_PTR_RECORD:
1013 		return "CE: TX: PTR:";
1014 	case QDF_DP_TRACE_CE_FAST_PACKET_PTR_RECORD:
1015 		return "CE: TX: FAST: PTR:";
1016 	case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD:
1017 		return "FREE: TX: PTR:";
1018 	case QDF_DP_TRACE_RX_HTT_PACKET_PTR_RECORD:
1019 		return "HTT: RX: PTR:";
1020 	case QDF_DP_TRACE_RX_OFFLOAD_HTT_PACKET_PTR_RECORD:
1021 		return "HTT: RX: OF: PTR:";
1022 	case QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD:
1023 		return "HDD: RX: PTR:";
1024 	case QDF_DP_TRACE_RX_LI_DP_PACKET_PTR_RECORD:
1025 		return "LI_DP: RX: PTR:";
1026 	case QDF_DP_TRACE_HDD_RX_PACKET_RECORD:
1027 		return "HDD: RX: DATA:";
1028 	case QDF_DP_TRACE_LI_DP_RX_PACKET_RECORD:
1029 		return "LI_DP: RX: DATA:";
1030 	case QDF_DP_TRACE_LI_DP_NULL_RX_PACKET_RECORD:
1031 		return "LI_DP_NULL: RX: DATA:";
1032 	case QDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD:
1033 		return "TXRX: TX: Q: PTR:";
1034 	case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD:
1035 		return "TXRX: TX: PTR:";
1036 	case QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD:
1037 		return "TXRX: TX: FAST: PTR:";
1038 	case QDF_DP_TRACE_HTT_PACKET_PTR_RECORD:
1039 		return "HTT: TX: PTR:";
1040 	case QDF_DP_TRACE_HTC_PACKET_PTR_RECORD:
1041 		return "HTC: TX: PTR:";
1042 	case QDF_DP_TRACE_HIF_PACKET_PTR_RECORD:
1043 		return "HIF: TX: PTR:";
1044 	case QDF_DP_TRACE_RX_TXRX_PACKET_PTR_RECORD:
1045 		return "TXRX: RX: PTR:";
1046 	case QDF_DP_TRACE_HDD_TX_TIMEOUT:
1047 		return "HDD: STA: TO:";
1048 	case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
1049 		return "HDD: SAP: TO:";
1050 	default:
1051 		return "Invalid";
1052 	}
1053 }
1054 
1055 /**
1056  * qdf_dp_dir_to_str() - convert direction to string
1057  * @dir: direction
1058  *
1059  * Return: string version of direction
1060  */
1061 static const char *qdf_dp_dir_to_str(enum qdf_proto_dir dir)
1062 {
1063 	switch (dir) {
1064 	case QDF_TX:
1065 		return " --> ";
1066 	case QDF_RX:
1067 		return " <-- ";
1068 	default:
1069 		return "invalid";
1070 	}
1071 }
1072 
1073 /**
1074  * qdf_dp_type_to_str() - convert packet type to string
1075  * @type: type
1076  *
1077  * Return: string version of packet type
1078  */
1079 static const char *qdf_dp_type_to_str(enum qdf_proto_type type)
1080 {
1081 	switch (type) {
1082 	case QDF_PROTO_TYPE_DHCP:
1083 		return "DHCP";
1084 	case QDF_PROTO_TYPE_EAPOL:
1085 		return "EAPOL";
1086 	case QDF_PROTO_TYPE_ARP:
1087 		return "ARP";
1088 	case QDF_PROTO_TYPE_ICMP:
1089 		return "ICMP";
1090 	case QDF_PROTO_TYPE_MGMT:
1091 		return "MGMT";
1092 	case QDF_PROTO_TYPE_EVENT:
1093 		return "EVENT";
1094 	default:
1095 		return "invalid";
1096 	}
1097 }
1098 
1099 /**
1100  * qdf_dp_subtype_to_str() - convert packet subtype to string
1101  * @type: type
1102  *
1103  * Return: string version of packet subtype
1104  */
1105 static const char *qdf_dp_subtype_to_str(enum qdf_proto_subtype subtype)
1106 {
1107 	switch (subtype) {
1108 	case QDF_PROTO_EAPOL_M1:
1109 		return "M1";
1110 	case QDF_PROTO_EAPOL_M2:
1111 		return "M2";
1112 	case QDF_PROTO_EAPOL_M3:
1113 		return "M3";
1114 	case QDF_PROTO_EAPOL_M4:
1115 		return "M4";
1116 	case QDF_PROTO_DHCP_DISCOVER:
1117 		return "DISC";
1118 	case QDF_PROTO_DHCP_REQUEST:
1119 		return "REQ";
1120 	case QDF_PROTO_DHCP_OFFER:
1121 		return "OFF";
1122 	case QDF_PROTO_DHCP_ACK:
1123 		return "ACK";
1124 	case QDF_PROTO_DHCP_NACK:
1125 		return "NACK";
1126 	case QDF_PROTO_DHCP_RELEASE:
1127 		return "REL";
1128 	case QDF_PROTO_DHCP_INFORM:
1129 		return "INFORM";
1130 	case QDF_PROTO_DHCP_DECLINE:
1131 		return "DECL";
1132 	case QDF_PROTO_ARP_REQ:
1133 	case QDF_PROTO_ICMP_REQ:
1134 		return "REQ";
1135 	case QDF_PROTO_ARP_RES:
1136 	case QDF_PROTO_ICMP_RES:
1137 		return "RSP";
1138 	case QDF_PROTO_MGMT_ASSOC:
1139 		return "ASSOC";
1140 	case QDF_PROTO_MGMT_DISASSOC:
1141 		return "DISASSOC";
1142 	case QDF_PROTO_MGMT_AUTH:
1143 		return "AUTH";
1144 	case QDF_PROTO_MGMT_DEAUTH:
1145 		return "DEAUTH";
1146 	case QDF_ROAM_SYNCH:
1147 		return "ROAM SYNCH";
1148 	case QDF_ROAM_COMPLETE:
1149 		return "ROAM COMP";
1150 	case QDF_ROAM_EVENTID:
1151 		return "ROAM EVENTID";
1152 	default:
1153 		return "invalid";
1154 	}
1155 }
1156 
1157 /**
1158  * qdf_dp_enable_check() - check if dptrace is enable or not
1159  * @nbuf: nbuf
1160  * @code: dptrace code
1161  *
1162  * Return: true/false
1163  */
1164 static bool qdf_dp_enable_check(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
1165 				enum qdf_proto_dir dir)
1166 {
1167 	/* Return when Dp trace is not enabled */
1168 	if (!g_qdf_dp_trace_data.enable)
1169 		return false;
1170 
1171 	if (qdf_dp_trace_enable_track(code) == false)
1172 		return false;
1173 
1174 	if ((nbuf) && ((QDF_NBUF_CB_TX_PACKET_TRACK(nbuf) !=
1175 		 QDF_NBUF_TX_PKT_DATA_TRACK) ||
1176 		 ((dir == QDF_TX) && (QDF_NBUF_CB_TX_DP_TRACE(nbuf) == 0)) ||
1177 		 ((dir == QDF_RX) && (QDF_NBUF_CB_RX_DP_TRACE(nbuf) == 0))))
1178 		return false;
1179 
1180 	return true;
1181 }
1182 
1183 /**
1184  * qdf_dp_add_record() - add dp trace record
1185  * @code: dptrace code
1186  * @data: data pointer
1187  * @size: size of buffer
1188  * @pdev_id: pdev_id
1189  * @print: true to print it in kmsg
1190  *
1191  * Return: none
1192  */
1193 static void qdf_dp_add_record(enum QDF_DP_TRACE_ID code, uint8_t *data,
1194 			uint8_t size, uint8_t pdev_id, bool print)
1195 {
1196 	struct qdf_dp_trace_record_s *rec = NULL;
1197 	int index;
1198 
1199 	spin_lock_bh(&l_dp_trace_lock);
1200 
1201 	g_qdf_dp_trace_data.num++;
1202 
1203 	if (g_qdf_dp_trace_data.num > MAX_QDF_DP_TRACE_RECORDS)
1204 		g_qdf_dp_trace_data.num = MAX_QDF_DP_TRACE_RECORDS;
1205 
1206 	if (INVALID_QDF_DP_TRACE_ADDR == g_qdf_dp_trace_data.head) {
1207 		/* first record */
1208 		g_qdf_dp_trace_data.head = 0;
1209 		g_qdf_dp_trace_data.tail = 0;
1210 	} else {
1211 		/* queue is not empty */
1212 		g_qdf_dp_trace_data.tail++;
1213 
1214 		if (MAX_QDF_DP_TRACE_RECORDS == g_qdf_dp_trace_data.tail)
1215 			g_qdf_dp_trace_data.tail = 0;
1216 
1217 		if (g_qdf_dp_trace_data.head == g_qdf_dp_trace_data.tail) {
1218 			/* full */
1219 			if (MAX_QDF_DP_TRACE_RECORDS ==
1220 				++g_qdf_dp_trace_data.head)
1221 				g_qdf_dp_trace_data.head = 0;
1222 		}
1223 	}
1224 
1225 	rec = &g_qdf_dp_trace_tbl[g_qdf_dp_trace_data.tail];
1226 	index = g_qdf_dp_trace_data.tail;
1227 	rec->code = code;
1228 	rec->pdev_id = pdev_id;
1229 	rec->size = 0;
1230 	if (data != NULL && size > 0) {
1231 		if (size > QDF_DP_TRACE_RECORD_SIZE)
1232 			size = QDF_DP_TRACE_RECORD_SIZE;
1233 
1234 		rec->size = size;
1235 		qdf_mem_copy(rec->data, data, size);
1236 	}
1237 	qdf_get_time_of_the_day_in_hr_min_sec_usec(rec->time,
1238 						   sizeof(rec->time));
1239 	rec->pid = (in_interrupt() ? 0 : current->pid);
1240 	spin_unlock_bh(&l_dp_trace_lock);
1241 
1242 
1243 	if (rec->code >= QDF_DP_TRACE_MAX) {
1244 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
1245 			"invalid record code %u, max code %u", rec->code,
1246 			QDF_DP_TRACE_MAX);
1247 		return;
1248 	}
1249 
1250 	if (print == true) {
1251 		qdf_dp_trace_cb_table[rec->code] (rec, index,
1252 					QDF_TRACE_DEFAULT_PDEV_ID, true);
1253 		return;
1254 	}
1255 
1256 	if (g_qdf_dp_trace_data.live_mode_config) {
1257 		spin_lock_bh(&l_dp_trace_lock);
1258 		g_qdf_dp_trace_data.print_pkt_cnt++;
1259 		if ((g_qdf_dp_trace_data.live_mode == 1) &&
1260 			(g_qdf_dp_trace_data.print_pkt_cnt >
1261 				g_qdf_dp_trace_data.high_tput_thresh))
1262 			g_qdf_dp_trace_data.live_mode = 0;
1263 		spin_unlock_bh(&l_dp_trace_lock);
1264 	}
1265 
1266 	if (g_qdf_dp_trace_data.live_mode == true) {
1267 		qdf_dp_trace_cb_table[rec->code] (rec, index,
1268 					QDF_TRACE_DEFAULT_PDEV_ID, true);
1269 		return;
1270 	}
1271 }
1272 
1273 
1274 /**
1275  * qdf_log_icmp_pkt() - log ICMP packet
1276  * @session_id: vdev_id
1277  * @skb: skb pointer
1278  * @dir: direction
1279  *
1280  * Return: true/false
1281  */
1282 static bool qdf_log_icmp_pkt(uint8_t session_id, struct sk_buff *skb,
1283 			    enum qdf_proto_dir dir, uint8_t pdev_id)
1284 {
1285 	enum qdf_proto_subtype proto_subtype;
1286 
1287 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMP) &&
1288 	    (qdf_nbuf_is_icmp_pkt(skb) == true)) {
1289 
1290 		proto_subtype = qdf_nbuf_get_icmp_subtype(skb);
1291 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ICMP_PACKET_RECORD,
1292 			session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
1293 			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
1294 			QDF_PROTO_TYPE_ICMP, proto_subtype, dir, pdev_id, false));
1295 		if (QDF_TX == dir)
1296 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1297 		else if (QDF_RX == dir)
1298 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1299 
1300 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false;
1301 
1302 		if (proto_subtype == QDF_PROTO_ICMP_REQ)
1303 			g_qdf_dp_trace_data.icmp_req++;
1304 		else
1305 			g_qdf_dp_trace_data.icmp_resp++;
1306 
1307 		return true;
1308 	}
1309 	return false;
1310 }
1311 
1312 /**
1313  * qdf_log_eapol_pkt() - log EAPOL packet
1314  * @session_id: vdev_id
1315  * @skb: skb pointer
1316  * @dir: direction
1317  * @pdev_id: pdev_id
1318  *
1319  * Return: true/false
1320  */
1321 static bool qdf_log_eapol_pkt(uint8_t session_id, struct sk_buff *skb,
1322 			      enum qdf_proto_dir dir, uint8_t pdev_id)
1323 {
1324 	enum qdf_proto_subtype subtype;
1325 
1326 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_EAPOL) &&
1327 		((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_EAPOL ==
1328 			QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1329 		 (dir == QDF_RX && qdf_nbuf_is_ipv4_eapol_pkt(skb) == true))) {
1330 
1331 		subtype = qdf_nbuf_get_eapol_subtype(skb);
1332 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_EAPOL_PACKET_RECORD,
1333 			session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
1334 			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
1335 			QDF_PROTO_TYPE_EAPOL, subtype, dir, pdev_id, true));
1336 		if (QDF_TX == dir)
1337 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1338 		else if (QDF_RX == dir)
1339 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1340 
1341 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
1342 		return true;
1343 	}
1344 	return false;
1345 }
1346 
1347 /**
1348  * qdf_log_dhcp_pkt() - log DHCP packet
1349  * @session_id: vdev_id
1350  * @skb: skb pointer
1351  * @dir: direction
1352  * @pdev_id: pdev_id
1353  *
1354  * Return: true/false
1355  */
1356 static bool qdf_log_dhcp_pkt(uint8_t session_id, struct sk_buff *skb,
1357 			     enum qdf_proto_dir dir, uint8_t pdev_id)
1358 {
1359 	enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
1360 
1361 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_DHCP) &&
1362 		((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_DHCP ==
1363 				QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1364 		 (dir == QDF_RX && qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true))) {
1365 
1366 		subtype = qdf_nbuf_get_dhcp_subtype(skb);
1367 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_DHCP_PACKET_RECORD,
1368 			session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
1369 			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
1370 			QDF_PROTO_TYPE_DHCP, subtype, dir, pdev_id, true));
1371 
1372 		if (QDF_TX == dir)
1373 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1374 		else if (QDF_RX == dir)
1375 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1376 
1377 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
1378 		return true;
1379 	}
1380 	return false;
1381 }
1382 
1383 /**
1384  * qdf_log_arp_pkt() - log ARP packet
1385  * @session_id: vdev_id
1386  * @skb: skb pointer
1387  * @dir: direction
1388  * @pdev_id: pdev_id
1389  *
1390  * Return: true/false
1391  */
1392 static bool qdf_log_arp_pkt(uint8_t session_id, struct sk_buff *skb,
1393 			    enum qdf_proto_dir dir, uint8_t pdev_id)
1394 {
1395 	enum qdf_proto_subtype proto_subtype;
1396 
1397 	if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ARP) &&
1398 		((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ARP ==
1399 			QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1400 		 (dir == QDF_RX && qdf_nbuf_is_ipv4_arp_pkt(skb) == true))) {
1401 
1402 		proto_subtype = qdf_nbuf_get_arp_subtype(skb);
1403 		DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ARP_PACKET_RECORD,
1404 			session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
1405 			(skb->data + QDF_NBUF_DEST_MAC_OFFSET),
1406 			QDF_PROTO_TYPE_ARP, proto_subtype, dir, pdev_id, true));
1407 		if (QDF_TX == dir)
1408 			QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1409 		else if (QDF_RX == dir)
1410 			QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1411 
1412 		QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
1413 
1414 		if (QDF_PROTO_ARP_REQ == proto_subtype)
1415 			g_qdf_dp_trace_data.arp_req++;
1416 		else
1417 			g_qdf_dp_trace_data.arp_resp++;
1418 
1419 		return true;
1420 	}
1421 	return false;
1422 }
1423 
1424 
1425 /**
1426  * qdf_dp_trace_log_pkt() - log packet type enabled through iwpriv
1427  * @session_id: vdev_id
1428  * @skb: skb pointer
1429  * @dir: direction
1430  * @pdev_id: pdev_id
1431  *
1432  * Return: true: some protocol was logged, false: no protocol was logged.
1433  */
1434 bool qdf_dp_trace_log_pkt(uint8_t session_id, struct sk_buff *skb,
1435 			  enum qdf_proto_dir dir, uint8_t pdev_id)
1436 {
1437 	if (!qdf_dp_get_proto_bitmap())
1438 		return false;
1439 	if (qdf_log_arp_pkt(session_id, skb, dir, pdev_id))
1440 		return true;
1441 	if (qdf_log_dhcp_pkt(session_id, skb, dir, pdev_id))
1442 		return true;
1443 	if (qdf_log_eapol_pkt(session_id, skb, dir, pdev_id))
1444 		return true;
1445 	if (qdf_log_icmp_pkt(session_id, skb, dir, pdev_id))
1446 		return true;
1447 	return false;
1448 }
1449 EXPORT_SYMBOL(qdf_dp_trace_log_pkt);
1450 
1451 /**
1452  * qdf_dp_display_mgmt_pkt() - display proto packet
1453  * @record: dptrace record
1454  * @index: index
1455  * @live : live mode or dump mode
1456  *
1457  * Return: none
1458  */
1459 void qdf_dp_display_mgmt_pkt(struct qdf_dp_trace_record_s *record,
1460 			      uint16_t index, uint8_t pdev_id, bool live)
1461 {
1462 	struct qdf_dp_trace_mgmt_buf *buf =
1463 		(struct qdf_dp_trace_mgmt_buf *)record->data;
1464 
1465 	DPTRACE_PRINT("DPT: %04d: %s [%d] [%s %s %s]",
1466 		index,
1467 		(live == true) ? " " : record->time,
1468 		buf->vdev_id,
1469 		qdf_dp_code_to_string(record->code),
1470 		qdf_dp_type_to_str(buf->type),
1471 		qdf_dp_subtype_to_str(buf->subtype));
1472 }
1473 EXPORT_SYMBOL(qdf_dp_display_mgmt_pkt);
1474 
1475 /**
1476  * qdf_dp_trace_mgmt_pkt() - record mgmt packet
1477  * @code: dptrace code
1478  * @vdev_id: vdev id
1479  * @pdev_id: pdev_id
1480  * @type: proto type
1481  * @subtype: proto subtype
1482  *
1483  * Return: none
1484  */
1485 void qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
1486 		uint8_t pdev_id, enum qdf_proto_type type,
1487 		enum qdf_proto_subtype subtype)
1488 {
1489 	struct qdf_dp_trace_mgmt_buf buf;
1490 	int buf_size = sizeof(struct qdf_dp_trace_mgmt_buf);
1491 
1492 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
1493 		return;
1494 
1495 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
1496 		QDF_BUG(0);
1497 
1498 	buf.type = type;
1499 	buf.subtype = subtype;
1500 	buf.vdev_id = vdev_id;
1501 	qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, pdev_id, true);
1502 }
1503 EXPORT_SYMBOL(qdf_dp_trace_mgmt_pkt);
1504 
1505 /**
1506  * qdf_dp_display_event_record() - display event records
1507  * @record: dptrace record
1508  * @index: index
1509  * @live : live mode or dump mode
1510  *
1511  * Return: none
1512  */
1513 void qdf_dp_display_event_record(struct qdf_dp_trace_record_s *record,
1514 			      uint16_t index, uint8_t pdev_id, bool live)
1515 {
1516 	struct qdf_dp_trace_event_buf *buf =
1517 		(struct qdf_dp_trace_event_buf *)record->data;
1518 
1519 	DPTRACE_PRINT("DPT: %04d: %s [%d] [%s %s %s]",
1520 		index,
1521 		(live == true) ? "" : record->time,
1522 		buf->vdev_id,
1523 		qdf_dp_code_to_string(record->code),
1524 		qdf_dp_type_to_str(buf->type),
1525 		qdf_dp_subtype_to_str(buf->subtype));
1526 }
1527 EXPORT_SYMBOL(qdf_dp_display_event_record);
1528 
1529 /**
1530  * qdf_dp_trace_record_event() - record events
1531  * @code: dptrace code
1532  * @vdev_id: vdev id
1533  * @pdev_id: pdev_id
1534  * @type: proto type
1535  * @subtype: proto subtype
1536  *
1537  * Return: none
1538  */
1539 void qdf_dp_trace_record_event(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
1540 		uint8_t pdev_id, enum qdf_proto_type type,
1541 		enum qdf_proto_subtype subtype)
1542 {
1543 	struct qdf_dp_trace_event_buf buf;
1544 	int buf_size = sizeof(struct qdf_dp_trace_event_buf);
1545 
1546 	if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
1547 		return;
1548 
1549 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
1550 		QDF_BUG(0);
1551 
1552 	buf.type = type;
1553 	buf.subtype = subtype;
1554 	buf.vdev_id = vdev_id;
1555 	qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, pdev_id, true);
1556 }
1557 EXPORT_SYMBOL(qdf_dp_trace_record_event);
1558 
1559 /**
1560  * qdf_dp_display_proto_pkt() - display proto packet
1561  * @record: dptrace record
1562  * @index: index
1563  * @live : live mode or dump mode
1564  *
1565  * Return: none
1566  */
1567 void qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s *record,
1568 			      uint16_t index, uint8_t pdev_id, bool live)
1569 {
1570 	struct qdf_dp_trace_proto_buf *buf =
1571 		(struct qdf_dp_trace_proto_buf *)record->data;
1572 
1573 	DPTRACE_PRINT("DPT: %04d: %s [%d] [%s%s] SA: "
1574 		QDF_MAC_ADDRESS_STR " %s DA: "
1575 		QDF_MAC_ADDRESS_STR,
1576 		index,
1577 		(live == true) ? "" : record->time,
1578 		buf->vdev_id,
1579 		qdf_dp_code_to_string(record->code),
1580 		qdf_dp_subtype_to_str(buf->subtype),
1581 		QDF_MAC_ADDR_ARRAY(buf->sa.bytes),
1582 		qdf_dp_dir_to_str(buf->dir), QDF_MAC_ADDR_ARRAY(buf->da.bytes));
1583 }
1584 EXPORT_SYMBOL(qdf_dp_display_proto_pkt);
1585 
1586 /**
1587  * qdf_dp_trace_proto_pkt() - record proto packet
1588  * @code: dptrace code
1589  * @vdev_id: vdev id
1590  * @sa: source mac address
1591  * @da: destination mac address
1592  * @type: proto type
1593  * @subtype: proto subtype
1594  * @dir: direction
1595  * @pdev_id: pdev id
1596  * @print: to print this proto pkt or not
1597  *
1598  * Return: none
1599  */
1600 void qdf_dp_trace_proto_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
1601 		uint8_t *sa, uint8_t *da, enum qdf_proto_type type,
1602 		enum qdf_proto_subtype subtype, enum qdf_proto_dir dir,
1603 		uint8_t pdev_id, bool print)
1604 {
1605 	struct qdf_dp_trace_proto_buf buf;
1606 	int buf_size = sizeof(struct qdf_dp_trace_ptr_buf);
1607 
1608 	if (qdf_dp_enable_check(NULL, code, dir) == false)
1609 		return;
1610 
1611 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
1612 		QDF_BUG(0);
1613 
1614 	memcpy(&buf.sa, sa, QDF_NET_ETH_LEN);
1615 	memcpy(&buf.da, da, QDF_NET_ETH_LEN);
1616 	buf.dir = dir;
1617 	buf.type = type;
1618 	buf.subtype = subtype;
1619 	buf.vdev_id = vdev_id;
1620 	qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, pdev_id, print);
1621 }
1622 EXPORT_SYMBOL(qdf_dp_trace_proto_pkt);
1623 
1624 /**
1625  * qdf_dp_display_ptr_record() - display record
1626  * @record: dptrace record
1627  * @index: index
1628  * @live : live mode or dump mode
1629  *
1630  * Return: none
1631  */
1632 void qdf_dp_display_ptr_record(struct qdf_dp_trace_record_s *record,
1633 				uint16_t index, uint8_t pdev_id, bool live)
1634 {
1635 	char prepend_str[100] = {'\0'};
1636 	struct qdf_dp_trace_ptr_buf *buf =
1637 		(struct qdf_dp_trace_ptr_buf *)record->data;
1638 
1639 	snprintf(prepend_str, sizeof(prepend_str),
1640 		"%04d: %s [%s] [msdu id %d %s %d]",
1641 		index,
1642 		(live == true) ? "" : record->time,
1643 		qdf_dp_code_to_string(record->code), buf->msdu_id,
1644 		(record->code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) ?
1645 			"status" : "vdev_id",
1646 		 buf->status);
1647 
1648 	if (live == true) {
1649 		/* In live mode donot dump the contents of the cookie */
1650 		DPTRACE_PRINT("DPT: %s", prepend_str);
1651 	} else {
1652 		dump_dp_hex_trace(prepend_str, (uint8_t *)&buf->cookie,
1653 			sizeof(buf->cookie));
1654 	}
1655 }
1656 EXPORT_SYMBOL(qdf_dp_display_ptr_record);
1657 
1658 /**
1659  * qdf_dp_trace_ptr() - record dptrace
1660  * @code: dptrace code
1661  * @pdev_id: pdev_id
1662  * @data: data
1663  * @size: size of data
1664  * @msdu_id: msdu_id
1665  * @status: return status
1666  *
1667  * Return: none
1668  */
1669 void qdf_dp_trace_ptr(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
1670 		uint8_t pdev_id, uint8_t *data, uint8_t size,
1671 		uint16_t msdu_id, uint16_t status)
1672 {
1673 	struct qdf_dp_trace_ptr_buf buf;
1674 	int buf_size = sizeof(struct qdf_dp_trace_ptr_buf);
1675 
1676 	if (qdf_dp_enable_check(nbuf, code, QDF_TX) == false)
1677 		return;
1678 
1679 	if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
1680 		QDF_BUG(0);
1681 
1682 	qdf_mem_copy(&buf.cookie, data, size);
1683 	buf.msdu_id = msdu_id;
1684 	buf.status = status;
1685 	qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, pdev_id,
1686 				QDF_NBUF_CB_DP_TRACE_PRINT(nbuf));
1687 }
1688 EXPORT_SYMBOL(qdf_dp_trace_ptr);
1689 
1690 /**
1691  * qdf_dp_display_trace() - Displays a record in DP trace
1692  * @pRecord  : pointer to a record in DP trace
1693  * @recIndex : record index
1694  * @live : live mode or dump mode
1695  *
1696  * Return: None
1697  */
1698 void qdf_dp_display_record(struct qdf_dp_trace_record_s *pRecord,
1699 				uint16_t recIndex, uint8_t pdev_id, bool live)
1700 
1701 {
1702 	char prepend_str[50] = {'\0'};
1703 
1704 	if (!(pdev_id == QDF_TRACE_DEFAULT_PDEV_ID ||
1705 		pdev_id == pRecord->pdev_id))
1706 		return;
1707 
1708 	snprintf(prepend_str, sizeof(prepend_str),
1709 		"%04d PDEV_ID = %02d: %s %s",
1710 		recIndex,
1711 		pRecord->pdev_id,
1712 		(live == true) ? "" : pRecord->time,
1713 		qdf_dp_code_to_string(pRecord->code));
1714 
1715 	switch (pRecord->code) {
1716 	case  QDF_DP_TRACE_HDD_TX_TIMEOUT:
1717 		DPTRACE_PRINT(" %s: HDD TX Timeout", prepend_str);
1718 		break;
1719 	case  QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
1720 		DPTRACE_PRINT(" %s: HDD SoftAP TX Timeout", prepend_str);
1721 		break;
1722 	case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
1723 	case QDF_DP_TRACE_HDD_RX_PACKET_RECORD:
1724 	case QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD:
1725 	case QDF_DP_TRACE_LI_DP_RX_PACKET_RECORD:
1726 	case QDF_DP_TRACE_LI_DP_NULL_RX_PACKET_RECORD:
1727 	default:
1728 		dump_dp_hex_trace(prepend_str, pRecord->data, pRecord->size);
1729 		break;
1730 	};
1731 }
1732 EXPORT_SYMBOL(qdf_dp_display_record);
1733 
1734 
1735 /**
1736  * qdf_dp_trace() - Stores the data in buffer
1737  * @nbuf  : defines the netbuf
1738  * @code : defines the event
1739  * @pdev_id: pdev_id
1740  * @data : defines the data to be stored
1741  * @size : defines the size of the data record
1742  *
1743  * Return: None
1744  */
1745 void qdf_dp_trace(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code, uint8_t pdev_id,
1746 	uint8_t *data, uint8_t size, enum qdf_proto_dir dir)
1747 {
1748 
1749 	if (qdf_dp_enable_check(nbuf, code, dir) == false)
1750 		return;
1751 
1752 	qdf_dp_add_record(code, data, size, pdev_id,
1753 		(nbuf != NULL) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false);
1754 }
1755 EXPORT_SYMBOL(qdf_dp_trace);
1756 
1757 /**
1758  * qdf_dp_trace_spin_lock_init() - initializes the lock variable before use
1759  * This function will be called from cds_alloc_global_context, we will have lock
1760  * available to use ASAP
1761  *
1762  * Return: None
1763  */
1764 void qdf_dp_trace_spin_lock_init(void)
1765 {
1766 	spin_lock_init(&l_dp_trace_lock);
1767 }
1768 EXPORT_SYMBOL(qdf_dp_trace_spin_lock_init);
1769 
1770 /**
1771  * qdf_dp_trace_disable_live_mode - disable live mode for dptrace
1772  *
1773  * Return: none
1774  */
1775 void qdf_dp_trace_disable_live_mode(void)
1776 {
1777 	g_qdf_dp_trace_data.live_mode = 0;
1778 }
1779 EXPORT_SYMBOL(qdf_dp_trace_disable_live_mode);
1780 
1781 /**
1782  * qdf_dp_trace_enable_live_mode() - enable live mode for dptrace
1783  *
1784  * Return: none
1785  */
1786 void qdf_dp_trace_enable_live_mode(void)
1787 {
1788 	g_qdf_dp_trace_data.live_mode = 1;
1789 }
1790 EXPORT_SYMBOL(qdf_dp_trace_enable_live_mode);
1791 
1792 /**
1793  * qdf_dp_trace_clear_buffer() - clear dp trace buffer
1794  *
1795  * Return: none
1796  */
1797 void qdf_dp_trace_clear_buffer(void)
1798 {
1799 	g_qdf_dp_trace_data.head = INVALID_QDF_DP_TRACE_ADDR;
1800 	g_qdf_dp_trace_data.tail = INVALID_QDF_DP_TRACE_ADDR;
1801 	g_qdf_dp_trace_data.num = 0;
1802 	memset(g_qdf_dp_trace_tbl, 0,
1803 	   MAX_QDF_DP_TRACE_RECORDS * sizeof(struct qdf_dp_trace_record_s));
1804 }
1805 EXPORT_SYMBOL(qdf_dp_trace_clear_buffer);
1806 
1807 /**
1808  * qdf_dp_trace_dump_all() - Dump data from ring buffer via call back functions
1809  * registered with QDF
1810  * @count: Number of lines to dump starting from tail to head
1811  * @pdev_id: pdev_id
1812  *
1813  * Return: None
1814  */
1815 void qdf_dp_trace_dump_all(uint32_t count, uint8_t pdev_id)
1816 {
1817 	struct qdf_dp_trace_record_s p_record;
1818 	int32_t i, tail;
1819 
1820 	if (!g_qdf_dp_trace_data.enable) {
1821 		DPTRACE_PRINT("Tracing Disabled");
1822 		return;
1823 	}
1824 
1825 	DPTRACE_PRINT(
1826 		"DPT: config - bitmap 0x%x verb %u #rec %u live_config %u thresh %u time_limit %u",
1827 		g_qdf_dp_trace_data.proto_bitmap,
1828 		g_qdf_dp_trace_data.verbosity,
1829 		g_qdf_dp_trace_data.no_of_record,
1830 		g_qdf_dp_trace_data.live_mode_config,
1831 		g_qdf_dp_trace_data.high_tput_thresh,
1832 		g_qdf_dp_trace_data.thresh_time_limit);
1833 
1834 	DPTRACE_PRINT("DPT: stats - tx %u rx %u icmp(%u %u) arp(%u %u)",
1835 		g_qdf_dp_trace_data.tx_count,
1836 		g_qdf_dp_trace_data.rx_count,
1837 		g_qdf_dp_trace_data.icmp_req,
1838 		g_qdf_dp_trace_data.icmp_resp,
1839 		g_qdf_dp_trace_data.arp_req,
1840 		g_qdf_dp_trace_data.arp_resp);
1841 
1842 	DPTRACE_PRINT("DPT: Total Records: %d, Head: %d, Tail: %d",
1843 		      g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head,
1844 		      g_qdf_dp_trace_data.tail);
1845 
1846 	/* aquire the lock so that only one thread at a time can read
1847 	 * the ring buffer
1848 	 */
1849 	spin_lock_bh(&l_dp_trace_lock);
1850 
1851 	if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) {
1852 		i = g_qdf_dp_trace_data.head;
1853 		tail = g_qdf_dp_trace_data.tail;
1854 
1855 		if (count) {
1856 			if (count > g_qdf_dp_trace_data.num)
1857 				count = g_qdf_dp_trace_data.num;
1858 			if (tail >= (count - 1))
1859 				i = tail - count + 1;
1860 			else if (count != MAX_QDF_DP_TRACE_RECORDS)
1861 				i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) -
1862 							     tail);
1863 		}
1864 
1865 		p_record = g_qdf_dp_trace_tbl[i];
1866 		spin_unlock_bh(&l_dp_trace_lock);
1867 		for (;; ) {
1868 			qdf_dp_trace_cb_table[p_record.code](&p_record,
1869 							(uint16_t)i, pdev_id, false);
1870 			if (i == tail)
1871 				break;
1872 			i += 1;
1873 
1874 			spin_lock_bh(&l_dp_trace_lock);
1875 			if (MAX_QDF_DP_TRACE_RECORDS == i)
1876 				i = 0;
1877 
1878 			p_record = g_qdf_dp_trace_tbl[i];
1879 			spin_unlock_bh(&l_dp_trace_lock);
1880 		}
1881 	} else {
1882 		spin_unlock_bh(&l_dp_trace_lock);
1883 	}
1884 }
1885 EXPORT_SYMBOL(qdf_dp_trace_dump_all);
1886 
1887 #endif
1888 
1889 struct qdf_print_ctrl print_ctrl_obj[MAX_PRINT_CONFIG_SUPPORTED];
1890 
1891 struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = {
1892 	[QDF_MODULE_ID_TDLS] = {"tdls"},
1893 	[QDF_MODULE_ID_ACS] = {"ACS"},
1894 	[QDF_MODULE_ID_SCAN_SM] = {"scan state machine"},
1895 	[QDF_MODULE_ID_SCANENTRY] = {"scan entry"},
1896 	[QDF_MODULE_ID_WDS] = {"WDS"},
1897 	[QDF_MODULE_ID_ACTION] = {"action"},
1898 	[QDF_MODULE_ID_ROAM] = {"STA roaming"},
1899 	[QDF_MODULE_ID_INACT] = {"inactivity"},
1900 	[QDF_MODULE_ID_DOTH] = {"11h"},
1901 	[QDF_MODULE_ID_IQUE] = {"IQUE"},
1902 	[QDF_MODULE_ID_WME] = {"WME"},
1903 	[QDF_MODULE_ID_ACL] = {"ACL"},
1904 	[QDF_MODULE_ID_WPA] = {"WPA/RSN"},
1905 	[QDF_MODULE_ID_RADKEYS] = {"dump 802.1x keys"},
1906 	[QDF_MODULE_ID_RADDUMP] = {"dump radius packet"},
1907 	[QDF_MODULE_ID_RADIUS] = {"802.1x radius client"},
1908 	[QDF_MODULE_ID_DOT1XSM] = {"802.1x state machine"},
1909 	[QDF_MODULE_ID_DOT1X] = {"802.1x authenticator"},
1910 	[QDF_MODULE_ID_POWER] = {"power save"},
1911 	[QDF_MODULE_ID_STATE] = {"state"},
1912 	[QDF_MODULE_ID_OUTPUT] = {"output"},
1913 	[QDF_MODULE_ID_SCAN] = {"scan"},
1914 	[QDF_MODULE_ID_AUTH] = {"authentication"},
1915 	[QDF_MODULE_ID_ASSOC] = {"association"},
1916 	[QDF_MODULE_ID_NODE] = {"node"},
1917 	[QDF_MODULE_ID_ELEMID] = {"element ID"},
1918 	[QDF_MODULE_ID_XRATE] = {"rate"},
1919 	[QDF_MODULE_ID_INPUT] = {"input"},
1920 	[QDF_MODULE_ID_CRYPTO] = {"crypto"},
1921 	[QDF_MODULE_ID_DUMPPKTS] = {"dump packet"},
1922 	[QDF_MODULE_ID_DEBUG] = {"debug"},
1923 	[QDF_MODULE_ID_MLME] = {"mlme"},
1924 	[QDF_MODULE_ID_RRM] = {"rrm"},
1925 	[QDF_MODULE_ID_WNM] = {"wnm"},
1926 	[QDF_MODULE_ID_P2P_PROT] = {"p2p_prot"},
1927 	[QDF_MODULE_ID_PROXYARP] = {"proxyarp"},
1928 	[QDF_MODULE_ID_L2TIF] = {"l2tif"},
1929 	[QDF_MODULE_ID_WIFIPOS] = {"wifipos"},
1930 	[QDF_MODULE_ID_WRAP] = {"wrap"},
1931 	[QDF_MODULE_ID_DFS] = {"dfs"},
1932 	[QDF_MODULE_ID_ATF] = {"atf"},
1933 	[QDF_MODULE_ID_SPLITMAC] = {"splitmac"},
1934 	[QDF_MODULE_ID_IOCTL] = {"ioctl"},
1935 	[QDF_MODULE_ID_NAC] = {"nac"},
1936 	[QDF_MODULE_ID_MESH] = {"mesh"},
1937 	[QDF_MODULE_ID_MBO] = {"mbo"},
1938 	[QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = {"extchanswitch"},
1939 	[QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = {"extchanscan"},
1940 	[QDF_MODULE_ID_TLSHIM] = {"tlshim"},
1941 	[QDF_MODULE_ID_WMI] = {"WMI"},
1942 	[QDF_MODULE_ID_HTT] = {"HTT"},
1943 	[QDF_MODULE_ID_HDD] = {"HDD"},
1944 	[QDF_MODULE_ID_SME] = {"SME"},
1945 	[QDF_MODULE_ID_PE] = {"PE"},
1946 	[QDF_MODULE_ID_WMA] = {"WMA"},
1947 	[QDF_MODULE_ID_SYS] = {"SYS"},
1948 	[QDF_MODULE_ID_QDF] = {"QDF"},
1949 	[QDF_MODULE_ID_SAP] = {"SAP"},
1950 	[QDF_MODULE_ID_HDD_SOFTAP] = {"HDD_SAP"},
1951 	[QDF_MODULE_ID_HDD_DATA] = {"DATA"},
1952 	[QDF_MODULE_ID_HDD_SAP_DATA] = {"SAP_DATA"},
1953 	[QDF_MODULE_ID_HIF] = {"HIF"},
1954 	[QDF_MODULE_ID_HTC] = {"HTC"},
1955 	[QDF_MODULE_ID_TXRX] = {"TXRX"},
1956 	[QDF_MODULE_ID_QDF_DEVICE] = {"QDF_DEV"},
1957 	[QDF_MODULE_ID_CFG] = {"CFG"},
1958 	[QDF_MODULE_ID_BMI] = {"BMI"},
1959 	[QDF_MODULE_ID_EPPING] = {"EPPING"},
1960 	[QDF_MODULE_ID_QVIT] = {"QVIT"},
1961 	[QDF_MODULE_ID_DP] = {"DP"},
1962 	[QDF_MODULE_ID_SOC] = {"SOC"},
1963 	[QDF_MODULE_ID_OS_IF] = {"OSIF"},
1964 	[QDF_MODULE_ID_TARGET_IF] = {"TIF"},
1965 	[QDF_MODULE_ID_SCHEDULER] = {"SCH"},
1966 	[QDF_MODULE_ID_MGMT_TXRX] = {"MGMT_TXRX"},
1967 	[QDF_MODULE_ID_PMO] = {"PMO"},
1968 	[QDF_MODULE_ID_POLICY_MGR] = {"POLICY_MGR"},
1969 	[QDF_MODULE_ID_NAN] = {"NAN"},
1970 	[QDF_MODULE_ID_SPECTRAL] = {"SPECTRAL"},
1971 	[QDF_MODULE_ID_P2P] = {"P2P"},
1972 	[QDF_MODULE_ID_OFFCHAN_TXRX] = {"OFFCHAN"},
1973 	[QDF_MODULE_ID_REGULATORY] = {"REGULATORY"},
1974 	[QDF_MODULE_ID_OBJ_MGR] = {"OBJMGR"},
1975 	[QDF_MODULE_ID_ANY] = {"ANY"},
1976 };
1977 EXPORT_SYMBOL(g_qdf_category_name);
1978 
1979 /**
1980  * qdf_trace_display() - Display trace
1981  *
1982  * Return:  None
1983  */
1984 void qdf_trace_display(void)
1985 {
1986 	QDF_MODULE_ID module_id;
1987 
1988 	pr_err("     1)FATAL  2)ERROR  3)WARN  4)INFO  5)INFO_H  6)INFO_M  7)INFO_L 8)DEBUG\n");
1989 	for (module_id = 0; module_id < QDF_MODULE_ID_MAX; ++module_id) {
1990 		pr_err("%2d)%s    %s        %s       %s       %s        %s         %s         %s        %s\n",
1991 		       (int)module_id,
1992 		       g_qdf_category_name[module_id].category_name_str,
1993 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
1994 			       QDF_TRACE_LEVEL_FATAL) ? "X" : " ",
1995 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
1996 			       QDF_TRACE_LEVEL_ERROR) ? "X" : " ",
1997 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
1998 			       QDF_TRACE_LEVEL_WARN) ? "X" : " ",
1999 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
2000 			       QDF_TRACE_LEVEL_INFO) ? "X" : " ",
2001 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
2002 			       QDF_TRACE_LEVEL_INFO_HIGH) ? "X" : " ",
2003 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
2004 			       QDF_TRACE_LEVEL_INFO_MED) ? "X" : " ",
2005 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
2006 			       QDF_TRACE_LEVEL_INFO_LOW) ? "X" : " ",
2007 		       qdf_print_is_verbose_enabled(qdf_pidx, module_id,
2008 			       QDF_TRACE_LEVEL_DEBUG) ? "X" : " ");
2009 	}
2010 }
2011 EXPORT_SYMBOL(qdf_trace_display);
2012 
2013 #ifdef CONFIG_MCL
2014 #define print_to_console(str)
2015 #else
2016 static inline void print_to_console(char *str_buffer)
2017 {
2018 	pr_err("%s\n", str_buffer);
2019 }
2020 #endif
2021 
2022 void qdf_trace_msg_cmn(unsigned int idx,
2023 			QDF_MODULE_ID category,
2024 			QDF_TRACE_LEVEL verbose,
2025 			const char *str_format, va_list val)
2026 {
2027 	char str_buffer[QDF_TRACE_BUFFER_SIZE];
2028 	int n;
2029 
2030 	/* Check if index passed is valid */
2031 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
2032 		pr_info("%s: Invalid index - %d\n", __func__, idx);
2033 		return;
2034 	}
2035 
2036 	/* Check if print control object is in use */
2037 	if (!print_ctrl_obj[idx].in_use) {
2038 		pr_info("%s: Invalid print control object\n", __func__);
2039 		return;
2040 	}
2041 
2042 	/* Check if category passed is valid */
2043 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
2044 		pr_info("%s: Invalid category: %d\n", __func__, category);
2045 		return;
2046 	}
2047 
2048 	/* Check if verbose mask is valid */
2049 	if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
2050 		pr_info("%s: Invalid verbose level %d\n", __func__, verbose);
2051 		return;
2052 	}
2053 
2054 	/*
2055 	 * Print the trace message when the desired verbose level is set in
2056 	 * the desired category for the print control object
2057 	 */
2058 	if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
2059 	    QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
2060 		/*
2061 		 * The verbose strings are in an array. These are ordered in
2062 		 * the same order as the verbose levels are defined in the enum
2063 		 * (see QDF_TRACE_LEVEL) so we can index into this array with
2064 		 * the level and get the right string. The qdf verbose
2065 		 * are... Off, Fatal, Error, Warning, Info, Info_high,
2066 		 * Info_med, Info_low, Debug
2067 		 */
2068 		static const char * const VERBOSE_STR[] = { "  ", "F", "E", "W",
2069 							"I", "IH", "IM", "IL",
2070 							"D" };
2071 
2072 		/* print the prefix string into the string buffer... */
2073 		n = scnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE,
2074 			     "wlan: [%d:%2s:%s] ",
2075 			     in_interrupt() ? 0 : current->pid,
2076 			     VERBOSE_STR[verbose],
2077 			     g_qdf_category_name[category].category_name_str);
2078 
2079 		/* print the formatted log message after the prefix string */
2080 		vscnprintf(str_buffer + n, QDF_TRACE_BUFFER_SIZE - n,
2081 			   str_format, val);
2082 #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE)
2083 		wlan_log_to_user(verbose, (char *)str_buffer,
2084 				 strlen(str_buffer));
2085 		print_to_console(str_buffer);
2086 #else
2087 		pr_err("%s\n", str_buffer);
2088 #endif
2089 		va_end(val);
2090 	}
2091 }
2092 EXPORT_SYMBOL(qdf_trace_msg_cmn);
2093 
2094 /**
2095  * qdf_dp_trace_throttle_live_mode() - Throttle DP Trace live mode
2096  * @high_bw_request: whether this is a high BW req or not
2097  *
2098  * The function tries to prevent excessive logging into the live buffer by
2099  * having an upper limit on number of packets that can be logged per second.
2100  *
2101  * The intention is to allow occasional pings and data packets and really low
2102  * throughput levels while suppressing bursts and higher throughput levels so
2103  * that we donot hog the live buffer.
2104  *
2105  * If the number of packets printed in a particular second exceeds the thresh,
2106  * disable printing in the next second.
2107  *
2108  * Return: None
2109  */
2110 void qdf_dp_trace_throttle_live_mode(bool high_bw_request)
2111 {
2112 	static int bw_interval_counter;
2113 
2114 	if (g_qdf_dp_trace_data.enable == false ||
2115 		g_qdf_dp_trace_data.live_mode_config == false)
2116 		return;
2117 
2118 	if (high_bw_request) {
2119 		g_qdf_dp_trace_data.live_mode = 0;
2120 		bw_interval_counter = 0;
2121 		return;
2122 	}
2123 
2124 	bw_interval_counter++;
2125 
2126 	if (0 == (bw_interval_counter %
2127 			g_qdf_dp_trace_data.thresh_time_limit)) {
2128 
2129 		spin_lock_bh(&l_dp_trace_lock);
2130 			if (g_qdf_dp_trace_data.print_pkt_cnt <=
2131 				g_qdf_dp_trace_data.high_tput_thresh)
2132 				g_qdf_dp_trace_data.live_mode = 1;
2133 
2134 		g_qdf_dp_trace_data.print_pkt_cnt = 0;
2135 		spin_unlock_bh(&l_dp_trace_lock);
2136 	}
2137 
2138 }
2139 EXPORT_SYMBOL(qdf_dp_trace_throttle_live_mode);
2140 
2141 QDF_STATUS qdf_print_setup(void)
2142 {
2143 	int i;
2144 
2145 	/* Loop through all print ctrl objects */
2146 	for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
2147 		if (qdf_print_ctrl_cleanup(i))
2148 			return QDF_STATUS_E_FAILURE;
2149 	}
2150 	return QDF_STATUS_SUCCESS;
2151 }
2152 EXPORT_SYMBOL(qdf_print_setup);
2153 
2154 QDF_STATUS qdf_print_ctrl_cleanup(unsigned int idx)
2155 {
2156 	int i = 0;
2157 
2158 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
2159 		pr_info("%s: Invalid index - %d\n", __func__, idx);
2160 		return QDF_STATUS_E_FAILURE;
2161 	}
2162 
2163 	/* Clean up the print control object corresponding to that index
2164 	 * If success, callee to change print control index to -1
2165 	 */
2166 
2167 	for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
2168 		print_ctrl_obj[idx].cat_info[i].category_verbose_mask =
2169 							QDF_TRACE_LEVEL_NONE;
2170 	}
2171 	print_ctrl_obj[idx].custom_print = NULL;
2172 	print_ctrl_obj[idx].custom_ctxt = NULL;
2173 	qdf_print_clean_node_flag(idx);
2174 	print_ctrl_obj[idx].in_use = false;
2175 
2176 	pr_info("%s: Print control object %d cleaned up\n", __func__, idx);
2177 
2178 	return QDF_STATUS_SUCCESS;
2179 }
2180 EXPORT_SYMBOL(qdf_print_ctrl_cleanup);
2181 
2182 int qdf_print_ctrl_register(const struct category_info *cinfo,
2183 			    void *custom_print_handler,
2184 			    void *custom_ctx,
2185 			    const char *pctrl_name)
2186 {
2187 	int idx = -1;
2188 	int i = 0;
2189 
2190 	for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
2191 		if (!print_ctrl_obj[i].in_use) {
2192 			idx = i;
2193 			break;
2194 		}
2195 	}
2196 
2197 	/* Callee to handle idx -1 appropriately */
2198 	if (idx == -1) {
2199 		pr_info("%s: Allocation failed! No print control object free\n",
2200 			__func__);
2201 		return idx;
2202 	}
2203 
2204 	print_ctrl_obj[idx].in_use = true;
2205 
2206 	/*
2207 	 * In case callee does not pass category info,
2208 	 * custom print handler, custom context and print control name,
2209 	 * we do not set any value here. Clean up for the print control
2210 	 * getting allocated would have taken care of initializing
2211 	 * default values.
2212 	 *
2213 	 * We need to only set in_use to 1 in such a case
2214 	 */
2215 
2216 	if (pctrl_name) {
2217 		qdf_str_lcopy(print_ctrl_obj[idx].name, pctrl_name,
2218 			      qdf_str_len(pctrl_name) + 1);
2219 	}
2220 
2221 	if (custom_print_handler)
2222 		print_ctrl_obj[idx].custom_print = custom_print_handler;
2223 
2224 	if (custom_ctx)
2225 		print_ctrl_obj[idx].custom_ctxt = custom_ctx;
2226 
2227 	if (cinfo) {
2228 		for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
2229 			if (cinfo[i].category_verbose_mask ==
2230 			    QDF_TRACE_LEVEL_ALL) {
2231 				print_ctrl_obj[idx].cat_info[i]
2232 				.category_verbose_mask = 0xFFFF;
2233 			} else if ((cinfo[i].category_verbose_mask ==
2234 				   QDF_TRACE_LEVEL_NONE) ||
2235 				   (cinfo[i].category_verbose_mask ==
2236 				   QDF_TRACE_LEVEL_TO_MODULE_BITMASK(
2237 				   QDF_TRACE_LEVEL_NONE))) {
2238 				print_ctrl_obj[idx].cat_info[i]
2239 				.category_verbose_mask = 0;
2240 			} else {
2241 				print_ctrl_obj[idx].cat_info[i]
2242 				.category_verbose_mask =
2243 				cinfo[i].category_verbose_mask;
2244 			}
2245 		}
2246 	}
2247 
2248 	pr_info("%s: Allocated print control object %d\n",
2249 		__func__, idx);
2250 	return idx;
2251 }
2252 EXPORT_SYMBOL(qdf_print_ctrl_register);
2253 
2254 #ifndef CONFIG_MCL
2255 void qdf_shared_print_ctrl_cleanup(void)
2256 {
2257 	qdf_print_ctrl_cleanup(qdf_pidx);
2258 }
2259 EXPORT_SYMBOL(qdf_shared_print_ctrl_cleanup);
2260 
2261 /*
2262  * Set this to invalid value to differentiate with user-provided
2263  * value.
2264  */
2265 int qdf_dbg_mask = 0;
2266 EXPORT_SYMBOL(qdf_dbg_mask);
2267 qdf_declare_param(qdf_dbg_mask, int);
2268 
2269 /*
2270  * QDF can be passed parameters which indicate the
2271  * debug level for each module.
2272  * an array of string values are passed, each string hold the following form
2273  *
2274  * <module name string>=<integer debug level value>
2275  *
2276  * The array qdf_dbg_arr will hold these module-string=value strings
2277  * The variable qdf_dbg_arr_cnt will have the count of how many such
2278  * string values were passed.
2279  */
2280 static char *qdf_dbg_arr[QDF_MODULE_ID_MAX];
2281 static int qdf_dbg_arr_cnt;
2282 qdf_declare_param_array(qdf_dbg_arr, charp, &qdf_dbg_arr_cnt);
2283 
2284 static uint16_t set_cumulative_verbose_mask(QDF_TRACE_LEVEL max_level)
2285 {
2286 	uint16_t category_verbose_mask = 0;
2287 	QDF_TRACE_LEVEL level;
2288 
2289 	for (level = QDF_TRACE_LEVEL_FATAL; level <= max_level; level++) {
2290 		category_verbose_mask |=
2291 			QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level);
2292 	}
2293 	return category_verbose_mask;
2294 }
2295 
2296 static QDF_MODULE_ID find_qdf_module_from_string(char *str)
2297 {
2298 	QDF_MODULE_ID mod_id;
2299 
2300 	for (mod_id = 0; mod_id < QDF_MODULE_ID_MAX; mod_id++) {
2301 		if (strcasecmp(str,
2302 				g_qdf_category_name[mod_id].category_name_str)
2303 				== 0) {
2304 			break;
2305 		}
2306 	}
2307 	return mod_id;
2308 }
2309 
2310 static void process_qdf_dbg_arr_param(struct category_info *cinfo,
2311 					int array_index)
2312 {
2313 	char *mod_val_str, *mod_str, *val_str;
2314 	unsigned long dbg_level;
2315 	QDF_MODULE_ID mod_id;
2316 
2317 	mod_val_str = qdf_dbg_arr[array_index];
2318 	mod_str = strsep(&mod_val_str, "=");
2319 	val_str = mod_val_str;
2320 	if (val_str == NULL) {
2321 		pr_info("qdf_dbg_arr: %s not in the <mod>=<val> form\n",
2322 				mod_str);
2323 		return;
2324 	}
2325 
2326 	mod_id = find_qdf_module_from_string(mod_str);
2327 	if (mod_id >= QDF_MODULE_ID_MAX) {
2328 		pr_info("ERROR!!Module name %s not in the list of modules\n",
2329 				mod_str);
2330 		return;
2331 	}
2332 
2333 	if (kstrtol(val_str, 10, &dbg_level) < 0) {
2334 		pr_info("ERROR!!Invalid debug level for module: %s\n",
2335 				mod_str);
2336 		return;
2337 	}
2338 
2339 	if (dbg_level >= QDF_TRACE_LEVEL_MAX) {
2340 		pr_info("ERROR!!Debug level for %s too high", mod_str);
2341 		pr_info("max: %d given %lu\n", QDF_TRACE_LEVEL_MAX,
2342 				dbg_level);
2343 		return;
2344 	}
2345 
2346 	pr_info("User passed setting module %s(%d) to level %lu\n",
2347 			mod_str,
2348 			mod_id,
2349 			dbg_level);
2350 	cinfo[mod_id].category_verbose_mask =
2351 		set_cumulative_verbose_mask((QDF_TRACE_LEVEL)dbg_level);
2352 }
2353 
2354 static void set_default_trace_levels(struct category_info *cinfo)
2355 {
2356 	int i;
2357 	static QDF_TRACE_LEVEL module_trace_default_level[QDF_MODULE_ID_MAX] = {
2358 		[QDF_MODULE_ID_TDLS] = QDF_TRACE_LEVEL_NONE,
2359 		[QDF_MODULE_ID_ACS] = QDF_TRACE_LEVEL_NONE,
2360 		[QDF_MODULE_ID_SCAN_SM] = QDF_TRACE_LEVEL_NONE,
2361 		[QDF_MODULE_ID_SCANENTRY] = QDF_TRACE_LEVEL_NONE,
2362 		[QDF_MODULE_ID_WDS] = QDF_TRACE_LEVEL_NONE,
2363 		[QDF_MODULE_ID_ACTION] = QDF_TRACE_LEVEL_NONE,
2364 		[QDF_MODULE_ID_ROAM] = QDF_TRACE_LEVEL_NONE,
2365 		[QDF_MODULE_ID_INACT] = QDF_TRACE_LEVEL_NONE,
2366 		[QDF_MODULE_ID_DOTH] = QDF_TRACE_LEVEL_NONE,
2367 		[QDF_MODULE_ID_IQUE] = QDF_TRACE_LEVEL_NONE,
2368 		[QDF_MODULE_ID_WME] = QDF_TRACE_LEVEL_NONE,
2369 		[QDF_MODULE_ID_ACL] = QDF_TRACE_LEVEL_NONE,
2370 		[QDF_MODULE_ID_WPA] = QDF_TRACE_LEVEL_NONE,
2371 		[QDF_MODULE_ID_RADKEYS] = QDF_TRACE_LEVEL_NONE,
2372 		[QDF_MODULE_ID_RADDUMP] = QDF_TRACE_LEVEL_NONE,
2373 		[QDF_MODULE_ID_RADIUS] = QDF_TRACE_LEVEL_NONE,
2374 		[QDF_MODULE_ID_DOT1XSM] = QDF_TRACE_LEVEL_NONE,
2375 		[QDF_MODULE_ID_DOT1X] = QDF_TRACE_LEVEL_NONE,
2376 		[QDF_MODULE_ID_POWER] = QDF_TRACE_LEVEL_NONE,
2377 		[QDF_MODULE_ID_STATE] = QDF_TRACE_LEVEL_NONE,
2378 		[QDF_MODULE_ID_OUTPUT] = QDF_TRACE_LEVEL_NONE,
2379 		[QDF_MODULE_ID_SCAN] = QDF_TRACE_LEVEL_NONE,
2380 		[QDF_MODULE_ID_AUTH] = QDF_TRACE_LEVEL_NONE,
2381 		[QDF_MODULE_ID_ASSOC] = QDF_TRACE_LEVEL_NONE,
2382 		[QDF_MODULE_ID_NODE] = QDF_TRACE_LEVEL_NONE,
2383 		[QDF_MODULE_ID_ELEMID] = QDF_TRACE_LEVEL_NONE,
2384 		[QDF_MODULE_ID_XRATE] = QDF_TRACE_LEVEL_NONE,
2385 		[QDF_MODULE_ID_INPUT] = QDF_TRACE_LEVEL_NONE,
2386 		[QDF_MODULE_ID_CRYPTO] = QDF_TRACE_LEVEL_NONE,
2387 		[QDF_MODULE_ID_DUMPPKTS] = QDF_TRACE_LEVEL_NONE,
2388 		[QDF_MODULE_ID_DEBUG] = QDF_TRACE_LEVEL_NONE,
2389 		[QDF_MODULE_ID_MLME] = QDF_TRACE_LEVEL_NONE,
2390 		[QDF_MODULE_ID_RRM] = QDF_TRACE_LEVEL_NONE,
2391 		[QDF_MODULE_ID_WNM] = QDF_TRACE_LEVEL_NONE,
2392 		[QDF_MODULE_ID_P2P_PROT] = QDF_TRACE_LEVEL_NONE,
2393 		[QDF_MODULE_ID_PROXYARP] = QDF_TRACE_LEVEL_NONE,
2394 		[QDF_MODULE_ID_L2TIF] = QDF_TRACE_LEVEL_NONE,
2395 		[QDF_MODULE_ID_WIFIPOS] = QDF_TRACE_LEVEL_NONE,
2396 		[QDF_MODULE_ID_WRAP] = QDF_TRACE_LEVEL_NONE,
2397 		[QDF_MODULE_ID_DFS] = QDF_TRACE_LEVEL_NONE,
2398 		[QDF_MODULE_ID_ATF] = QDF_TRACE_LEVEL_NONE,
2399 		[QDF_MODULE_ID_SPLITMAC] = QDF_TRACE_LEVEL_NONE,
2400 		[QDF_MODULE_ID_IOCTL] = QDF_TRACE_LEVEL_NONE,
2401 		[QDF_MODULE_ID_NAC] = QDF_TRACE_LEVEL_NONE,
2402 		[QDF_MODULE_ID_MESH] = QDF_TRACE_LEVEL_NONE,
2403 		[QDF_MODULE_ID_MBO] = QDF_TRACE_LEVEL_NONE,
2404 		[QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = QDF_TRACE_LEVEL_NONE,
2405 		[QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = QDF_TRACE_LEVEL_NONE,
2406 		[QDF_MODULE_ID_TLSHIM] = QDF_TRACE_LEVEL_NONE,
2407 		[QDF_MODULE_ID_WMI] = QDF_TRACE_LEVEL_NONE,
2408 		[QDF_MODULE_ID_HTT] = QDF_TRACE_LEVEL_NONE,
2409 		[QDF_MODULE_ID_HDD] = QDF_TRACE_LEVEL_NONE,
2410 		[QDF_MODULE_ID_SME] = QDF_TRACE_LEVEL_NONE,
2411 		[QDF_MODULE_ID_PE] = QDF_TRACE_LEVEL_NONE,
2412 		[QDF_MODULE_ID_WMA] = QDF_TRACE_LEVEL_NONE,
2413 		[QDF_MODULE_ID_SYS] = QDF_TRACE_LEVEL_NONE,
2414 		[QDF_MODULE_ID_QDF] = QDF_TRACE_LEVEL_NONE,
2415 		[QDF_MODULE_ID_SAP] = QDF_TRACE_LEVEL_NONE,
2416 		[QDF_MODULE_ID_HDD_SOFTAP] = QDF_TRACE_LEVEL_NONE,
2417 		[QDF_MODULE_ID_HDD_DATA] = QDF_TRACE_LEVEL_NONE,
2418 		[QDF_MODULE_ID_HDD_SAP_DATA] = QDF_TRACE_LEVEL_NONE,
2419 		[QDF_MODULE_ID_HIF] = QDF_TRACE_LEVEL_NONE,
2420 		[QDF_MODULE_ID_HTC] = QDF_TRACE_LEVEL_NONE,
2421 		[QDF_MODULE_ID_TXRX] = QDF_TRACE_LEVEL_NONE,
2422 		[QDF_MODULE_ID_QDF_DEVICE] = QDF_TRACE_LEVEL_NONE,
2423 		[QDF_MODULE_ID_CFG] = QDF_TRACE_LEVEL_NONE,
2424 		[QDF_MODULE_ID_BMI] = QDF_TRACE_LEVEL_NONE,
2425 		[QDF_MODULE_ID_EPPING] = QDF_TRACE_LEVEL_NONE,
2426 		[QDF_MODULE_ID_QVIT] = QDF_TRACE_LEVEL_NONE,
2427 		[QDF_MODULE_ID_DP] = QDF_TRACE_LEVEL_FATAL,
2428 		[QDF_MODULE_ID_SOC] = QDF_TRACE_LEVEL_NONE,
2429 		[QDF_MODULE_ID_OS_IF] = QDF_TRACE_LEVEL_NONE,
2430 		[QDF_MODULE_ID_TARGET_IF] = QDF_TRACE_LEVEL_NONE,
2431 		[QDF_MODULE_ID_SCHEDULER] = QDF_TRACE_LEVEL_NONE,
2432 		[QDF_MODULE_ID_MGMT_TXRX] = QDF_TRACE_LEVEL_NONE,
2433 		[QDF_MODULE_ID_PMO] = QDF_TRACE_LEVEL_NONE,
2434 		[QDF_MODULE_ID_POLICY_MGR] = QDF_TRACE_LEVEL_NONE,
2435 		[QDF_MODULE_ID_NAN] = QDF_TRACE_LEVEL_NONE,
2436 		[QDF_MODULE_ID_P2P] = QDF_TRACE_LEVEL_NONE,
2437 		[QDF_MODULE_ID_OFFCHAN_TXRX] = QDF_TRACE_LEVEL_NONE,
2438 		[QDF_MODULE_ID_OBJ_MGR] = QDF_TRACE_LEVEL_INFO,
2439 		[QDF_MODULE_ID_ANY] = QDF_TRACE_LEVEL_NONE,
2440 	};
2441 
2442 	for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
2443 		cinfo[i].category_verbose_mask = set_cumulative_verbose_mask(
2444 				module_trace_default_level[i]);
2445 	}
2446 }
2447 
2448 void qdf_shared_print_ctrl_init(void)
2449 {
2450 	int i;
2451 	struct category_info *cinfo = qdf_mem_malloc((sizeof(*cinfo))*
2452 			MAX_SUPPORTED_CATEGORY);
2453 	if (cinfo == NULL) {
2454 		pr_info("ERROR!! qdf_mem_malloc failed. \
2455 			Shared Print Ctrl object not initialized \
2456 			\nQDF_TRACE messages may not be logged/displayed");
2457 		return;
2458 	}
2459 
2460 	set_default_trace_levels(cinfo);
2461 
2462 	/*
2463 	 * User specified across-module single debug level
2464 	 */
2465 	if ((qdf_dbg_mask > 0) && (qdf_dbg_mask <= QDF_TRACE_LEVEL_MAX)) {
2466 		pr_info("User specified module debug level of %d\n",
2467 			qdf_dbg_mask);
2468 		for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
2469 			cinfo[i].category_verbose_mask =
2470 			set_cumulative_verbose_mask(qdf_dbg_mask);
2471 		}
2472 	} else {
2473 		pr_info("qdf_dbg_mask value is invalid\n");
2474 		pr_info("Using the default module debug levels instead\n");
2475 	}
2476 
2477 	/*
2478 	 * Module ID-Level specified as array during module load
2479 	 */
2480 	for (i = 0; i < qdf_dbg_arr_cnt; i++) {
2481 		process_qdf_dbg_arr_param(cinfo, i);
2482 	}
2483 	qdf_pidx = qdf_print_ctrl_register(cinfo, NULL, NULL,
2484 			"LOG_SHARED_OBJ");
2485 	qdf_mem_free(cinfo);
2486 }
2487 EXPORT_SYMBOL(qdf_shared_print_ctrl_init);
2488 #endif
2489 
2490 QDF_STATUS qdf_print_set_category_verbose(unsigned int idx,
2491 						QDF_MODULE_ID category,
2492 						QDF_TRACE_LEVEL verbose,
2493 						bool is_set)
2494 {
2495 	/* Check if index passed is valid */
2496 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
2497 		pr_info("%s: Invalid index - %d\n", __func__, idx);
2498 		return QDF_STATUS_E_FAILURE;
2499 	}
2500 
2501 	/* Check if print control object is in use */
2502 	if (!print_ctrl_obj[idx].in_use) {
2503 		pr_info("%s: Invalid print control object\n", __func__);
2504 		return QDF_STATUS_E_FAILURE;
2505 	}
2506 
2507 	/* Check if category passed is valid */
2508 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
2509 		pr_info("%s: Invalid category: %d\n", __func__, category);
2510 		return QDF_STATUS_E_FAILURE;
2511 	}
2512 
2513 	/* Check if verbose mask is valid */
2514 	if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
2515 		pr_info("%s: Invalid verbose level %d\n", __func__, verbose);
2516 		return QDF_STATUS_E_FAILURE;
2517 	}
2518 
2519 	if (verbose == QDF_TRACE_LEVEL_ALL) {
2520 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
2521 				0xFFFF;
2522 		return QDF_STATUS_SUCCESS;
2523 	}
2524 
2525 	if (verbose == QDF_TRACE_LEVEL_NONE) {
2526 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
2527 				QDF_TRACE_LEVEL_NONE;
2528 		return QDF_STATUS_SUCCESS;
2529 	}
2530 
2531 	if (!is_set) {
2532 		if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask
2533 		    & QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
2534 			print_ctrl_obj[idx].cat_info[category]
2535 				.category_verbose_mask &=
2536 				~QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
2537 		}
2538 	} else {
2539 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask |=
2540 				QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
2541 	}
2542 
2543 	pr_info("%s: Print control object %d, Category %d, Verbose level %d\n",
2544 		__func__,
2545 		idx,
2546 		category,
2547 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask);
2548 
2549 	return QDF_STATUS_SUCCESS;
2550 }
2551 EXPORT_SYMBOL(qdf_print_set_category_verbose);
2552 
2553 bool qdf_print_is_category_enabled(unsigned int idx, QDF_MODULE_ID category)
2554 {
2555 	QDF_TRACE_LEVEL verbose_mask;
2556 
2557 	/* Check if index passed is valid */
2558 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
2559 		pr_info("%s: Invalid index - %d\n", __func__, idx);
2560 		return false;
2561 	}
2562 
2563 	/* Check if print control object is in use */
2564 	if (!print_ctrl_obj[idx].in_use) {
2565 		pr_info("%s: Invalid print control object\n", __func__);
2566 		return false;
2567 	}
2568 
2569 	/* Check if category passed is valid */
2570 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
2571 		pr_info("%s: Invalid category: %d\n", __func__, category);
2572 		return false;
2573 	}
2574 
2575 	verbose_mask =
2576 		print_ctrl_obj[idx].cat_info[category].category_verbose_mask;
2577 
2578 	if (verbose_mask == QDF_TRACE_LEVEL_NONE)
2579 		return false;
2580 	else
2581 		return true;
2582 }
2583 EXPORT_SYMBOL(qdf_print_is_category_enabled);
2584 
2585 bool qdf_print_is_verbose_enabled(unsigned int idx, QDF_MODULE_ID category,
2586 				  QDF_TRACE_LEVEL verbose)
2587 {
2588 	bool verbose_enabled = false;
2589 
2590 	/* Check if index passed is valid */
2591 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
2592 		pr_info("%s: Invalid index - %d\n", __func__, idx);
2593 		return verbose_enabled;
2594 	}
2595 
2596 	/* Check if print control object is in use */
2597 	if (!print_ctrl_obj[idx].in_use) {
2598 		pr_info("%s: Invalid print control object\n", __func__);
2599 		return verbose_enabled;
2600 	}
2601 
2602 	/* Check if category passed is valid */
2603 	if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
2604 		pr_info("%s: Invalid category: %d\n", __func__, category);
2605 		return verbose_enabled;
2606 	}
2607 
2608 	if ((verbose == QDF_TRACE_LEVEL_NONE) ||
2609 	    (verbose >= QDF_TRACE_LEVEL_MAX)) {
2610 		verbose_enabled = false;
2611 	} else if (verbose == QDF_TRACE_LEVEL_ALL) {
2612 		if (print_ctrl_obj[idx].cat_info[category]
2613 					.category_verbose_mask == 0xFFFF)
2614 			verbose_enabled = true;
2615 	} else {
2616 		verbose_enabled =
2617 		(print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
2618 		 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) ? true : false;
2619 	}
2620 
2621 	return verbose_enabled;
2622 }
2623 EXPORT_SYMBOL(qdf_print_is_verbose_enabled);
2624 
2625 #ifdef DBG_LVL_MAC_FILTERING
2626 
2627 QDF_STATUS qdf_print_set_node_flag(unsigned int idx, uint8_t enable)
2628 {
2629 	/* Check if index passed is valid */
2630 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
2631 		pr_info("%s: Invalid index - %d\n", __func__, idx);
2632 		return QDF_STATUS_E_FAILURE;
2633 	}
2634 
2635 	/* Check if print control object is in use */
2636 	if (!print_ctrl_obj[idx].in_use) {
2637 		pr_info("%s: Invalid print control object\n", __func__);
2638 		return QDF_STATUS_E_FAILURE;
2639 	}
2640 
2641 	if (enable > 1) {
2642 		pr_info("%s: Incorrect input: Use 1 or 0 to enable or disable\n",
2643 			__func__);
2644 		return QDF_STATUS_E_FAILURE;
2645 	}
2646 
2647 	print_ctrl_obj[idx].dbglvlmac_on = enable;
2648 	pr_info("%s: DbgLVLmac feature %s\n",
2649 		__func__,
2650 		((enable) ? "enabled" : "disabled"));
2651 
2652 	return QDF_STATUS_SUCCESS;
2653 }
2654 EXPORT_SYMBOL(qdf_print_set_node_flag);
2655 
2656 bool qdf_print_get_node_flag(unsigned int idx)
2657 {
2658 	bool node_flag = false;
2659 
2660 	/* Check if index passed is valid */
2661 	if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
2662 		pr_info("%s: Invalid index - %d\n", __func__, idx);
2663 		return node_flag;
2664 	}
2665 
2666 	/* Check if print control object is in use */
2667 	if (!print_ctrl_obj[idx].in_use) {
2668 		pr_info("%s: Invalid print control object\n", __func__);
2669 		return node_flag;
2670 	}
2671 
2672 	if (print_ctrl_obj[idx].dbglvlmac_on)
2673 		node_flag = true;
2674 
2675 	return node_flag;
2676 }
2677 EXPORT_SYMBOL(qdf_print_get_node_flag);
2678 
2679 void qdf_print_clean_node_flag(unsigned int idx)
2680 {
2681 	/* Disable dbglvlmac_on during cleanup */
2682 	print_ctrl_obj[idx].dbglvlmac_on = 0;
2683 }
2684 
2685 #else
2686 
2687 void qdf_print_clean_node_flag(unsigned int idx)
2688 {
2689 	/* No operation in case of no support for DBG_LVL_MAC_FILTERING */
2690 	return;
2691 }
2692 #endif
2693 
2694 void QDF_PRINT_INFO(unsigned int idx, QDF_MODULE_ID module,
2695 		    QDF_TRACE_LEVEL level,
2696 		    char *str_format, ...)
2697 {
2698 	va_list args;
2699 
2700 	/* Generic wrapper API will compile qdf_vprint in order to
2701 	 * log the message. Once QDF converged debug framework is in
2702 	 * place, this will be changed to adapt to the framework, compiling
2703 	 * call to converged tracing API
2704 	 */
2705 	va_start(args, str_format);
2706 	qdf_vprint(str_format, args);
2707 	va_end(args);
2708 }
2709 EXPORT_SYMBOL(QDF_PRINT_INFO);
2710 
2711 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
2712 void qdf_logging_init(void)
2713 {
2714 	wlan_logging_sock_init_svc();
2715 	nl_srv_init(NULL);
2716 }
2717 
2718 void qdf_logging_exit(void)
2719 {
2720 	nl_srv_exit();
2721 	wlan_logging_sock_deinit_svc();
2722 }
2723 #else
2724 void qdf_logging_init(void)
2725 {
2726 }
2727 
2728 void qdf_logging_exit(void)
2729 {
2730 }
2731 #endif
2732 
2733 #ifdef CONFIG_KALLSYMS
2734 inline int qdf_sprint_symbol(char *buffer, void *addr)
2735 {
2736 	return sprint_symbol(buffer, (unsigned long)addr);
2737 }
2738 #else
2739 int qdf_sprint_symbol(char *buffer, void *addr)
2740 {
2741 	if (!buffer)
2742 		return 0;
2743 
2744 	buffer[0] = '\0';
2745 	return 1;
2746 }
2747 #endif
2748 EXPORT_SYMBOL(qdf_sprint_symbol);
2749 
2750 void qdf_set_pidx(int pidx)
2751 {
2752 	qdf_pidx = pidx;
2753 }
2754 EXPORT_SYMBOL(qdf_set_pidx);
2755 
2756 int qdf_get_pidx(void)
2757 {
2758 	return qdf_pidx;
2759 }
2760 EXPORT_SYMBOL(qdf_get_pidx);
2761