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