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