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