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