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