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