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