1 /*
2 * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /**
21 * DOC: qdf_trace
22 * QCA driver framework (QDF) trace APIs
23 * Trace, logging, and debugging definitions and APIs
24 */
25
26 /* Include Files */
27 #include "qdf_str.h"
28 #include <qdf_trace.h>
29 #include <qdf_parse.h>
30 #include <qdf_module.h>
31 #include <qdf_util.h>
32 #include <qdf_mem.h>
33 #include <qdf_list.h>
34
35 /* macro to map qdf trace levels into the bitmask */
36 #define QDF_TRACE_LEVEL_TO_MODULE_BITMASK(_level) ((1 << (_level)))
37
38 #include <wlan_logging_sock_svc.h>
39 #include <qdf_module.h>
40 static int qdf_pidx = -1;
41 static bool qdf_log_dump_at_kernel_enable = true;
42 qdf_declare_param(qdf_log_dump_at_kernel_enable, bool);
43
44 /* This value of 0 will disable the timer by default. */
45 static uint32_t qdf_log_flush_timer_period;
46 qdf_declare_param(qdf_log_flush_timer_period, uint);
47
48 #include "qdf_time.h"
49 #include "qdf_mc_timer.h"
50 #include <host_diag_core_log.h>
51
52 #ifdef CONNECTIVITY_DIAG_EVENT
53 #include <wlan_connectivity_logging.h>
54 #include "i_host_diag_core_event.h"
55 #endif
56
57 #ifdef WLAN_CHIPSET_STATS
58 #include "wlan_cp_stats_chipset_stats.h"
59 #endif
60 /* Global qdf print id */
61
62 /* Preprocessor definitions and constants */
63
64 enum qdf_timestamp_unit qdf_log_timestamp_type = QDF_LOG_TIMESTAMP_UNIT;
65
66 #define DP_TRACE_META_DATA_STRLEN 50
67
68 #ifdef TRACE_RECORD
69 /* Static and Global variables */
70 static spinlock_t ltrace_lock;
71 /* global qdf trace data */
72 static t_qdf_trace_data g_qdf_trace_data;
73 /*
74 * all the call back functions for dumping MTRACE messages from ring buffer
75 * are stored in qdf_trace_cb_table,these callbacks are initialized during init
76 * only so, we will make a copy of these call back functions and maintain in to
77 * qdf_trace_restore_cb_table. Incase if we make modifications to
78 * qdf_trace_cb_table, we can certainly retrieve all the call back functions
79 * back from Restore Table
80 */
81 static tp_qdf_trace_cb qdf_trace_cb_table[QDF_MODULE_ID_MAX];
82 static tp_qdf_trace_cb qdf_trace_restore_cb_table[QDF_MODULE_ID_MAX];
83
84 #ifdef WLAN_LOGGING_BUFFERS_DYNAMICALLY
85 static qdf_trace_record_t *g_qdf_trace_tbl;
86 #else
87 static qdf_trace_record_t g_qdf_trace_tbl[MAX_QDF_TRACE_RECORDS];
88 #endif
89
90 #endif
91
92 #ifdef WLAN_FEATURE_MEMDUMP_ENABLE
93 static tp_qdf_state_info_cb qdf_state_info_table[QDF_MODULE_ID_MAX];
94 #endif
95
96 #ifdef CONFIG_DP_TRACE
97 /* Static and Global variables */
98 #ifdef WLAN_LOGGING_BUFFERS_DYNAMICALLY
99 static struct qdf_dp_trace_record_s *g_qdf_dp_trace_tbl;
100 #else
101 static struct qdf_dp_trace_record_s
102 g_qdf_dp_trace_tbl[MAX_QDF_DP_TRACE_RECORDS];
103 #endif
104 static spinlock_t l_dp_trace_lock;
105
106 /*
107 * all the options to configure/control DP trace are
108 * defined in this structure
109 */
110 static struct s_qdf_dp_trace_data g_qdf_dp_trace_data;
111 /*
112 * all the call back functions for dumping DPTRACE messages from ring buffer
113 * are stored in qdf_dp_trace_cb_table, callbacks are initialized during init
114 */
115 static tp_qdf_dp_trace_cb qdf_dp_trace_cb_table[QDF_DP_TRACE_MAX + 1];
116 #endif
117
118 #ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI
119 #define QDF_PARAM_STR_LENGTH 40
120
121 enum qdf_num_module_param {
122 MEM_DEBUG_DISABLED,
123 QDF_DBG_MASK,
124 PREALLOC_DISABLED,
125 QDF_LOG_DUMP_AT_KERNEL_ENABLE,
126 QDF_DBG_ARR,
127 QDF_LOG_FLUSH_TIMER_PERIOD,
128 QDF_PARAM_MAX,
129 };
130
131 static char qdf_module_param[QDF_PARAM_MAX][QDF_PARAM_STR_LENGTH] = {
132 "mem_debug_disabled",
133 "qdf_dbg_mask",
134 "prealloc_disabled",
135 "qdf_log_dump_at_kernel_enable",
136 "qdf_dbg_arr",
137 "qdf_log_flush_timer_period",
138 };
139 #endif
140
qdf_snprintf(char * str_buffer,unsigned int size,char * str_format,...)141 int qdf_snprintf(char *str_buffer, unsigned int size, char *str_format, ...)
142 {
143 va_list args;
144 int i;
145
146 va_start(args, str_format);
147 i = vsnprintf(str_buffer, size, str_format, args);
148 va_end(args);
149
150 return i;
151 }
152 qdf_export_symbol(qdf_snprintf);
153
154 #ifdef QDF_ENABLE_TRACING
155
qdf_trace_msg(QDF_MODULE_ID module,QDF_TRACE_LEVEL level,const char * str_format,...)156 void qdf_trace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
157 const char *str_format, ...)
158 {
159 va_list val;
160
161 va_start(val, str_format);
162 qdf_trace_msg_cmn(qdf_pidx, module, level, str_format, val);
163 va_end(val);
164 }
165 qdf_export_symbol(qdf_trace_msg);
166
qdf_vtrace_msg(QDF_MODULE_ID module,QDF_TRACE_LEVEL level,const char * str_format,va_list val)167 void qdf_vtrace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
168 const char *str_format, va_list val)
169 {
170 qdf_trace_msg_cmn(qdf_pidx, module, level, str_format, val);
171 }
172 qdf_export_symbol(qdf_vtrace_msg);
173
174 #define ROW_SIZE 16
175 /* Buffer size = data bytes(2 hex chars plus space) + NULL */
176 #define BUFFER_SIZE ((QDF_DP_TRACE_RECORD_SIZE * 3) + 1)
177
__qdf_trace_hex_dump(QDF_MODULE_ID module,QDF_TRACE_LEVEL level,void * data,int buf_len,bool print_ascii)178 static void __qdf_trace_hex_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
179 void *data, int buf_len, bool print_ascii)
180 {
181 const u8 *ptr = data;
182 int i = 0;
183
184 if (!qdf_print_is_verbose_enabled(qdf_pidx, module, level))
185 return;
186
187 while (buf_len > 0) {
188 unsigned char linebuf[BUFFER_SIZE] = {0};
189 int linelen = min(buf_len, ROW_SIZE);
190
191 buf_len -= ROW_SIZE;
192
193 hex_dump_to_buffer(ptr, linelen, ROW_SIZE, 1,
194 linebuf, sizeof(linebuf), print_ascii);
195
196 qdf_trace_msg(module, level, "%.8x: %s", i, linebuf);
197 ptr += ROW_SIZE;
198 i += ROW_SIZE;
199 }
200 }
201
qdf_trace_hex_dump(QDF_MODULE_ID module,QDF_TRACE_LEVEL level,void * data,int buf_len)202 void qdf_trace_hex_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
203 void *data, int buf_len)
204 {
205 __qdf_trace_hex_dump(module, level, data, buf_len, false);
206 }
207
208 qdf_export_symbol(qdf_trace_hex_dump);
209
qdf_trace_hex_ascii_dump(QDF_MODULE_ID module,QDF_TRACE_LEVEL level,void * data,int buf_len)210 void qdf_trace_hex_ascii_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level,
211 void *data, int buf_len)
212 {
213 __qdf_trace_hex_dump(module, level, data, buf_len, true);
214 }
215
216 qdf_export_symbol(qdf_trace_hex_ascii_dump);
217
218 #endif
219
220 #ifdef TRACE_RECORD
221
222 #ifdef WLAN_LOGGING_BUFFERS_DYNAMICALLY
allocate_g_qdf_trace_tbl_buffer(void)223 static inline QDF_STATUS allocate_g_qdf_trace_tbl_buffer(void)
224 {
225 g_qdf_trace_tbl = qdf_mem_valloc(MAX_QDF_TRACE_RECORDS *
226 sizeof(*g_qdf_trace_tbl));
227 QDF_BUG(g_qdf_trace_tbl);
228 return g_qdf_trace_tbl ? QDF_STATUS_SUCCESS : QDF_STATUS_E_NOMEM;
229 }
230
free_g_qdf_trace_tbl_buffer(void)231 static inline void free_g_qdf_trace_tbl_buffer(void)
232 {
233 qdf_mem_vfree(g_qdf_trace_tbl);
234 g_qdf_trace_tbl = NULL;
235 }
236 #else
allocate_g_qdf_trace_tbl_buffer(void)237 static inline QDF_STATUS allocate_g_qdf_trace_tbl_buffer(void)
238 {
239 return QDF_STATUS_SUCCESS;
240 }
241
free_g_qdf_trace_tbl_buffer(void)242 static inline void free_g_qdf_trace_tbl_buffer(void)
243 { }
244 #endif
qdf_trace_enable(uint32_t bitmask_of_module_id,uint8_t enable)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
qdf_trace_init(void)284 void qdf_trace_init(void)
285 {
286 uint8_t i;
287
288 if (allocate_g_qdf_trace_tbl_buffer() != QDF_STATUS_SUCCESS)
289 return;
290 g_qdf_trace_data.head = INVALID_QDF_TRACE_ADDR;
291 g_qdf_trace_data.tail = INVALID_QDF_TRACE_ADDR;
292 g_qdf_trace_data.num = 0;
293 g_qdf_trace_data.enable = true;
294 g_qdf_trace_data.dump_count = DEFAULT_QDF_TRACE_DUMP_COUNT;
295 g_qdf_trace_data.num_since_last_dump = 0;
296
297 for (i = 0; i < QDF_MODULE_ID_MAX; i++) {
298 qdf_trace_cb_table[i] = NULL;
299 qdf_trace_restore_cb_table[i] = NULL;
300 }
301 }
302 qdf_export_symbol(qdf_trace_init);
303
qdf_trace_deinit(void)304 void qdf_trace_deinit(void)
305 {
306 g_qdf_trace_data.enable = false;
307 g_qdf_trace_data.num = 0;
308 g_qdf_trace_data.head = INVALID_QDF_TRACE_ADDR;
309 g_qdf_trace_data.tail = INVALID_QDF_TRACE_ADDR;
310
311 free_g_qdf_trace_tbl_buffer();
312 }
313
314 qdf_export_symbol(qdf_trace_deinit);
315
qdf_trace(uint8_t module,uint16_t code,uint16_t session,uint32_t data)316 void qdf_trace(uint8_t module, uint16_t code, uint16_t session, uint32_t data)
317 {
318 tp_qdf_trace_record rec = NULL;
319 unsigned long flags;
320 char time[18];
321
322 if (!g_qdf_trace_data.enable)
323 return;
324
325 /* if module is not registered, don't record for that module */
326 if (!qdf_trace_cb_table[module])
327 return;
328
329 qdf_get_time_of_the_day_in_hr_min_sec_usec(time, sizeof(time));
330 /* Acquire the lock so that only one thread at a time can fill the ring
331 * buffer
332 */
333 spin_lock_irqsave(<race_lock, flags);
334
335 g_qdf_trace_data.num++;
336
337 if (g_qdf_trace_data.num > MAX_QDF_TRACE_RECORDS)
338 g_qdf_trace_data.num = MAX_QDF_TRACE_RECORDS;
339
340 if (INVALID_QDF_TRACE_ADDR == g_qdf_trace_data.head) {
341 /* first record */
342 g_qdf_trace_data.head = 0;
343 g_qdf_trace_data.tail = 0;
344 } else {
345 /* queue is not empty */
346 uint32_t tail = g_qdf_trace_data.tail + 1;
347
348 if (MAX_QDF_TRACE_RECORDS == tail)
349 tail = 0;
350
351 if (g_qdf_trace_data.head == tail) {
352 /* full */
353 if (MAX_QDF_TRACE_RECORDS == ++g_qdf_trace_data.head)
354 g_qdf_trace_data.head = 0;
355 }
356 g_qdf_trace_data.tail = tail;
357 }
358
359 rec = &g_qdf_trace_tbl[g_qdf_trace_data.tail];
360 rec->code = code;
361 rec->session = session;
362 rec->data = data;
363 rec->qtime = qdf_get_log_timestamp();
364 scnprintf(rec->time, sizeof(rec->time), "%s", time);
365 rec->module = module;
366 rec->pid = (in_interrupt() ? 0 : current->pid);
367 g_qdf_trace_data.num_since_last_dump++;
368 spin_unlock_irqrestore(<race_lock, flags);
369 }
370 qdf_export_symbol(qdf_trace);
371
372 #ifdef ENABLE_MTRACE_LOG
qdf_mtrace_log(QDF_MODULE_ID src_module,QDF_MODULE_ID dst_module,uint16_t message_id,uint8_t vdev_id)373 void qdf_mtrace_log(QDF_MODULE_ID src_module, QDF_MODULE_ID dst_module,
374 uint16_t message_id, uint8_t vdev_id)
375 {
376 uint32_t trace_log, payload;
377 static uint16_t counter;
378
379 trace_log = (src_module << 23) | (dst_module << 15) | message_id;
380 payload = (vdev_id << 16) | counter++;
381
382 QDF_TRACE(src_module, QDF_TRACE_LEVEL_TRACE, "%x %x",
383 trace_log, payload);
384 }
385
386 qdf_export_symbol(qdf_mtrace_log);
387 #endif
388
qdf_mtrace(QDF_MODULE_ID src_module,QDF_MODULE_ID dst_module,uint16_t message_id,uint8_t vdev_id,uint32_t data)389 void qdf_mtrace(QDF_MODULE_ID src_module, QDF_MODULE_ID dst_module,
390 uint16_t message_id, uint8_t vdev_id, uint32_t data)
391 {
392 qdf_trace(src_module, message_id, vdev_id, data);
393 qdf_mtrace_log(src_module, dst_module, message_id, vdev_id);
394 }
395
396 qdf_export_symbol(qdf_mtrace);
397
qdf_trace_spin_lock_init(void)398 QDF_STATUS qdf_trace_spin_lock_init(void)
399 {
400 spin_lock_init(<race_lock);
401
402 return QDF_STATUS_SUCCESS;
403 }
404 qdf_export_symbol(qdf_trace_spin_lock_init);
405
qdf_trace_register(QDF_MODULE_ID module_id,tp_qdf_trace_cb qdf_trace_callback)406 void qdf_trace_register(QDF_MODULE_ID module_id,
407 tp_qdf_trace_cb qdf_trace_callback)
408 {
409 qdf_trace_cb_table[module_id] = qdf_trace_callback;
410 }
411 qdf_export_symbol(qdf_trace_register);
412
qdf_trace_dump_all(void * p_mac,uint8_t code,uint8_t session,uint32_t count,uint32_t bitmask_of_module)413 void qdf_trace_dump_all(void *p_mac, uint8_t code, uint8_t session,
414 uint32_t count, uint32_t bitmask_of_module)
415 {
416 qdf_trace_record_t p_record;
417 int32_t i, tail;
418
419 if (!g_qdf_trace_data.enable) {
420 QDF_TRACE(QDF_MODULE_ID_SYS,
421 QDF_TRACE_LEVEL_ERROR, "Tracing Disabled");
422 return;
423 }
424
425 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_INFO,
426 "DPT: Total Records: %d, Head: %d, Tail: %d",
427 g_qdf_trace_data.num, g_qdf_trace_data.head,
428 g_qdf_trace_data.tail);
429
430 /* acquire the lock so that only one thread at a time can read
431 * the ring buffer
432 */
433 spin_lock(<race_lock);
434
435 if (g_qdf_trace_data.head != INVALID_QDF_TRACE_ADDR) {
436 i = g_qdf_trace_data.head;
437 tail = g_qdf_trace_data.tail;
438
439 if (count) {
440 if (count > g_qdf_trace_data.num)
441 count = g_qdf_trace_data.num;
442 if (tail >= (count - 1))
443 i = tail - count + 1;
444 else if (count != MAX_QDF_TRACE_RECORDS)
445 i = MAX_QDF_TRACE_RECORDS - ((count - 1) -
446 tail);
447 }
448
449 p_record = g_qdf_trace_tbl[i];
450 /* right now we are not using num_since_last_dump member but
451 * in future we might re-visit and use this member to track
452 * how many latest messages got added while we were dumping
453 * from ring buffer
454 */
455 g_qdf_trace_data.num_since_last_dump = 0;
456 spin_unlock(<race_lock);
457 for (;; ) {
458 if ((code == 0 || (code == p_record.code)) &&
459 (qdf_trace_cb_table[p_record.module])) {
460 if (0 == bitmask_of_module) {
461 qdf_trace_cb_table[p_record.
462 module] (p_mac,
463 &p_record,
464 (uint16_t)
465 i);
466 } else {
467 if (bitmask_of_module &
468 (1 << p_record.module)) {
469 qdf_trace_cb_table[p_record.
470 module]
471 (p_mac, &p_record,
472 (uint16_t) i);
473 }
474 }
475 }
476
477 if (i == tail)
478 break;
479 i += 1;
480
481 spin_lock(<race_lock);
482 if (MAX_QDF_TRACE_RECORDS == i) {
483 i = 0;
484 p_record = g_qdf_trace_tbl[0];
485 } else {
486 p_record = g_qdf_trace_tbl[i];
487 }
488 spin_unlock(<race_lock);
489 }
490 } else {
491 spin_unlock(<race_lock);
492 }
493 }
494 qdf_export_symbol(qdf_trace_dump_all);
495 #endif
496
497 #ifdef WLAN_FEATURE_MEMDUMP_ENABLE
qdf_register_debugcb_init(void)498 void qdf_register_debugcb_init(void)
499 {
500 uint8_t i;
501
502 for (i = 0; i < QDF_MODULE_ID_MAX; i++)
503 qdf_state_info_table[i] = NULL;
504 }
505 qdf_export_symbol(qdf_register_debugcb_init);
506
qdf_register_debug_callback(QDF_MODULE_ID module_id,tp_qdf_state_info_cb qdf_state_infocb)507 void qdf_register_debug_callback(QDF_MODULE_ID module_id,
508 tp_qdf_state_info_cb qdf_state_infocb)
509 {
510 qdf_state_info_table[module_id] = qdf_state_infocb;
511 }
512 qdf_export_symbol(qdf_register_debug_callback);
513
qdf_state_info_dump_all(char * buf,uint16_t size,uint16_t * driver_dump_size)514 QDF_STATUS qdf_state_info_dump_all(char *buf, uint16_t size,
515 uint16_t *driver_dump_size)
516 {
517 uint8_t module, ret = QDF_STATUS_SUCCESS;
518 uint16_t buf_len = size;
519 char *buf_ptr = buf;
520
521 for (module = 0; module < QDF_MODULE_ID_MAX; module++) {
522 if (qdf_state_info_table[module]) {
523 qdf_state_info_table[module](&buf_ptr, &buf_len);
524 if (!buf_len) {
525 ret = QDF_STATUS_E_NOMEM;
526 break;
527 }
528 }
529 }
530
531 *driver_dump_size = size - buf_len;
532 return ret;
533 }
534 qdf_export_symbol(qdf_state_info_dump_all);
535 #endif
536
537 #ifdef CONFIG_DP_TRACE
538
539 #ifdef WLAN_LOGGING_BUFFERS_DYNAMICALLY
allocate_g_qdf_dp_trace_tbl_buffer(void)540 static inline QDF_STATUS allocate_g_qdf_dp_trace_tbl_buffer(void)
541 {
542 g_qdf_dp_trace_tbl = qdf_mem_valloc(MAX_QDF_DP_TRACE_RECORDS *
543 sizeof(*g_qdf_dp_trace_tbl));
544 QDF_BUG(g_qdf_dp_trace_tbl);
545 return g_qdf_dp_trace_tbl ? QDF_STATUS_SUCCESS : QDF_STATUS_E_NOMEM;
546 }
547
free_g_qdf_dp_trace_tbl_buffer(void)548 static inline void free_g_qdf_dp_trace_tbl_buffer(void)
549 {
550 qdf_mem_vfree(g_qdf_dp_trace_tbl);
551 g_qdf_dp_trace_tbl = NULL;
552 }
553 #else
allocate_g_qdf_dp_trace_tbl_buffer(void)554 static inline QDF_STATUS allocate_g_qdf_dp_trace_tbl_buffer(void)
555 {
556 return QDF_STATUS_SUCCESS;
557 }
558
free_g_qdf_dp_trace_tbl_buffer(void)559 static inline void free_g_qdf_dp_trace_tbl_buffer(void)
560 { }
561 #endif
562
563 #define QDF_DP_TRACE_PREPEND_STR_SIZE 100
564 /*
565 * one dp trace record can't be greater than 300 bytes.
566 * Max Size will be QDF_DP_TRACE_PREPEND_STR_SIZE(100) + BUFFER_SIZE(121).
567 * Always make sure to change this QDF_DP_TRACE_MAX_RECORD_SIZE
568 * value accordingly whenever above two mentioned MACRO value changes.
569 */
570 #define QDF_DP_TRACE_MAX_RECORD_SIZE 300
571
qdf_dp_unused(struct qdf_dp_trace_record_s * record,uint16_t index,uint8_t pdev_id,uint8_t info)572 static void qdf_dp_unused(struct qdf_dp_trace_record_s *record,
573 uint16_t index, uint8_t pdev_id, uint8_t info)
574 {
575 qdf_print("%s: QDF_DP_TRACE_MAX event should not be generated",
576 __func__);
577 }
578
qdf_dp_trace_init(bool live_mode_config,uint8_t thresh,uint16_t time_limit,uint8_t verbosity,uint32_t proto_bitmap)579 void qdf_dp_trace_init(bool live_mode_config, uint8_t thresh,
580 uint16_t time_limit, uint8_t verbosity,
581 uint32_t proto_bitmap)
582 {
583 uint8_t i;
584
585 if (allocate_g_qdf_dp_trace_tbl_buffer() != QDF_STATUS_SUCCESS) {
586 QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
587 "Failed!!! DP Trace buffer allocation");
588 return;
589 }
590 qdf_dp_trace_spin_lock_init();
591 qdf_dp_trace_clear_buffer();
592 g_qdf_dp_trace_data.enable = true;
593 g_qdf_dp_trace_data.no_of_record = 1;
594
595 g_qdf_dp_trace_data.live_mode_config = live_mode_config;
596 g_qdf_dp_trace_data.live_mode = live_mode_config;
597 g_qdf_dp_trace_data.high_tput_thresh = thresh;
598 g_qdf_dp_trace_data.thresh_time_limit = time_limit;
599 g_qdf_dp_trace_data.proto_bitmap = proto_bitmap;
600 g_qdf_dp_trace_data.verbosity = verbosity;
601 g_qdf_dp_trace_data.ini_conf_verbosity = verbosity;
602
603 for (i = 0; i < ARRAY_SIZE(qdf_dp_trace_cb_table); i++)
604 qdf_dp_trace_cb_table[i] = qdf_dp_display_record;
605
606 qdf_dp_trace_cb_table[QDF_DP_TRACE_HDD_TX_PACKET_RECORD] =
607 qdf_dp_trace_cb_table[QDF_DP_TRACE_HDD_RX_PACKET_RECORD] =
608 qdf_dp_trace_cb_table[QDF_DP_TRACE_TX_PACKET_RECORD] =
609 qdf_dp_trace_cb_table[QDF_DP_TRACE_RX_PACKET_RECORD] =
610 qdf_dp_trace_cb_table[QDF_DP_TRACE_DROP_PACKET_RECORD] =
611 qdf_dp_trace_cb_table[QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD] =
612 qdf_dp_trace_cb_table[QDF_DP_TRACE_LI_DP_RX_PACKET_RECORD] =
613 qdf_dp_display_data_pkt_record;
614
615 qdf_dp_trace_cb_table[QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD] =
616 qdf_dp_trace_cb_table[QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD] =
617 qdf_dp_trace_cb_table[QDF_DP_TRACE_FREE_PACKET_PTR_RECORD] =
618 qdf_dp_trace_cb_table[QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD] =
619 qdf_dp_display_ptr_record;
620 qdf_dp_trace_cb_table[QDF_DP_TRACE_EAPOL_PACKET_RECORD] =
621 qdf_dp_trace_cb_table[QDF_DP_TRACE_DHCP_PACKET_RECORD] =
622 qdf_dp_trace_cb_table[QDF_DP_TRACE_ARP_PACKET_RECORD] =
623 qdf_dp_trace_cb_table[QDF_DP_TRACE_ICMP_PACKET_RECORD] =
624 qdf_dp_trace_cb_table[QDF_DP_TRACE_ICMPv6_PACKET_RECORD] =
625 qdf_dp_display_proto_pkt;
626 qdf_dp_trace_cb_table[QDF_DP_TRACE_MGMT_PACKET_RECORD] =
627 qdf_dp_display_mgmt_pkt;
628 qdf_dp_trace_cb_table[QDF_DP_TRACE_TX_CREDIT_RECORD] =
629 qdf_dp_display_credit_record;
630 qdf_dp_trace_cb_table[QDF_DP_TRACE_EVENT_RECORD] =
631 qdf_dp_display_event_record;
632
633 qdf_dp_trace_cb_table[QDF_DP_TRACE_MAX] = qdf_dp_unused;
634 }
635 qdf_export_symbol(qdf_dp_trace_init);
636
qdf_dp_trace_deinit(void)637 void qdf_dp_trace_deinit(void)
638 {
639 if (!g_qdf_dp_trace_data.enable)
640 return;
641 spin_lock_bh(&l_dp_trace_lock);
642 g_qdf_dp_trace_data.enable = false;
643 g_qdf_dp_trace_data.no_of_record = 0;
644 spin_unlock_bh(&l_dp_trace_lock);
645
646 free_g_qdf_dp_trace_tbl_buffer();
647 }
648
qdf_dp_trace_set_value(uint32_t proto_bitmap,uint8_t no_of_record,uint8_t verbosity)649 void qdf_dp_trace_set_value(uint32_t proto_bitmap, uint8_t no_of_record,
650 uint8_t verbosity)
651 {
652 g_qdf_dp_trace_data.proto_bitmap = proto_bitmap;
653 g_qdf_dp_trace_data.no_of_record = no_of_record;
654 g_qdf_dp_trace_data.verbosity = verbosity;
655 g_qdf_dp_trace_data.dynamic_verbosity_modify = true;
656 }
657 qdf_export_symbol(qdf_dp_trace_set_value);
658
qdf_dp_trace_set_verbosity(uint32_t val)659 void qdf_dp_trace_set_verbosity(uint32_t val)
660 {
661 g_qdf_dp_trace_data.verbosity = val;
662 }
663 qdf_export_symbol(qdf_dp_trace_set_verbosity);
664
665 /**
666 * qdf_dp_get_verbosity() - get verbosity value
667 *
668 * Return: int
669 */
qdf_dp_get_verbosity(void)670 uint8_t qdf_dp_get_verbosity(void)
671 {
672 return g_qdf_dp_trace_data.verbosity;
673 }
674 qdf_export_symbol(qdf_dp_get_verbosity);
675
qdf_dp_set_proto_bitmap(uint32_t val)676 void qdf_dp_set_proto_bitmap(uint32_t val)
677 {
678 g_qdf_dp_trace_data.proto_bitmap = val;
679 }
680 qdf_export_symbol(qdf_dp_set_proto_bitmap);
681
qdf_dp_set_proto_event_bitmap(uint32_t value)682 void qdf_dp_set_proto_event_bitmap(uint32_t value)
683 {
684 g_qdf_dp_trace_data.proto_event_bitmap = value;
685 }
686
687 qdf_export_symbol(qdf_dp_set_proto_event_bitmap);
688
qdf_dp_get_proto_event_bitmap(void)689 static uint32_t qdf_dp_get_proto_event_bitmap(void)
690 {
691 return g_qdf_dp_trace_data.proto_event_bitmap;
692 }
693
qdf_dp_set_no_of_record(uint32_t val)694 void qdf_dp_set_no_of_record(uint32_t val)
695 {
696 g_qdf_dp_trace_data.no_of_record = val;
697 }
698 qdf_export_symbol(qdf_dp_set_no_of_record);
699
qdf_dp_get_no_of_record(void)700 uint8_t qdf_dp_get_no_of_record(void)
701 {
702 return g_qdf_dp_trace_data.no_of_record;
703 }
704 qdf_export_symbol(qdf_dp_get_no_of_record);
705
706
707 /**
708 * qdf_dp_trace_verbosity_check() - check whether verbosity level is enabled
709 * @code: defines the event
710 *
711 * In High verbosity all codes are logged.
712 * For Med/Low and Default case code which has
713 * less value than corresponding verbosity codes
714 * are logged.
715 *
716 * Return: true or false depends on whether tracing enabled
717 */
qdf_dp_trace_verbosity_check(enum QDF_DP_TRACE_ID code)718 static bool qdf_dp_trace_verbosity_check(enum QDF_DP_TRACE_ID code)
719 {
720 switch (g_qdf_dp_trace_data.verbosity) {
721 case QDF_DP_TRACE_VERBOSITY_HIGH:
722 return true;
723 case QDF_DP_TRACE_VERBOSITY_MEDIUM:
724 if (code <= QDF_DP_TRACE_MED_VERBOSITY)
725 return true;
726 return false;
727 case QDF_DP_TRACE_VERBOSITY_LOW:
728 if (code <= QDF_DP_TRACE_LOW_VERBOSITY)
729 return true;
730 return false;
731 case QDF_DP_TRACE_VERBOSITY_ULTRA_LOW:
732 if (code <= QDF_DP_TRACE_ULTRA_LOW_VERBOSITY)
733 return true;
734 return false;
735 case QDF_DP_TRACE_VERBOSITY_BASE:
736 if (code <= QDF_DP_TRACE_BASE_VERBOSITY)
737 return true;
738 return false;
739 default:
740 return false;
741 }
742 }
743
qdf_dp_get_proto_bitmap(void)744 uint32_t qdf_dp_get_proto_bitmap(void)
745 {
746 if (g_qdf_dp_trace_data.enable)
747 return g_qdf_dp_trace_data.proto_bitmap;
748 else
749 return 0;
750 }
751
qdf_dp_trace_set_track(qdf_nbuf_t nbuf,enum qdf_proto_dir dir)752 void qdf_dp_trace_set_track(qdf_nbuf_t nbuf, enum qdf_proto_dir dir)
753 {
754 uint32_t count = 0;
755
756 if (!g_qdf_dp_trace_data.enable)
757 return;
758
759 spin_lock_bh(&l_dp_trace_lock);
760 if (QDF_TX == dir)
761 count = ++g_qdf_dp_trace_data.tx_count;
762 else if (QDF_RX == dir)
763 count = ++g_qdf_dp_trace_data.rx_count;
764
765 if ((g_qdf_dp_trace_data.no_of_record != 0) &&
766 (count % g_qdf_dp_trace_data.no_of_record == 0)) {
767 if (QDF_TX == dir)
768 QDF_NBUF_CB_TX_DP_TRACE(nbuf) = 1;
769 else if (QDF_RX == dir)
770 QDF_NBUF_CB_RX_DP_TRACE(nbuf) = 1;
771 }
772 spin_unlock_bh(&l_dp_trace_lock);
773 }
774 qdf_export_symbol(qdf_dp_trace_set_track);
775
776 /* Number of bytes to be grouped together while printing DP-Trace data */
777 #define QDF_DUMP_DP_GROUP_SIZE 6
778
779 /**
780 * dump_dp_hex_trace() - Display the data in buffer
781 * @prepend_str: string to prepend the hexdump with.
782 * @inbuf: buffer which contains data to be displayed
783 * @inbuf_len: defines the size of the data to be displayed
784 *
785 * Return: None
786 */
787 static void
dump_dp_hex_trace(char * prepend_str,uint8_t * inbuf,uint8_t inbuf_len)788 dump_dp_hex_trace(char *prepend_str, uint8_t *inbuf, uint8_t inbuf_len)
789 {
790 unsigned char outbuf[BUFFER_SIZE];
791 const uint8_t *inbuf_ptr = inbuf;
792 char *outbuf_ptr = outbuf;
793 int outbytes_written = 0;
794
795 qdf_mem_zero(outbuf, sizeof(outbuf));
796 do {
797 outbytes_written += scnprintf(outbuf_ptr,
798 BUFFER_SIZE - outbytes_written,
799 "%02x", *inbuf_ptr);
800 outbuf_ptr = outbuf + outbytes_written;
801
802 if ((inbuf_ptr - inbuf) &&
803 (inbuf_ptr - inbuf + 1) % QDF_DUMP_DP_GROUP_SIZE == 0) {
804 outbytes_written += scnprintf(outbuf_ptr,
805 BUFFER_SIZE - outbytes_written,
806 " ");
807 outbuf_ptr = outbuf + outbytes_written;
808 }
809 inbuf_ptr++;
810 } while (inbuf_ptr < (inbuf + inbuf_len));
811 DPTRACE_PRINT("%s %s", prepend_str, outbuf);
812 }
813
814 /**
815 * qdf_dp_code_to_string() - convert dptrace code to string
816 * @code: dptrace code
817 *
818 * Return: string version of code
819 */
820 static
qdf_dp_code_to_string(enum QDF_DP_TRACE_ID code)821 const char *qdf_dp_code_to_string(enum QDF_DP_TRACE_ID code)
822 {
823 switch (code) {
824 case QDF_DP_TRACE_DROP_PACKET_RECORD:
825 return "DROP:";
826 case QDF_DP_TRACE_EAPOL_PACKET_RECORD:
827 return "EAPOL:";
828 case QDF_DP_TRACE_DHCP_PACKET_RECORD:
829 return "DHCP:";
830 case QDF_DP_TRACE_ARP_PACKET_RECORD:
831 return "ARP:";
832 case QDF_DP_TRACE_ICMP_PACKET_RECORD:
833 return "ICMP:";
834 case QDF_DP_TRACE_ICMPv6_PACKET_RECORD:
835 return "ICMPv6:";
836 case QDF_DP_TRACE_MGMT_PACKET_RECORD:
837 return "MGMT:";
838 case QDF_DP_TRACE_TX_CREDIT_RECORD:
839 return "CREDIT:";
840 case QDF_DP_TRACE_EVENT_RECORD:
841 return "EVENT:";
842 case QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD:
843 return "HDD: TX: PTR:";
844 case QDF_DP_TRACE_LI_DP_TX_PACKET_PTR_RECORD:
845 return "LI_DP: TX: PTR:";
846 case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
847 return "HDD: TX: DATA:";
848 case QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD:
849 case QDF_DP_TRACE_TX_PACKET_RECORD:
850 return "TX:";
851 case QDF_DP_TRACE_CE_PACKET_PTR_RECORD:
852 return "CE: TX: PTR:";
853 case QDF_DP_TRACE_CE_FAST_PACKET_PTR_RECORD:
854 return "CE: TX: FAST: PTR:";
855 case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
856 return "CE: TX: FAST: ERR:";
857 case QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD:
858 case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD:
859 return "FREE: TX: PTR:";
860 case QDF_DP_TRACE_RX_HTT_PACKET_PTR_RECORD:
861 return "HTT: RX: PTR:";
862 case QDF_DP_TRACE_RX_OFFLOAD_HTT_PACKET_PTR_RECORD:
863 return "HTT: RX: OF: PTR:";
864 case QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD:
865 return "HDD: RX: PTR:";
866 case QDF_DP_TRACE_RX_LI_DP_PACKET_PTR_RECORD:
867 return "LI_DP: RX: PTR:";
868 case QDF_DP_TRACE_HDD_RX_PACKET_RECORD:
869 return "HDD: RX: DATA:";
870 case QDF_DP_TRACE_LI_DP_NULL_RX_PACKET_RECORD:
871 return "LI_DP_NULL: RX: DATA:";
872 case QDF_DP_TRACE_LI_DP_RX_PACKET_RECORD:
873 case QDF_DP_TRACE_RX_PACKET_RECORD:
874 return "RX:";
875 case QDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD:
876 return "TXRX: TX: Q: PTR:";
877 case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD:
878 return "TXRX: TX: PTR:";
879 case QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD:
880 return "TXRX: TX: FAST: PTR:";
881 case QDF_DP_TRACE_HTT_PACKET_PTR_RECORD:
882 return "HTT: TX: PTR:";
883 case QDF_DP_TRACE_HTC_PACKET_PTR_RECORD:
884 return "HTC: TX: PTR:";
885 case QDF_DP_TRACE_HIF_PACKET_PTR_RECORD:
886 return "HIF: TX: PTR:";
887 case QDF_DP_TRACE_RX_TXRX_PACKET_PTR_RECORD:
888 return "TXRX: RX: PTR:";
889 case QDF_DP_TRACE_HDD_TX_TIMEOUT:
890 return "HDD: STA: TO:";
891 case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
892 return "HDD: SAP: TO:";
893 default:
894 return "Invalid";
895 }
896 }
897
898 /**
899 * qdf_dp_dir_to_str() - convert direction to string
900 * @dir: direction
901 *
902 * Return: string version of direction
903 */
qdf_dp_dir_to_str(enum qdf_proto_dir dir)904 static const char *qdf_dp_dir_to_str(enum qdf_proto_dir dir)
905 {
906 switch (dir) {
907 case QDF_TX:
908 return " --> ";
909 case QDF_RX:
910 return " <-- ";
911 default:
912 return "invalid";
913 }
914 }
915
qdf_dp_credit_source_to_str(enum QDF_CREDIT_UPDATE_SOURCE source)916 static const char *qdf_dp_credit_source_to_str(
917 enum QDF_CREDIT_UPDATE_SOURCE source)
918 {
919 switch (source) {
920 case QDF_TX_SCHED:
921 return "TX SCHED";
922 case QDF_TX_COMP:
923 return "TX COMP";
924 case QDF_TX_CREDIT_UPDATE:
925 return "CREDIT UP";
926 case QDF_TX_HTT_MSG:
927 return "HTT TX MSG";
928 case QDF_HTT_ATTACH:
929 return "HTT ATTACH";
930 default:
931 return "invalid";
932 }
933 }
934
qdf_dp_operation_to_str(enum QDF_CREDIT_OPERATION op)935 static const char *qdf_dp_operation_to_str(enum QDF_CREDIT_OPERATION op)
936 {
937 switch (op) {
938 case QDF_CREDIT_INC:
939 return "+";
940 case QDF_CREDIT_DEC:
941 return "-";
942 case QDF_CREDIT_ABS:
943 return "ABS";
944 default:
945 return "invalid";
946 }
947 }
948
949 /**
950 * qdf_dp_type_to_str() - convert packet type to string
951 * @type: type
952 *
953 * Return: string version of packet type
954 */
qdf_dp_type_to_str(enum qdf_proto_type type)955 static const char *qdf_dp_type_to_str(enum qdf_proto_type type)
956 {
957 switch (type) {
958 case QDF_PROTO_TYPE_DHCP:
959 return "DHCP";
960 case QDF_PROTO_TYPE_EAPOL:
961 return "EAPOL";
962 case QDF_PROTO_TYPE_ARP:
963 return "ARP";
964 case QDF_PROTO_TYPE_ICMP:
965 return "ICMP";
966 case QDF_PROTO_TYPE_ICMPv6:
967 return "ICMPv6";
968 case QDF_PROTO_TYPE_MGMT:
969 return "MGMT";
970 case QDF_PROTO_TYPE_EVENT:
971 return "EVENT";
972 default:
973 return "invalid";
974 }
975 }
976
977 /**
978 * qdf_dp_subtype_to_str() - convert packet subtype to string
979 * @subtype: subtype
980 *
981 * Return: string version of packet subtype
982 */
qdf_dp_subtype_to_str(enum qdf_proto_subtype subtype)983 static const char *qdf_dp_subtype_to_str(enum qdf_proto_subtype subtype)
984 {
985 switch (subtype) {
986 case QDF_PROTO_EAPOL_M1:
987 return "M1";
988 case QDF_PROTO_EAPOL_M2:
989 return "M2";
990 case QDF_PROTO_EAPOL_M3:
991 return "M3";
992 case QDF_PROTO_EAPOL_M4:
993 return "M4";
994 case QDF_PROTO_DHCP_DISCOVER:
995 return "DISC";
996 case QDF_PROTO_DHCP_REQUEST:
997 return "REQ";
998 case QDF_PROTO_DHCP_OFFER:
999 return "OFF";
1000 case QDF_PROTO_DHCP_ACK:
1001 return "ACK";
1002 case QDF_PROTO_DHCP_NACK:
1003 return "NACK";
1004 case QDF_PROTO_DHCP_RELEASE:
1005 return "REL";
1006 case QDF_PROTO_DHCP_INFORM:
1007 return "INFORM";
1008 case QDF_PROTO_DHCP_DECLINE:
1009 return "DECL";
1010 case QDF_PROTO_ARP_REQ:
1011 case QDF_PROTO_ICMP_REQ:
1012 case QDF_PROTO_ICMPV6_REQ:
1013 return "REQ";
1014 case QDF_PROTO_ARP_RES:
1015 case QDF_PROTO_ICMP_RES:
1016 case QDF_PROTO_ICMPV6_RES:
1017 return "RSP";
1018 case QDF_PROTO_ICMPV6_RS:
1019 return "RS";
1020 case QDF_PROTO_ICMPV6_RA:
1021 return "RA";
1022 case QDF_PROTO_ICMPV6_NS:
1023 return "NS";
1024 case QDF_PROTO_ICMPV6_NA:
1025 return "NA";
1026 case QDF_PROTO_MGMT_ASSOC:
1027 return "ASSOC";
1028 case QDF_PROTO_MGMT_DISASSOC:
1029 return "DISASSOC";
1030 case QDF_PROTO_MGMT_AUTH:
1031 return "AUTH";
1032 case QDF_PROTO_MGMT_DEAUTH:
1033 return "DEAUTH";
1034 case QDF_ROAM_SYNCH:
1035 return "ROAM SYNCH";
1036 case QDF_ROAM_COMPLETE:
1037 return "ROAM COMP";
1038 case QDF_ROAM_EVENTID:
1039 return "ROAM EVENTID";
1040 case QDF_PROTO_EAP_REQUEST:
1041 return "EAP REQ";
1042 case QDF_PROTO_EAP_RESPONSE:
1043 return "EAP RSP";
1044 case QDF_PROTO_EAP_SUCCESS:
1045 return "EAP SUC";
1046 case QDF_PROTO_EAP_FAILURE:
1047 return "EAP FAIL";
1048 case QDF_PROTO_EAP_INITIATE:
1049 return "EAP INIT";
1050 case QDF_PROTO_EAP_FINISH:
1051 return "EAP FINISH";
1052 case QDF_PROTO_EAPOL_START:
1053 return "START";
1054 case QDF_PROTO_EAPOL_LOGOFF:
1055 return "LOGOFF";
1056 case QDF_PROTO_EAPOL_ASF:
1057 return "ASF";
1058 case QDF_PROTO_EAP_REQ_ID:
1059 return "EAP REQ ID";
1060 case QDF_PROTO_EAP_RSP_ID:
1061 return "EAP RSP ID";
1062 case QDF_PROTO_EAP_M1:
1063 return "EAP M1";
1064 case QDF_PROTO_EAP_M2:
1065 return "EAP M2";
1066 case QDF_PROTO_EAP_M3:
1067 return "EAP M3";
1068 case QDF_PROTO_EAP_M4:
1069 return "EAP M4";
1070 case QDF_PROTO_EAP_M5:
1071 return "EAP M5";
1072 case QDF_PROTO_EAP_M6:
1073 return "EAP M6";
1074 case QDF_PROTO_EAP_M7:
1075 return "EAP M7";
1076 case QDF_PROTO_EAP_M8:
1077 return "EAP M8";
1078 case QDF_PROTO_EAP_WSC_START:
1079 return "EAP WSC START";
1080 case QDF_PROTO_EAP_WSC_DONE:
1081 return "EAP WSC DONE";
1082 case QDF_PROTO_EAP_WSC_ACK:
1083 return "EAP WSC ACK";
1084 case QDF_PROTO_EAP_WSC_NACK:
1085 return "EAP WSC NACK";
1086 case QDF_PROTO_EAP_WSC_FRAG_ACK:
1087 return "EAP WSC FRAG ACK";
1088 default:
1089 return "invalid";
1090 }
1091 }
1092
1093 /**
1094 * qdf_dp_enable_check() - check if dptrace, TX/RX tracing is enabled
1095 * @nbuf: nbuf
1096 * @code: dptrace code
1097 * @dir: TX or RX direction
1098 *
1099 * Return: true/false
1100 */
qdf_dp_enable_check(qdf_nbuf_t nbuf,enum QDF_DP_TRACE_ID code,enum qdf_proto_dir dir)1101 static bool qdf_dp_enable_check(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
1102 enum qdf_proto_dir dir)
1103 {
1104 /* Return when Dp trace is not enabled */
1105 if (!g_qdf_dp_trace_data.enable)
1106 return false;
1107
1108 if (qdf_dp_trace_verbosity_check(code) == false)
1109 return false;
1110
1111 if (nbuf && (dir == QDF_TX && ((QDF_NBUF_CB_TX_DP_TRACE(nbuf) == 0) ||
1112 (QDF_NBUF_CB_TX_PACKET_TRACK(nbuf) !=
1113 QDF_NBUF_TX_PKT_DATA_TRACK))))
1114 return false;
1115
1116 if (nbuf && (dir == QDF_RX && (QDF_NBUF_CB_RX_DP_TRACE(nbuf) == 0)))
1117 return false;
1118
1119 /*
1120 * Special packets called with NULL nbuf and this API is expected to
1121 * return true
1122 */
1123 return true;
1124 }
1125
1126 /**
1127 * qdf_dp_trace_fill_meta_str() - fill up a common meta string
1128 * @prepend_str: pointer to string
1129 * @size: size of prepend_str
1130 * @rec_index: index of record
1131 * @info: info related to the record
1132 * @record: pointer to the record
1133 *
1134 * Return: ret value from scnprintf
1135 */
1136 static inline
qdf_dp_trace_fill_meta_str(char * prepend_str,int size,int rec_index,uint8_t info,struct qdf_dp_trace_record_s * record)1137 int qdf_dp_trace_fill_meta_str(char *prepend_str, int size,
1138 int rec_index, uint8_t info,
1139 struct qdf_dp_trace_record_s *record)
1140 {
1141 char buffer[20];
1142 int ret = 0;
1143 bool live = info & QDF_DP_TRACE_RECORD_INFO_LIVE ? true : false;
1144 bool throttled = info & QDF_DP_TRACE_RECORD_INFO_THROTTLED ?
1145 true : false;
1146
1147 scnprintf(buffer, sizeof(buffer), "%llu", record->time);
1148 ret = scnprintf(prepend_str, size,
1149 "%s DPT: %04d:%02d%s %s",
1150 throttled ? "*" : "",
1151 rec_index,
1152 record->pdev_id,
1153 live ? "" : buffer,
1154 qdf_dp_code_to_string(record->code));
1155
1156 return ret;
1157 }
1158
1159 /**
1160 * qdf_dp_fill_record_data() - fill meta data and data into the record
1161 * @rec: pointer to record data
1162 * @data: pointer to data
1163 * @data_size: size of the data
1164 * @meta_data: pointer to metadata
1165 * @metadata_size: size of metadata
1166 *
1167 * Should be called from within a spin_lock for the qdf record.
1168 * Fills up rec->data with |metadata|data|
1169 *
1170 * Return: none
1171 */
qdf_dp_fill_record_data(struct qdf_dp_trace_record_s * rec,uint8_t * data,uint8_t data_size,uint8_t * meta_data,uint8_t metadata_size)1172 static void qdf_dp_fill_record_data
1173 (struct qdf_dp_trace_record_s *rec,
1174 uint8_t *data, uint8_t data_size,
1175 uint8_t *meta_data, uint8_t metadata_size)
1176 {
1177 int32_t available = QDF_DP_TRACE_RECORD_SIZE;
1178 uint8_t *rec_data = rec->data;
1179 uint8_t data_to_copy = 0;
1180
1181 qdf_mem_zero(rec_data, QDF_DP_TRACE_RECORD_SIZE);
1182
1183 /* copy meta data */
1184 if (meta_data) {
1185 if (metadata_size > available) {
1186 QDF_TRACE_WARN(QDF_MODULE_ID_QDF,
1187 "%s: meta data does not fit into the record",
1188 __func__);
1189 goto end;
1190 }
1191 qdf_mem_copy(rec_data, meta_data, metadata_size);
1192 available = available - metadata_size;
1193 } else {
1194 metadata_size = 0;
1195 }
1196
1197 /* copy data */
1198 if (data && (data_size > 0) && (available > 0)) {
1199 data_to_copy = data_size;
1200 if (data_size > available)
1201 data_to_copy = available;
1202 qdf_mem_copy(&rec_data[metadata_size], data, data_to_copy);
1203 }
1204 end:
1205 rec->size = data_to_copy;
1206 }
1207
1208 /**
1209 * qdf_dp_add_record() - add dp trace record
1210 * @code: dptrace code
1211 * @pdev_id: pdev_id
1212 * @print: true to print it in kmsg
1213 * @data: data pointer
1214 * @data_size: size of data to be copied
1215 * @meta_data: meta data to be prepended to data
1216 * @metadata_size: sizeof meta data
1217 * @print: whether to print record
1218 *
1219 * Return: none
1220 */
qdf_dp_add_record(enum QDF_DP_TRACE_ID code,uint8_t pdev_id,uint8_t * data,uint8_t data_size,uint8_t * meta_data,uint8_t metadata_size,bool print)1221 static void qdf_dp_add_record(enum QDF_DP_TRACE_ID code, uint8_t pdev_id,
1222 uint8_t *data, uint8_t data_size,
1223 uint8_t *meta_data, uint8_t metadata_size,
1224 bool print)
1225
1226 {
1227 struct qdf_dp_trace_record_s *rec = NULL;
1228 int index;
1229 bool print_this_record = false;
1230 u8 info = 0;
1231
1232 if (code >= QDF_DP_TRACE_MAX) {
1233 QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
1234 "invalid record code %u, max code %u",
1235 code, QDF_DP_TRACE_MAX);
1236 return;
1237 }
1238
1239 spin_lock_bh(&l_dp_trace_lock);
1240
1241 if (print || g_qdf_dp_trace_data.force_live_mode) {
1242 print_this_record = true;
1243 } else if (g_qdf_dp_trace_data.live_mode == 1) {
1244 print_this_record = true;
1245 g_qdf_dp_trace_data.print_pkt_cnt++;
1246 if (g_qdf_dp_trace_data.print_pkt_cnt >
1247 g_qdf_dp_trace_data.high_tput_thresh) {
1248 g_qdf_dp_trace_data.live_mode = 0;
1249 g_qdf_dp_trace_data.verbosity =
1250 QDF_DP_TRACE_VERBOSITY_ULTRA_LOW;
1251 info |= QDF_DP_TRACE_RECORD_INFO_THROTTLED;
1252 }
1253 }
1254
1255 g_qdf_dp_trace_data.num++;
1256
1257 if (g_qdf_dp_trace_data.num > MAX_QDF_DP_TRACE_RECORDS)
1258 g_qdf_dp_trace_data.num = MAX_QDF_DP_TRACE_RECORDS;
1259
1260 if (INVALID_QDF_DP_TRACE_ADDR == g_qdf_dp_trace_data.head) {
1261 /* first record */
1262 g_qdf_dp_trace_data.head = 0;
1263 g_qdf_dp_trace_data.tail = 0;
1264 } else {
1265 /* queue is not empty */
1266 g_qdf_dp_trace_data.tail++;
1267
1268 if (MAX_QDF_DP_TRACE_RECORDS == g_qdf_dp_trace_data.tail)
1269 g_qdf_dp_trace_data.tail = 0;
1270
1271 if (g_qdf_dp_trace_data.head == g_qdf_dp_trace_data.tail) {
1272 /* full */
1273 if (MAX_QDF_DP_TRACE_RECORDS ==
1274 ++g_qdf_dp_trace_data.head)
1275 g_qdf_dp_trace_data.head = 0;
1276 }
1277 }
1278
1279 rec = &g_qdf_dp_trace_tbl[g_qdf_dp_trace_data.tail];
1280 index = g_qdf_dp_trace_data.tail;
1281 rec->code = code;
1282 rec->pdev_id = pdev_id;
1283 rec->size = 0;
1284 qdf_dp_fill_record_data(rec, data, data_size,
1285 meta_data, metadata_size);
1286 rec->time = qdf_get_log_timestamp();
1287 rec->pid = (in_interrupt() ? 0 : current->pid);
1288
1289 if (rec->code >= QDF_DP_TRACE_MAX) {
1290 QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
1291 "invalid record code %u, max code %u",
1292 rec->code, QDF_DP_TRACE_MAX);
1293 return;
1294 }
1295
1296 spin_unlock_bh(&l_dp_trace_lock);
1297
1298 info |= QDF_DP_TRACE_RECORD_INFO_LIVE;
1299 if (print_this_record)
1300 qdf_dp_trace_cb_table[rec->code] (rec, index,
1301 QDF_TRACE_DEFAULT_PDEV_ID, info);
1302 }
1303
1304 /**
1305 * qdf_get_rate_limit_by_type() - Get the rate limit by pkt type
1306 * @type: packet type
1307 *
1308 * Return: Rate limit value for a particular packet type
1309 */
1310 static inline
qdf_get_rate_limit_by_type(uint8_t type)1311 uint8_t qdf_get_rate_limit_by_type(uint8_t type)
1312 {
1313 switch (type) {
1314 case QDF_PROTO_TYPE_DHCP:
1315 return QDF_MAX_DHCP_PKTS_PER_SEC;
1316 case QDF_PROTO_TYPE_EAPOL:
1317 return QDF_MAX_EAPOL_PKTS_PER_SEC;
1318 case QDF_PROTO_TYPE_ARP:
1319 return QDF_MAX_ARP_PKTS_PER_SEC;
1320 case QDF_PROTO_TYPE_DNS:
1321 return QDF_MAX_DNS_PKTS_PER_SEC;
1322 default:
1323 return QDF_MAX_OTHER_PKTS_PER_SEC;
1324 }
1325 }
1326
1327 /**
1328 * qdf_get_pkt_type_string() - Get the string based on pkt type
1329 * @type: packet type
1330 * @subtype: packet subtype
1331 *
1332 * Return: String based on pkt type
1333 */
1334 static
qdf_get_pkt_type_string(uint8_t type,uint8_t subtype)1335 uint8_t *qdf_get_pkt_type_string(uint8_t type, uint8_t subtype)
1336 {
1337 switch (subtype) {
1338 case QDF_PROTO_EAPOL_M1:
1339 return "EAPOL-1";
1340 case QDF_PROTO_EAPOL_M2:
1341 return "EAPOL-2";
1342 case QDF_PROTO_EAPOL_M3:
1343 return "EAPOL-3";
1344 case QDF_PROTO_EAPOL_M4:
1345 return "EAPOL-4";
1346 case QDF_PROTO_DHCP_DISCOVER:
1347 return "DHCP-D";
1348 case QDF_PROTO_DHCP_REQUEST:
1349 return "DHCP-R";
1350 case QDF_PROTO_DHCP_OFFER:
1351 return "DHCP-O";
1352 case QDF_PROTO_DHCP_ACK:
1353 return "DHCP-A";
1354 case QDF_PROTO_DHCP_NACK:
1355 return "DHCP-NA";
1356 case QDF_PROTO_DHCP_RELEASE:
1357 return "DHCP-REL";
1358 case QDF_PROTO_DHCP_INFORM:
1359 return "DHCP-IN";
1360 case QDF_PROTO_DHCP_DECLINE:
1361 return "DHCP-DEC";
1362 case QDF_PROTO_ARP_REQ:
1363 return "ARP-RQ";
1364 case QDF_PROTO_ARP_RES:
1365 return "ARP-RS";
1366 case QDF_PROTO_DNS_QUERY:
1367 return "DNS_Q";
1368 case QDF_PROTO_DNS_RES:
1369 return "DNS_RS";
1370 case QDF_PROTO_EAP_REQUEST:
1371 return "EAP_REQ";
1372 case QDF_PROTO_EAP_RESPONSE:
1373 return "EAP-RSP";
1374 case QDF_PROTO_EAP_SUCCESS:
1375 return "EAP-SUCCESS";
1376 case QDF_PROTO_EAP_FAILURE:
1377 return "EAP-FAIL";
1378 case QDF_PROTO_EAP_INITIATE:
1379 return "EAP-INIT";
1380 case QDF_PROTO_EAP_FINISH:
1381 return "EAP-FINISH";
1382 case QDF_PROTO_EAPOL_START:
1383 return "EAPOL-START";
1384 case QDF_PROTO_EAPOL_LOGOFF:
1385 return "EAPOL-LOGOFF";
1386 case QDF_PROTO_EAPOL_ASF:
1387 return "EAPOL-ASF";
1388 case QDF_PROTO_EAP_REQ_ID:
1389 return "EAP-REQ-ID";
1390 case QDF_PROTO_EAP_RSP_ID:
1391 return "EAP-RSP-ID";
1392 case QDF_PROTO_EAP_M1:
1393 return "EAP-M1";
1394 case QDF_PROTO_EAP_M2:
1395 return "EAP-M2";
1396 case QDF_PROTO_EAP_M3:
1397 return "EAP-M3";
1398 case QDF_PROTO_EAP_M4:
1399 return "EAP-M4";
1400 case QDF_PROTO_EAP_M5:
1401 return "EAP-M5";
1402 case QDF_PROTO_EAP_M6:
1403 return "EAP-M6";
1404 case QDF_PROTO_EAP_M7:
1405 return "EAP-M7";
1406 case QDF_PROTO_EAP_M8:
1407 return "EAP-M8";
1408 case QDF_PROTO_EAP_WSC_START:
1409 return "EAP-WSC-START";
1410 case QDF_PROTO_EAP_WSC_DONE:
1411 return "EAP-WSC-DONE";
1412 case QDF_PROTO_EAP_WSC_ACK:
1413 return "EAP-WSC-ACK";
1414 case QDF_PROTO_EAP_WSC_NACK:
1415 return "EAP-WSC-NACK";
1416 case QDF_PROTO_EAP_WSC_FRAG_ACK:
1417 return "EAP-WSC-FRAG-ACK";
1418 default:
1419 switch (type) {
1420 case QDF_PROTO_TYPE_EAPOL:
1421 return "EAP";
1422 case QDF_PROTO_TYPE_DHCP:
1423 return "DHCP";
1424 case QDF_PROTO_TYPE_ARP:
1425 return "ARP";
1426 case QDF_PROTO_TYPE_DNS:
1427 return "DNS";
1428 default:
1429 return "UNKNOWN";
1430 }
1431 }
1432 }
1433
1434 /**
1435 * qdf_get_pkt_status_string() - Get the string based on pkt status
1436 * @status: packet status
1437 *
1438 * Return: String based on pkt status
1439 */
1440 static
qdf_get_pkt_status_string(uint8_t status)1441 uint8_t *qdf_get_pkt_status_string(uint8_t status)
1442 {
1443 switch (status) {
1444 case QDF_TX_RX_STATUS_INVALID:
1445 return "inv";
1446 case QDF_TX_RX_STATUS_OK:
1447 return "succ";
1448 case QDF_TX_RX_STATUS_FW_DISCARD:
1449 return "disc";
1450 case QDF_TX_RX_STATUS_NO_ACK:
1451 return "nack";
1452 case QDF_TX_RX_STATUS_DROP:
1453 return "drop";
1454 default:
1455 return "unknown";
1456 }
1457 }
1458
qdf_dp_log_proto_pkt_info(uint8_t * sa,uint8_t * da,uint8_t type,uint8_t subtype,uint8_t dir,uint16_t msdu_id,uint8_t status)1459 void qdf_dp_log_proto_pkt_info(uint8_t *sa, uint8_t *da, uint8_t type,
1460 uint8_t subtype, uint8_t dir, uint16_t msdu_id,
1461 uint8_t status)
1462 {
1463 uint8_t pkt_rate_limit;
1464 static ulong last_ticks_tx[QDF_PROTO_SUBTYPE_MAX] = {0};
1465 static ulong last_ticks_rx[QDF_PROTO_SUBTYPE_MAX] = {0};
1466 ulong curr_ticks = jiffies;
1467
1468 pkt_rate_limit = qdf_get_rate_limit_by_type(type);
1469
1470 if ((dir == QDF_TX &&
1471 !time_after(curr_ticks,
1472 last_ticks_tx[subtype] + HZ / pkt_rate_limit)) ||
1473 (dir == QDF_RX &&
1474 !time_after(curr_ticks,
1475 last_ticks_rx[subtype] + HZ / pkt_rate_limit)))
1476 return;
1477
1478 if (dir == QDF_TX)
1479 last_ticks_tx[subtype] = curr_ticks;
1480 else
1481 last_ticks_rx[subtype] = curr_ticks;
1482
1483 if (status == QDF_TX_RX_STATUS_INVALID)
1484 qdf_nofl_info("%s %s: SA:" QDF_MAC_ADDR_FMT " DA:" QDF_MAC_ADDR_FMT,
1485 qdf_get_pkt_type_string(type, subtype),
1486 dir ? "RX" : "TX", QDF_MAC_ADDR_REF(sa),
1487 QDF_MAC_ADDR_REF(da));
1488 else
1489 qdf_nofl_info("%s %s: SA:" QDF_MAC_ADDR_FMT " DA:" QDF_MAC_ADDR_FMT " msdu_id:%d status: %s",
1490 qdf_get_pkt_type_string(type, subtype),
1491 dir ? "RX" : "TX", QDF_MAC_ADDR_REF(sa),
1492 QDF_MAC_ADDR_REF(da), msdu_id,
1493 qdf_get_pkt_status_string(status));
1494 }
1495
1496 qdf_export_symbol(qdf_dp_log_proto_pkt_info);
1497
1498 /**
1499 * qdf_log_icmpv6_pkt() - log ICMPv6 packet
1500 * @vdev_id: ID of the vdev
1501 * @skb: skb pointer
1502 * @dir: direction
1503 * @pdev_id: ID of the pdev
1504 *
1505 * Return: true/false
1506 */
qdf_log_icmpv6_pkt(uint8_t vdev_id,struct sk_buff * skb,enum qdf_proto_dir dir,uint8_t pdev_id)1507 static bool qdf_log_icmpv6_pkt(uint8_t vdev_id, struct sk_buff *skb,
1508 enum qdf_proto_dir dir, uint8_t pdev_id)
1509 {
1510 enum qdf_proto_subtype subtype;
1511 struct qdf_dp_trace_proto_cmn cmn_info;
1512
1513 if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMPv6) &&
1514 ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ICMPv6 ==
1515 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1516 (dir == QDF_RX && qdf_nbuf_is_icmpv6_pkt(skb) == true))) {
1517
1518 subtype = qdf_nbuf_get_icmpv6_subtype(skb);
1519
1520 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false;
1521 if (dir == QDF_TX)
1522 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1523 else if (dir == QDF_RX)
1524 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1525
1526 cmn_info.vdev_id = vdev_id;
1527 cmn_info.type = QDF_PROTO_TYPE_ICMPv6;
1528 cmn_info.subtype = subtype;
1529 cmn_info.proto_priv_data = 0;
1530 cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb);
1531 DPTRACE(qdf_dp_trace_proto_pkt(
1532 QDF_DP_TRACE_ICMPv6_PACKET_RECORD,
1533 (skb->data + QDF_NBUF_SRC_MAC_OFFSET),
1534 (skb->data + QDF_NBUF_DEST_MAC_OFFSET),
1535 dir, pdev_id, false, &cmn_info));
1536
1537 switch (subtype) {
1538 case QDF_PROTO_ICMPV6_REQ:
1539 g_qdf_dp_trace_data.icmpv6_req++;
1540 break;
1541 case QDF_PROTO_ICMPV6_RES:
1542 g_qdf_dp_trace_data.icmpv6_resp++;
1543 break;
1544 case QDF_PROTO_ICMPV6_RS:
1545 g_qdf_dp_trace_data.icmpv6_rs++;
1546 break;
1547 case QDF_PROTO_ICMPV6_RA:
1548 g_qdf_dp_trace_data.icmpv6_ra++;
1549 break;
1550 case QDF_PROTO_ICMPV6_NS:
1551 g_qdf_dp_trace_data.icmpv6_ns++;
1552 break;
1553 case QDF_PROTO_ICMPV6_NA:
1554 g_qdf_dp_trace_data.icmpv6_na++;
1555 break;
1556 default:
1557 break;
1558 }
1559 return true;
1560 }
1561
1562 return false;
1563 }
1564
1565 /**
1566 * qdf_log_icmp_pkt() - log ICMP packet
1567 * @vdev_id: ID of the vdev
1568 * @skb: skb pointer
1569 * @dir: direction
1570 * @pdev_id: ID of the pdev
1571 *
1572 * Return: true/false
1573 */
qdf_log_icmp_pkt(uint8_t vdev_id,struct sk_buff * skb,enum qdf_proto_dir dir,uint8_t pdev_id)1574 static bool qdf_log_icmp_pkt(uint8_t vdev_id, struct sk_buff *skb,
1575 enum qdf_proto_dir dir, uint8_t pdev_id)
1576 {
1577 uint8_t *data = NULL;
1578 uint16_t seq_num = 0;
1579 uint16_t icmp_id = 0;
1580 struct qdf_dp_trace_proto_cmn cmn_info;
1581
1582 if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMP) &&
1583 (qdf_nbuf_is_icmp_pkt(skb) == true)) {
1584
1585 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false;
1586 cmn_info.subtype = qdf_nbuf_get_icmp_subtype(skb);
1587
1588 data = qdf_nbuf_data(skb);
1589 icmp_id = qdf_cpu_to_be16(*(uint16_t *)(data + ICMP_ID_OFFSET));
1590 seq_num = qdf_cpu_to_be16(*(uint16_t *)(data + ICMP_SEQ_NUM_OFFSET));
1591
1592 cmn_info.proto_priv_data = ((uint32_t)icmp_id) << 16;
1593 cmn_info.proto_priv_data |= (uint32_t)seq_num;
1594 cmn_info.type = QDF_PROTO_TYPE_ICMP;
1595 cmn_info.vdev_id = vdev_id;
1596 cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb);
1597
1598 if (QDF_TX == dir)
1599 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1600 else if (QDF_RX == dir)
1601 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1602
1603 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ICMP_PACKET_RECORD,
1604 skb->data +
1605 QDF_NBUF_SRC_MAC_OFFSET,
1606 skb->data +
1607 QDF_NBUF_DEST_MAC_OFFSET,
1608 dir, pdev_id,
1609 false, &cmn_info));
1610
1611 if (cmn_info.subtype == QDF_PROTO_ICMP_REQ)
1612 g_qdf_dp_trace_data.icmp_req++;
1613 else
1614 g_qdf_dp_trace_data.icmp_resp++;
1615
1616 return true;
1617 }
1618 return false;
1619 }
1620
1621 #ifdef WLAN_CHIPSET_STATS
1622 static void
qdf_log_pkt_cstats(uint8_t * sa,uint8_t * da,enum qdf_proto_type pkt_type,enum qdf_proto_subtype subtype,enum qdf_proto_dir dir,enum qdf_dp_tx_rx_status status,uint8_t vdev_id,enum QDF_OPMODE op_mode)1623 qdf_log_pkt_cstats(uint8_t *sa, uint8_t *da, enum qdf_proto_type pkt_type,
1624 enum qdf_proto_subtype subtype, enum qdf_proto_dir dir,
1625 enum qdf_dp_tx_rx_status status, uint8_t vdev_id,
1626 enum QDF_OPMODE op_mode)
1627 {
1628 wlan_cp_stats_cstats_pkt_log(sa, da, pkt_type, subtype, dir,
1629 status, vdev_id, op_mode);
1630 }
1631 #else
1632 static void
qdf_log_pkt_cstats(uint8_t * sa,uint8_t * da,enum qdf_proto_type pkt_type,enum qdf_proto_subtype subtype,enum qdf_proto_dir dir,enum qdf_dp_tx_rx_status status,uint8_t vdev_id,enum QDF_OPMODE op_mode)1633 qdf_log_pkt_cstats(uint8_t *sa, uint8_t *da, enum qdf_proto_type pkt_type,
1634 enum qdf_proto_subtype subtype, enum qdf_proto_dir dir,
1635 enum qdf_dp_tx_rx_status status, uint8_t vdev_id,
1636 enum QDF_OPMODE op_mode)
1637 {
1638 }
1639 #endif
1640
1641 #ifdef CONNECTIVITY_DIAG_EVENT
wlan_get_diag_tx_status(enum qdf_dp_tx_rx_status tx_status)1642 enum diag_tx_status wlan_get_diag_tx_status(enum qdf_dp_tx_rx_status tx_status)
1643 {
1644 switch (tx_status) {
1645 case DIAG_TX_RX_STATUS_FW_DISCARD:
1646 case DIAG_TX_RX_STATUS_INVALID:
1647 case DIAG_TX_RX_STATUS_DROP:
1648 case DIAG_TX_RX_STATUS_DOWNLOAD_SUCC:
1649 case DIAG_TX_RX_STATUS_DEFAULT:
1650 default:
1651 return DIAG_TX_STATUS_FAIL;
1652 case DIAG_TX_RX_STATUS_NO_ACK:
1653 return DIAG_TX_STATUS_NO_ACK;
1654 case DIAG_TX_RX_STATUS_OK:
1655 return DIAG_TX_STATUS_ACK;
1656 }
1657
1658 return DIAG_TX_STATUS_FAIL;
1659 }
1660
1661 /**
1662 * qdf_subtype_to_wlan_main_tag() - Convert qdf subtype to wlan main tag
1663 * @subtype: EAPoL key subtype
1664 *
1665 * Return: Wlan main tag subtype
1666 */
qdf_subtype_to_wlan_main_tag(enum qdf_proto_subtype subtype)1667 static int qdf_subtype_to_wlan_main_tag(enum qdf_proto_subtype subtype)
1668 {
1669 switch (subtype) {
1670 case QDF_PROTO_DHCP_DISCOVER:
1671 return WLAN_CONN_DIAG_DHCP_DISC_EVENT;
1672 case QDF_PROTO_DHCP_REQUEST:
1673 return WLAN_CONN_DIAG_DHCP_REQUEST_EVENT;
1674 case QDF_PROTO_DHCP_OFFER:
1675 return WLAN_CONN_DIAG_DHCP_OFFER_EVENT;
1676 case QDF_PROTO_DHCP_ACK:
1677 return WLAN_CONN_DIAG_DHCP_ACK_EVENT;
1678 case QDF_PROTO_DHCP_NACK:
1679 return WLAN_CONN_DIAG_DHCP_NACK_EVENT;
1680 case QDF_PROTO_EAPOL_M1:
1681 return WLAN_CONN_DIAG_EAPOL_M1_EVENT;
1682 case QDF_PROTO_EAPOL_M2:
1683 return WLAN_CONN_DIAG_EAPOL_M2_EVENT;
1684 case QDF_PROTO_EAPOL_M3:
1685 return WLAN_CONN_DIAG_EAPOL_M3_EVENT;
1686 case QDF_PROTO_EAPOL_M4:
1687 return WLAN_CONN_DIAG_EAPOL_M4_EVENT;
1688 case QDF_PROTO_EAP_REQUEST:
1689 return WLAN_CONN_DIAG_EAP_REQ_EVENT;
1690 case QDF_PROTO_EAP_RESPONSE:
1691 return WLAN_CONN_DIAG_EAP_RESP_EVENT;
1692 case QDF_PROTO_EAP_SUCCESS:
1693 return WLAN_CONN_DIAG_EAP_SUCC_EVENT;
1694 case QDF_PROTO_EAP_FAILURE:
1695 return WLAN_CONN_DIAG_EAP_FAIL_EVENT;
1696 case QDF_PROTO_EAPOL_START:
1697 return WLAN_CONN_DIAG_EAP_START_EVENT;
1698 default:
1699 return WLAN_CONN_DIAG_MAX;
1700 }
1701 }
1702
1703 /**
1704 * qdf_get_wlan_eap_code() - Get EAP code
1705 * @data: skb data pointer
1706 *
1707 * Return: EAP code value
1708 */
qdf_get_wlan_eap_code(uint8_t * data)1709 static int qdf_get_wlan_eap_code(uint8_t *data)
1710 {
1711 uint8_t code = *(data + EAP_CODE_OFFSET);
1712
1713 switch (code) {
1714 case QDF_EAP_REQUEST:
1715 return WLAN_CONN_DIAG_EAP_REQ_EVENT;
1716 case QDF_EAP_RESPONSE:
1717 return WLAN_CONN_DIAG_EAP_RESP_EVENT;
1718 case QDF_EAP_SUCCESS:
1719 return WLAN_CONN_DIAG_EAP_SUCC_EVENT;
1720 case QDF_EAP_FAILURE:
1721 return WLAN_CONN_DIAG_EAP_FAIL_EVENT;
1722 default:
1723 return WLAN_CONN_DIAG_MAX;
1724 }
1725 }
1726
1727 /**
1728 * qdf_eapol_get_key_type() - Get EAPOL key type
1729 * @data: skb data pointer
1730 * @subtype: EAPoL key subtype
1731 *
1732 * Return: EAPOL key type
1733 */
1734 static
qdf_eapol_get_key_type(uint8_t * data,enum qdf_proto_subtype subtype)1735 uint8_t qdf_eapol_get_key_type(uint8_t *data, enum qdf_proto_subtype subtype)
1736 {
1737 uint16_t key_info = *(uint16_t *)(data + EAPOL_KEY_INFO_OFFSET);
1738
1739 /* If key type is PTK, key type will be set in EAPOL Key info */
1740 if (key_info & EAPOL_KEY_TYPE_MASK)
1741 return qdf_subtype_to_wlan_main_tag(subtype);
1742 else if (key_info & EAPOL_KEY_ENCRYPTED_MASK)
1743 return WLAN_CONN_DIAG_GTK_M1_EVENT;
1744 else
1745 return WLAN_CONN_DIAG_GTK_M2_EVENT;
1746 }
1747
1748 /**
1749 * qdf_skip_wlan_connectivity_log() - Check if connectivity log need to skip
1750 * @type: Protocol type
1751 * @subtype: Protocol subtype
1752 * @dir: Rx or Tx
1753 * @op_mode: Vdev Operation mode
1754 *
1755 * Return: true or false
1756 */
1757 static inline
qdf_skip_wlan_connectivity_log(enum qdf_proto_type type,enum qdf_proto_subtype subtype,enum qdf_proto_dir dir,enum QDF_OPMODE op_mode)1758 bool qdf_skip_wlan_connectivity_log(enum qdf_proto_type type,
1759 enum qdf_proto_subtype subtype,
1760 enum qdf_proto_dir dir,
1761 enum QDF_OPMODE op_mode)
1762 {
1763 if (op_mode != QDF_STA_MODE)
1764 return true;
1765
1766 if (dir == QDF_RX && type == QDF_PROTO_TYPE_DHCP &&
1767 (subtype == QDF_PROTO_DHCP_DISCOVER ||
1768 subtype == QDF_PROTO_DHCP_REQUEST))
1769 return true;
1770 return false;
1771 }
1772
1773 /**
1774 * qdf_fill_wlan_connectivity_log() - Fill and queue protocol packet to logging
1775 * the logging queue
1776 * @type: Protocol type
1777 * @subtype: Protocol subtype
1778 * @dir: Rx or Tx
1779 * @qdf_tx_status: Tx completion status
1780 * @op_mode: Vdev Operation mode
1781 * @vdev_id: DP vdev ID
1782 * @data: skb data pointer
1783 * @band: band
1784 *
1785 * Return: None
1786 */
1787 static
qdf_fill_wlan_connectivity_log(enum qdf_proto_type type,enum qdf_proto_subtype subtype,enum qdf_proto_dir dir,enum qdf_dp_tx_rx_status qdf_tx_status,enum QDF_OPMODE op_mode,uint8_t vdev_id,uint8_t * data,uint8_t band)1788 void qdf_fill_wlan_connectivity_log(enum qdf_proto_type type,
1789 enum qdf_proto_subtype subtype,
1790 enum qdf_proto_dir dir,
1791 enum qdf_dp_tx_rx_status qdf_tx_status,
1792 enum QDF_OPMODE op_mode,
1793 uint8_t vdev_id, uint8_t *data,
1794 uint8_t band)
1795 {
1796 uint8_t pkt_type;
1797
1798 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_packet_info);
1799
1800 if (qdf_skip_wlan_connectivity_log(type, subtype, dir, op_mode))
1801 return;
1802
1803 qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
1804
1805 wlan_diag_event.diag_cmn.timestamp_us =
1806 qdf_get_time_of_the_day_ms() * 1000;
1807 wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get());
1808 wlan_diag_event.diag_cmn.vdev_id = vdev_id;
1809
1810 wlan_diag_event.version = DIAG_MGMT_VERSION_V2;
1811
1812 if (type == QDF_PROTO_TYPE_DHCP) {
1813 wlan_diag_event.subtype =
1814 qdf_subtype_to_wlan_main_tag(subtype);
1815 } else if (type == QDF_PROTO_TYPE_EAPOL) {
1816 pkt_type = *(data + EAPOL_PACKET_TYPE_OFFSET);
1817 if (pkt_type == EAPOL_PACKET_TYPE_EAP) {
1818 wlan_diag_event.subtype =
1819 qdf_get_wlan_eap_code(data);
1820 wlan_diag_event.eap_type =
1821 *(data + EAP_TYPE_OFFSET);
1822 wlan_diag_event.eap_len =
1823 qdf_ntohs(*(uint16_t *)(data + EAP_LENGTH_OFFSET));
1824 } else if (pkt_type == EAPOL_PACKET_TYPE_KEY) {
1825 wlan_diag_event.subtype =
1826 qdf_eapol_get_key_type(data, subtype);
1827 } else if (pkt_type == EAPOL_PACKET_TYPE_START) {
1828 wlan_diag_event.subtype =
1829 WLAN_CONN_DIAG_EAP_START_EVENT;
1830 wlan_diag_event.eap_len =
1831 qdf_ntohs(*(uint16_t *)(data + EAPOL_PKT_LEN_OFFSET));
1832 } else {
1833 return;
1834 }
1835 } else {
1836 return;
1837 }
1838
1839 wlan_diag_event.supported_links = band;
1840
1841 /*Tx completion status needs to be logged*/
1842 if (dir == QDF_TX) {
1843 wlan_diag_event.is_tx = 1;
1844 wlan_diag_event.tx_status =
1845 wlan_get_diag_tx_status(qdf_tx_status);
1846 }
1847
1848 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_CONN_DP);
1849 }
1850
1851 #else
1852 static inline
qdf_fill_wlan_connectivity_log(enum qdf_proto_type type,enum qdf_proto_subtype subtype,enum qdf_proto_dir dir,enum qdf_dp_tx_rx_status qdf_tx_status,enum QDF_OPMODE op_mode,uint8_t vdev_id,uint8_t * data,uint8_t band)1853 void qdf_fill_wlan_connectivity_log(enum qdf_proto_type type,
1854 enum qdf_proto_subtype subtype,
1855 enum qdf_proto_dir dir,
1856 enum qdf_dp_tx_rx_status qdf_tx_status,
1857 enum QDF_OPMODE op_mode,
1858 uint8_t vdev_id, uint8_t *data,
1859 uint8_t band)
1860 {
1861 }
1862 #endif
1863
1864 /**
1865 * qdf_log_eapol_pkt() - log EAPOL packet
1866 * @vdev_id: ID of the vdev
1867 * @skb: skb pointer
1868 * @dir: direction
1869 * @pdev_id: ID of the pdev
1870 * @op_mode: Vdev Operation mode
1871 *
1872 * Return: true/false
1873 */
qdf_log_eapol_pkt(uint8_t vdev_id,struct sk_buff * skb,enum qdf_proto_dir dir,uint8_t pdev_id,enum QDF_OPMODE op_mode)1874 static bool qdf_log_eapol_pkt(uint8_t vdev_id, struct sk_buff *skb,
1875 enum qdf_proto_dir dir, uint8_t pdev_id,
1876 enum QDF_OPMODE op_mode)
1877 {
1878 enum qdf_proto_subtype subtype;
1879 uint32_t dp_eap_trace;
1880 uint32_t dp_eap_event;
1881 struct qdf_dp_trace_proto_cmn cmn_info;
1882
1883 dp_eap_trace = qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
1884 dp_eap_event = qdf_dp_get_proto_event_bitmap() &
1885 QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
1886
1887 if (!dp_eap_trace && !dp_eap_event)
1888 return false;
1889
1890 if (!((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_EAPOL ==
1891 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1892 (dir == QDF_RX && qdf_nbuf_is_ipv4_eapol_pkt(skb) == true)))
1893 return false;
1894
1895 subtype = qdf_nbuf_get_eapol_subtype(skb);
1896
1897 if (dp_eap_event && dir == QDF_RX) {
1898 qdf_dp_log_proto_pkt_info(skb->data + QDF_NBUF_SRC_MAC_OFFSET,
1899 skb->data + QDF_NBUF_DEST_MAC_OFFSET,
1900 QDF_PROTO_TYPE_EAPOL, subtype, dir,
1901 QDF_TRACE_DEFAULT_MSDU_ID,
1902 QDF_TX_RX_STATUS_INVALID);
1903 qdf_fill_wlan_connectivity_log(QDF_PROTO_TYPE_EAPOL, subtype,
1904 QDF_RX, 0, op_mode,
1905 vdev_id, skb->data,
1906 qdf_nbuf_rx_get_band(skb));
1907 qdf_log_pkt_cstats(skb->data + QDF_NBUF_SRC_MAC_OFFSET,
1908 skb->data + QDF_NBUF_DEST_MAC_OFFSET,
1909 QDF_PROTO_TYPE_EAPOL, subtype, dir,
1910 QDF_TX_RX_STATUS_INVALID, vdev_id, op_mode);
1911 }
1912
1913 if (dp_eap_trace) {
1914 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
1915 if (QDF_TX == dir)
1916 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
1917 else if (QDF_RX == dir)
1918 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
1919
1920 cmn_info.vdev_id = vdev_id;
1921 cmn_info.type = QDF_PROTO_TYPE_EAPOL;
1922 cmn_info.subtype = subtype;
1923 cmn_info.proto_priv_data = 0;
1924 cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb);
1925 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_EAPOL_PACKET_RECORD,
1926 skb->data +
1927 QDF_NBUF_SRC_MAC_OFFSET,
1928 skb->data +
1929 QDF_NBUF_DEST_MAC_OFFSET,
1930 dir, pdev_id, true, &cmn_info));
1931
1932 switch (subtype) {
1933 case QDF_PROTO_EAPOL_M1:
1934 g_qdf_dp_trace_data.eapol_m1++;
1935 break;
1936 case QDF_PROTO_EAPOL_M2:
1937 g_qdf_dp_trace_data.eapol_m2++;
1938 break;
1939 case QDF_PROTO_EAPOL_M3:
1940 g_qdf_dp_trace_data.eapol_m3++;
1941 break;
1942 case QDF_PROTO_EAPOL_M4:
1943 g_qdf_dp_trace_data.eapol_m4++;
1944 break;
1945 default:
1946 g_qdf_dp_trace_data.eapol_others++;
1947 break;
1948 }
1949 }
1950
1951 return true;
1952 }
1953
1954 /**
1955 * qdf_log_dhcp_pkt() - log DHCP packet
1956 * @vdev_id: ID of the vdev
1957 * @skb: skb pointer
1958 * @dir: direction
1959 * @pdev_id: ID of the pdev
1960 * @op_mode: Vdev Operation mode
1961 *
1962 * Return: true/false
1963 */
qdf_log_dhcp_pkt(uint8_t vdev_id,struct sk_buff * skb,enum qdf_proto_dir dir,uint8_t pdev_id,enum QDF_OPMODE op_mode)1964 static bool qdf_log_dhcp_pkt(uint8_t vdev_id, struct sk_buff *skb,
1965 enum qdf_proto_dir dir, uint8_t pdev_id,
1966 enum QDF_OPMODE op_mode)
1967 {
1968 enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
1969 uint32_t dp_dhcp_trace;
1970 uint32_t dp_dhcp_event;
1971 struct qdf_dp_trace_proto_cmn cmn_info;
1972
1973 dp_dhcp_trace = qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_DHCP;
1974 dp_dhcp_event = qdf_dp_get_proto_event_bitmap() &
1975 QDF_NBUF_PKT_TRAC_TYPE_DHCP;
1976
1977 if (!dp_dhcp_trace && !dp_dhcp_event)
1978 return false;
1979
1980 if (!((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_DHCP ==
1981 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
1982 (dir == QDF_RX && qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true)))
1983 return false;
1984
1985 subtype = qdf_nbuf_get_dhcp_subtype(skb);
1986
1987 if (dp_dhcp_event && dir == QDF_RX) {
1988 qdf_dp_log_proto_pkt_info(skb->data + QDF_NBUF_SRC_MAC_OFFSET,
1989 skb->data + QDF_NBUF_DEST_MAC_OFFSET,
1990 QDF_PROTO_TYPE_DHCP, subtype, dir,
1991 QDF_TRACE_DEFAULT_MSDU_ID,
1992 QDF_TX_RX_STATUS_INVALID);
1993 qdf_fill_wlan_connectivity_log(QDF_PROTO_TYPE_DHCP, subtype,
1994 QDF_RX, 0, op_mode, vdev_id, 0,
1995 qdf_nbuf_rx_get_band(skb));
1996 qdf_log_pkt_cstats(skb->data + QDF_NBUF_SRC_MAC_OFFSET,
1997 skb->data + QDF_NBUF_DEST_MAC_OFFSET,
1998 QDF_PROTO_TYPE_DHCP, subtype, dir,
1999 QDF_TX_RX_STATUS_INVALID, vdev_id, op_mode);
2000 }
2001
2002 if (dp_dhcp_trace) {
2003 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
2004 if (QDF_TX == dir)
2005 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
2006 else if (QDF_RX == dir)
2007 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
2008
2009 cmn_info.vdev_id = vdev_id;
2010 cmn_info.type = QDF_PROTO_TYPE_DHCP;
2011 cmn_info.subtype = subtype;
2012 cmn_info.proto_priv_data = 0;
2013 cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb);
2014 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_DHCP_PACKET_RECORD,
2015 skb->data +
2016 QDF_NBUF_SRC_MAC_OFFSET,
2017 skb->data +
2018 QDF_NBUF_DEST_MAC_OFFSET,
2019 dir, pdev_id, true, &cmn_info));
2020
2021 switch (subtype) {
2022 case QDF_PROTO_DHCP_DISCOVER:
2023 g_qdf_dp_trace_data.dhcp_disc++;
2024 break;
2025 case QDF_PROTO_DHCP_OFFER:
2026 g_qdf_dp_trace_data.dhcp_off++;
2027 break;
2028 case QDF_PROTO_DHCP_REQUEST:
2029 g_qdf_dp_trace_data.dhcp_req++;
2030 break;
2031 case QDF_PROTO_DHCP_ACK:
2032 g_qdf_dp_trace_data.dhcp_ack++;
2033 break;
2034 case QDF_PROTO_DHCP_NACK:
2035 g_qdf_dp_trace_data.dhcp_nack++;
2036 break;
2037 default:
2038 g_qdf_dp_trace_data.eapol_others++;
2039 break;
2040 }
2041 }
2042
2043 return true;
2044 }
2045
2046 /**
2047 * qdf_log_arp_pkt() - log ARP packet
2048 * @vdev_id: ID of the vdev
2049 * @skb: skb pointer
2050 * @dir: direction
2051 * @pdev_id: ID of the pdev
2052 *
2053 * Return: true/false
2054 */
qdf_log_arp_pkt(uint8_t vdev_id,struct sk_buff * skb,enum qdf_proto_dir dir,uint8_t pdev_id)2055 static bool qdf_log_arp_pkt(uint8_t vdev_id, struct sk_buff *skb,
2056 enum qdf_proto_dir dir, uint8_t pdev_id)
2057 {
2058 enum qdf_proto_subtype proto_subtype;
2059 struct qdf_dp_trace_proto_cmn cmn_info;
2060
2061 if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ARP) &&
2062 ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ARP ==
2063 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) ||
2064 (dir == QDF_RX && qdf_nbuf_is_ipv4_arp_pkt(skb) == true))) {
2065
2066 proto_subtype = qdf_nbuf_get_arp_subtype(skb);
2067 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true;
2068 if (QDF_TX == dir)
2069 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
2070 else if (QDF_RX == dir)
2071 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1;
2072
2073 cmn_info.vdev_id = vdev_id;
2074 cmn_info.type = QDF_PROTO_TYPE_ARP;
2075 cmn_info.subtype = proto_subtype;
2076 cmn_info.proto_priv_data = 0;
2077 cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb);
2078 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ARP_PACKET_RECORD,
2079 skb->data +
2080 QDF_NBUF_SRC_MAC_OFFSET,
2081 skb->data +
2082 QDF_NBUF_DEST_MAC_OFFSET,
2083 dir, pdev_id, true,
2084 &cmn_info));
2085
2086 if (QDF_PROTO_ARP_REQ == proto_subtype)
2087 g_qdf_dp_trace_data.arp_req++;
2088 else
2089 g_qdf_dp_trace_data.arp_resp++;
2090
2091 return true;
2092 }
2093 return false;
2094 }
2095
2096
qdf_dp_trace_log_pkt(uint8_t vdev_id,struct sk_buff * skb,enum qdf_proto_dir dir,uint8_t pdev_id,enum QDF_OPMODE op_mode)2097 bool qdf_dp_trace_log_pkt(uint8_t vdev_id, struct sk_buff *skb,
2098 enum qdf_proto_dir dir, uint8_t pdev_id,
2099 enum QDF_OPMODE op_mode)
2100 {
2101 if (!qdf_dp_get_proto_bitmap() && !qdf_dp_get_proto_event_bitmap())
2102 return false;
2103 if (qdf_log_arp_pkt(vdev_id, skb, dir, pdev_id))
2104 return true;
2105 if (qdf_log_dhcp_pkt(vdev_id, skb, dir, pdev_id, op_mode))
2106 return true;
2107 if (qdf_log_eapol_pkt(vdev_id, skb, dir, pdev_id, op_mode))
2108 return true;
2109 if (qdf_log_icmp_pkt(vdev_id, skb, dir, pdev_id))
2110 return true;
2111 if (qdf_log_icmpv6_pkt(vdev_id, skb, dir, pdev_id))
2112 return true;
2113 return false;
2114 }
2115 qdf_export_symbol(qdf_dp_trace_log_pkt);
2116
qdf_dp_display_mgmt_pkt(struct qdf_dp_trace_record_s * record,uint16_t index,uint8_t pdev_id,uint8_t info)2117 void qdf_dp_display_mgmt_pkt(struct qdf_dp_trace_record_s *record,
2118 uint16_t index, uint8_t pdev_id, uint8_t info)
2119 {
2120 int loc;
2121 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2122 struct qdf_dp_trace_mgmt_buf *buf =
2123 (struct qdf_dp_trace_mgmt_buf *)record->data;
2124
2125 qdf_mem_zero(prepend_str, sizeof(prepend_str));
2126 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2127 index, info, record);
2128
2129 DPTRACE_PRINT("%s [%d] [%s %s]",
2130 prepend_str,
2131 buf->vdev_id,
2132 qdf_dp_type_to_str(buf->type),
2133 qdf_dp_subtype_to_str(buf->subtype));
2134 }
2135 qdf_export_symbol(qdf_dp_display_mgmt_pkt);
2136
2137
qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code,uint8_t vdev_id,uint8_t pdev_id,enum qdf_proto_type type,enum qdf_proto_subtype subtype)2138 void qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
2139 uint8_t pdev_id, enum qdf_proto_type type,
2140 enum qdf_proto_subtype subtype)
2141 {
2142 struct qdf_dp_trace_mgmt_buf buf;
2143 int buf_size = sizeof(struct qdf_dp_trace_mgmt_buf);
2144
2145 if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
2146 return;
2147
2148 if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2149 QDF_BUG(0);
2150
2151 buf.type = type;
2152 buf.subtype = subtype;
2153 buf.vdev_id = vdev_id;
2154 qdf_dp_add_record(code, pdev_id, (uint8_t *)&buf, buf_size,
2155 NULL, 0, true);
2156 }
2157 qdf_export_symbol(qdf_dp_trace_mgmt_pkt);
2158
2159 static void
qdf_dpt_display_credit_record_debugfs(qdf_debugfs_file_t file,struct qdf_dp_trace_record_s * record,uint32_t index)2160 qdf_dpt_display_credit_record_debugfs(qdf_debugfs_file_t file,
2161 struct qdf_dp_trace_record_s *record,
2162 uint32_t index)
2163 {
2164 int loc;
2165 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2166 struct qdf_dp_trace_credit_record *buf =
2167 (struct qdf_dp_trace_credit_record *)record->data;
2168
2169 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2170 index, 0, record);
2171 if (buf->operation == QDF_OP_NA)
2172 qdf_debugfs_printf(file, "%s [%s] [T: %d G0: %d G1: %d]\n",
2173 prepend_str,
2174 qdf_dp_credit_source_to_str(buf->source),
2175 buf->total_credits, buf->g0_credit,
2176 buf->g1_credit);
2177 else
2178 qdf_debugfs_printf(file,
2179 "%s [%s] [T: %d G0: %d G1: %d] [%s %d]\n",
2180 prepend_str,
2181 qdf_dp_credit_source_to_str(buf->source),
2182 buf->total_credits, buf->g0_credit,
2183 buf->g1_credit,
2184 qdf_dp_operation_to_str(buf->operation),
2185 buf->delta);
2186 }
2187
qdf_dp_display_credit_record(struct qdf_dp_trace_record_s * record,uint16_t index,uint8_t pdev_id,uint8_t info)2188 void qdf_dp_display_credit_record(struct qdf_dp_trace_record_s *record,
2189 uint16_t index, uint8_t pdev_id, uint8_t info)
2190 {
2191 int loc;
2192 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2193 struct qdf_dp_trace_credit_record *buf =
2194 (struct qdf_dp_trace_credit_record *)record->data;
2195
2196 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2197 index, info, record);
2198 if (buf->operation == QDF_OP_NA)
2199 DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d]",
2200 prepend_str,
2201 qdf_dp_credit_source_to_str(buf->source),
2202 buf->total_credits, buf->g0_credit,
2203 buf->g1_credit);
2204 else
2205 DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d] [%s %d]",
2206 prepend_str,
2207 qdf_dp_credit_source_to_str(buf->source),
2208 buf->total_credits, buf->g0_credit,
2209 buf->g1_credit,
2210 qdf_dp_operation_to_str(buf->operation),
2211 buf->delta);
2212 }
2213
qdf_dp_trace_credit_record(enum QDF_CREDIT_UPDATE_SOURCE source,enum QDF_CREDIT_OPERATION operation,int delta,int total_credits,int g0_credit,int g1_credit)2214 void qdf_dp_trace_credit_record(enum QDF_CREDIT_UPDATE_SOURCE source,
2215 enum QDF_CREDIT_OPERATION operation,
2216 int delta, int total_credits,
2217 int g0_credit, int g1_credit)
2218 {
2219 struct qdf_dp_trace_credit_record buf;
2220 int buf_size = sizeof(struct qdf_dp_trace_credit_record);
2221 enum QDF_DP_TRACE_ID code = QDF_DP_TRACE_TX_CREDIT_RECORD;
2222
2223 if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
2224 return;
2225
2226 if (!(qdf_dp_get_proto_bitmap() & QDF_HL_CREDIT_TRACKING))
2227 return;
2228
2229 if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2230 QDF_BUG(0);
2231
2232 buf.source = source;
2233 buf.operation = operation;
2234 buf.delta = delta;
2235 buf.total_credits = total_credits;
2236 buf.g0_credit = g0_credit;
2237 buf.g1_credit = g1_credit;
2238
2239 qdf_dp_add_record(code, QDF_TRACE_DEFAULT_PDEV_ID, (uint8_t *)&buf,
2240 buf_size, NULL, 0, false);
2241 }
2242 qdf_export_symbol(qdf_dp_trace_credit_record);
2243
qdf_dp_display_event_record(struct qdf_dp_trace_record_s * record,uint16_t index,uint8_t pdev_id,uint8_t info)2244 void qdf_dp_display_event_record(struct qdf_dp_trace_record_s *record,
2245 uint16_t index, uint8_t pdev_id, uint8_t info)
2246 {
2247 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2248 struct qdf_dp_trace_event_buf *buf =
2249 (struct qdf_dp_trace_event_buf *)record->data;
2250
2251 qdf_mem_zero(prepend_str, sizeof(prepend_str));
2252 qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2253 index, info, record);
2254
2255 DPTRACE_PRINT("%s [%d] [%s %s]",
2256 prepend_str,
2257 buf->vdev_id,
2258 qdf_dp_type_to_str(buf->type),
2259 qdf_dp_subtype_to_str(buf->subtype));
2260 }
2261 qdf_export_symbol(qdf_dp_display_event_record);
2262
qdf_dp_trace_record_event(enum QDF_DP_TRACE_ID code,uint8_t vdev_id,uint8_t pdev_id,enum qdf_proto_type type,enum qdf_proto_subtype subtype)2263 void qdf_dp_trace_record_event(enum QDF_DP_TRACE_ID code, uint8_t vdev_id,
2264 uint8_t pdev_id, enum qdf_proto_type type,
2265 enum qdf_proto_subtype subtype)
2266 {
2267 struct qdf_dp_trace_event_buf buf;
2268 int buf_size = sizeof(struct qdf_dp_trace_event_buf);
2269
2270 if (qdf_dp_enable_check(NULL, code, QDF_NA) == false)
2271 return;
2272
2273 if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2274 QDF_BUG(0);
2275
2276 buf.type = type;
2277 buf.subtype = subtype;
2278 buf.vdev_id = vdev_id;
2279 qdf_dp_add_record(code, pdev_id,
2280 (uint8_t *)&buf, buf_size, NULL, 0, true);
2281 }
2282 qdf_export_symbol(qdf_dp_trace_record_event);
2283
2284
qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s * record,uint16_t index,uint8_t pdev_id,uint8_t info)2285 void qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s *record,
2286 uint16_t index, uint8_t pdev_id, uint8_t info)
2287 {
2288 int loc;
2289 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2290 struct qdf_dp_trace_proto_buf *buf =
2291 (struct qdf_dp_trace_proto_buf *)record->data;
2292
2293 qdf_mem_zero(prepend_str, sizeof(prepend_str));
2294 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2295 index, info, record);
2296
2297 if (QDF_RX == buf->dir)
2298 DPTRACE_PRINT("%s [%d] [%d] [%s] SA: "
2299 QDF_MAC_ADDR_FMT " %s DA:"
2300 QDF_MAC_ADDR_FMT " proto priv data = %08x",
2301 prepend_str,
2302 buf->cmn_info.vdev_id,
2303 buf->cmn_info.mpdu_seq,
2304 qdf_dp_subtype_to_str(buf->cmn_info.subtype),
2305 QDF_MAC_ADDR_REF(buf->sa.bytes),
2306 qdf_dp_dir_to_str(buf->dir),
2307 QDF_MAC_ADDR_REF(buf->da.bytes),
2308 buf->cmn_info.proto_priv_data);
2309 else
2310 DPTRACE_PRINT("%s [%d] [%s] SA: "
2311 QDF_MAC_ADDR_FMT " %s DA:"
2312 QDF_MAC_ADDR_FMT " proto priv data = %08x",
2313 prepend_str,
2314 buf->cmn_info.vdev_id,
2315 qdf_dp_subtype_to_str(buf->cmn_info.subtype),
2316 QDF_MAC_ADDR_REF(buf->sa.bytes),
2317 qdf_dp_dir_to_str(buf->dir),
2318 QDF_MAC_ADDR_REF(buf->da.bytes),
2319 buf->cmn_info.proto_priv_data);
2320 }
2321 qdf_export_symbol(qdf_dp_display_proto_pkt);
2322
qdf_dp_trace_proto_pkt(enum QDF_DP_TRACE_ID code,uint8_t * sa,uint8_t * da,enum qdf_proto_dir dir,uint8_t pdev_id,bool print,struct qdf_dp_trace_proto_cmn * cmn_info)2323 void qdf_dp_trace_proto_pkt(enum QDF_DP_TRACE_ID code,
2324 uint8_t *sa, uint8_t *da,
2325 enum qdf_proto_dir dir,
2326 uint8_t pdev_id, bool print,
2327 struct qdf_dp_trace_proto_cmn *cmn_info)
2328 {
2329 struct qdf_dp_trace_proto_buf buf;
2330 int buf_size = sizeof(struct qdf_dp_trace_proto_buf);
2331
2332 if (qdf_dp_enable_check(NULL, code, dir) == false)
2333 return;
2334
2335 if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2336 QDF_BUG(0);
2337
2338 memcpy(&buf.sa, sa, QDF_NET_ETH_LEN);
2339 memcpy(&buf.da, da, QDF_NET_ETH_LEN);
2340 memcpy(&buf.cmn_info, cmn_info, sizeof(*cmn_info));
2341 buf.dir = dir;
2342 qdf_dp_add_record(code, pdev_id,
2343 (uint8_t *)&buf, buf_size, NULL, 0, print);
2344 }
2345 qdf_export_symbol(qdf_dp_trace_proto_pkt);
2346
qdf_dp_display_ptr_record(struct qdf_dp_trace_record_s * record,uint16_t index,uint8_t pdev_id,uint8_t info)2347 void qdf_dp_display_ptr_record(struct qdf_dp_trace_record_s *record,
2348 uint16_t index, uint8_t pdev_id, uint8_t info)
2349 {
2350 int loc;
2351 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2352 struct qdf_dp_trace_ptr_buf *buf =
2353 (struct qdf_dp_trace_ptr_buf *)record->data;
2354 bool is_free_pkt_ptr_record = false;
2355
2356 if ((record->code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) ||
2357 (record->code == QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD))
2358 is_free_pkt_ptr_record = true;
2359
2360 qdf_mem_zero(prepend_str, sizeof(prepend_str));
2361 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2362 index, info, record);
2363
2364 if (loc < sizeof(prepend_str))
2365 scnprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2366 "[msdu id %d %s %d]",
2367 buf->msdu_id,
2368 is_free_pkt_ptr_record ? "status" : "vdev_id",
2369 buf->status);
2370
2371 if (info & QDF_DP_TRACE_RECORD_INFO_LIVE) {
2372 /* In live mode donot dump the contents of the cookie */
2373 DPTRACE_PRINT("%s", prepend_str);
2374 } else {
2375 dump_dp_hex_trace(prepend_str, (uint8_t *)&buf->cookie,
2376 sizeof(buf->cookie));
2377 }
2378 }
2379 qdf_export_symbol(qdf_dp_display_ptr_record);
2380
2381 static
qdf_dp_get_pkt_proto_type(qdf_nbuf_t nbuf)2382 enum qdf_proto_type qdf_dp_get_pkt_proto_type(qdf_nbuf_t nbuf)
2383 {
2384 uint8_t pkt_type;
2385
2386 if (!nbuf)
2387 return QDF_PROTO_TYPE_MAX;
2388
2389 if (qdf_nbuf_data_is_dns_query(nbuf) ||
2390 qdf_nbuf_data_is_dns_response(nbuf))
2391 return QDF_PROTO_TYPE_DNS;
2392
2393 pkt_type = QDF_NBUF_CB_GET_PACKET_TYPE(nbuf);
2394
2395 switch (pkt_type) {
2396 case QDF_NBUF_CB_PACKET_TYPE_EAPOL:
2397 return QDF_PROTO_TYPE_EAPOL;
2398 case QDF_NBUF_CB_PACKET_TYPE_ARP:
2399 return QDF_PROTO_TYPE_ARP;
2400 case QDF_NBUF_CB_PACKET_TYPE_DHCP:
2401 return QDF_PROTO_TYPE_DHCP;
2402 default:
2403 return QDF_PROTO_TYPE_MAX;
2404 }
2405 }
2406
2407 static
qdf_dp_get_pkt_subtype(qdf_nbuf_t nbuf,enum qdf_proto_type pkt_type)2408 enum qdf_proto_subtype qdf_dp_get_pkt_subtype(qdf_nbuf_t nbuf,
2409 enum qdf_proto_type pkt_type)
2410 {
2411 switch (pkt_type) {
2412 case QDF_PROTO_TYPE_EAPOL:
2413 return qdf_nbuf_get_eapol_subtype(nbuf);
2414 case QDF_PROTO_TYPE_ARP:
2415 return qdf_nbuf_get_arp_subtype(nbuf);
2416 case QDF_PROTO_TYPE_DHCP:
2417 return qdf_nbuf_get_dhcp_subtype(nbuf);
2418 case QDF_PROTO_TYPE_DNS:
2419 return (qdf_nbuf_data_is_dns_query(nbuf)) ?
2420 QDF_PROTO_DNS_QUERY : QDF_PROTO_DNS_RES;
2421 default:
2422 return QDF_PROTO_INVALID;
2423 }
2424 }
2425
2426 static
qdf_dp_proto_log_enable_check(enum qdf_proto_type pkt_type,uint16_t status)2427 bool qdf_dp_proto_log_enable_check(enum qdf_proto_type pkt_type,
2428 uint16_t status)
2429 {
2430 if (pkt_type == QDF_PROTO_TYPE_MAX)
2431 return false;
2432
2433 switch (pkt_type) {
2434 case QDF_PROTO_TYPE_EAPOL:
2435 return qdf_dp_get_proto_event_bitmap() &
2436 QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
2437 case QDF_PROTO_TYPE_DHCP:
2438 return qdf_dp_get_proto_event_bitmap() &
2439 QDF_NBUF_PKT_TRAC_TYPE_DHCP;
2440 case QDF_PROTO_TYPE_ARP:
2441 if (status == QDF_TX_RX_STATUS_OK)
2442 return false;
2443 else
2444 return qdf_dp_get_proto_event_bitmap() &
2445 QDF_NBUF_PKT_TRAC_TYPE_ARP;
2446 case QDF_PROTO_TYPE_DNS:
2447 if (status == QDF_TX_RX_STATUS_OK)
2448 return false;
2449 else
2450 return qdf_dp_get_proto_event_bitmap() &
2451 QDF_NBUF_PKT_TRAC_TYPE_DNS;
2452 default:
2453 return false;
2454 }
2455 }
2456
qdf_dp_track_noack_check(qdf_nbuf_t nbuf,enum qdf_proto_subtype * subtype)2457 void qdf_dp_track_noack_check(qdf_nbuf_t nbuf, enum qdf_proto_subtype *subtype)
2458 {
2459 enum qdf_proto_type pkt_type = qdf_dp_get_pkt_proto_type(nbuf);
2460 uint16_t dp_track = 0;
2461
2462 switch (pkt_type) {
2463 case QDF_PROTO_TYPE_EAPOL:
2464 dp_track = qdf_dp_get_proto_bitmap() &
2465 QDF_NBUF_PKT_TRAC_TYPE_EAPOL;
2466 break;
2467 case QDF_PROTO_TYPE_DHCP:
2468 dp_track = qdf_dp_get_proto_bitmap() &
2469 QDF_NBUF_PKT_TRAC_TYPE_DHCP;
2470 break;
2471 case QDF_PROTO_TYPE_ARP:
2472 dp_track = qdf_dp_get_proto_bitmap() &
2473 QDF_NBUF_PKT_TRAC_TYPE_ARP;
2474 break;
2475 case QDF_PROTO_TYPE_DNS:
2476 dp_track = qdf_dp_get_proto_bitmap() &
2477 QDF_NBUF_PKT_TRAC_TYPE_DNS;
2478 break;
2479 default:
2480 break;
2481 }
2482
2483 if (!dp_track) {
2484 *subtype = QDF_PROTO_INVALID;
2485 return;
2486 }
2487
2488 *subtype = qdf_dp_get_pkt_subtype(nbuf, pkt_type);
2489 }
2490 qdf_export_symbol(qdf_dp_track_noack_check);
2491
qdf_dp_get_status_from_a_status(uint8_t status)2492 enum qdf_dp_tx_rx_status qdf_dp_get_status_from_a_status(uint8_t status)
2493 {
2494 if (status == QDF_A_STATUS_ERROR)
2495 return QDF_TX_RX_STATUS_INVALID;
2496 else if (status == QDF_A_STATUS_OK)
2497 return QDF_TX_RX_STATUS_OK;
2498 else
2499 return QDF_TX_RX_STATUS_MAX;
2500 }
2501 qdf_export_symbol(qdf_dp_get_status_from_a_status);
2502
qdf_dp_trace_ptr(qdf_nbuf_t nbuf,enum QDF_DP_TRACE_ID code,uint8_t pdev_id,uint8_t * data,uint8_t size,uint16_t msdu_id,uint16_t buf_arg_status,enum qdf_dp_tx_rx_status qdf_tx_status,enum QDF_OPMODE op_mode)2503 void qdf_dp_trace_ptr(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code,
2504 uint8_t pdev_id, uint8_t *data, uint8_t size,
2505 uint16_t msdu_id, uint16_t buf_arg_status,
2506 enum qdf_dp_tx_rx_status qdf_tx_status,
2507 enum QDF_OPMODE op_mode)
2508 {
2509 struct qdf_dp_trace_ptr_buf buf;
2510 int buf_size = sizeof(struct qdf_dp_trace_ptr_buf);
2511 enum qdf_proto_type pkt_type;
2512 enum qdf_proto_subtype subtype;
2513
2514 pkt_type = qdf_dp_get_pkt_proto_type(nbuf);
2515 if ((code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD ||
2516 code == QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD) &&
2517 qdf_dp_proto_log_enable_check(pkt_type, qdf_tx_status)) {
2518 subtype = qdf_dp_get_pkt_subtype(nbuf, pkt_type);
2519 qdf_dp_log_proto_pkt_info(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET,
2520 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET,
2521 pkt_type, subtype,
2522 QDF_TX, msdu_id, qdf_tx_status);
2523 qdf_fill_wlan_connectivity_log(pkt_type, subtype,
2524 QDF_TX, qdf_tx_status, op_mode,
2525 QDF_NBUF_CB_TX_VDEV_CTX(nbuf),
2526 nbuf->data,
2527 qdf_nbuf_tx_get_band(nbuf));
2528 qdf_log_pkt_cstats(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET,
2529 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET,
2530 pkt_type, subtype, QDF_TX,
2531 qdf_tx_status, QDF_NBUF_CB_TX_VDEV_CTX(nbuf),
2532 op_mode);
2533 }
2534
2535 if (qdf_dp_enable_check(nbuf, code, QDF_TX) == false)
2536 return;
2537
2538 if (buf_size > QDF_DP_TRACE_RECORD_SIZE)
2539 QDF_BUG(0);
2540
2541 qdf_mem_copy(&buf.cookie, data, size);
2542 buf.msdu_id = msdu_id;
2543 buf.status = buf_arg_status;
2544 qdf_dp_add_record(code, pdev_id, (uint8_t *)&buf, buf_size, NULL, 0,
2545 QDF_NBUF_CB_DP_TRACE_PRINT(nbuf));
2546 }
2547 qdf_export_symbol(qdf_dp_trace_ptr);
2548
qdf_dp_trace_data_pkt(qdf_nbuf_t nbuf,uint8_t pdev_id,enum QDF_DP_TRACE_ID code,uint16_t msdu_id,enum qdf_proto_dir dir)2549 void qdf_dp_trace_data_pkt(qdf_nbuf_t nbuf, uint8_t pdev_id,
2550 enum QDF_DP_TRACE_ID code, uint16_t msdu_id,
2551 enum qdf_proto_dir dir)
2552 {
2553 struct qdf_dp_trace_data_buf buf;
2554 enum qdf_proto_type pkt_type;
2555
2556 pkt_type = qdf_dp_get_pkt_proto_type(nbuf);
2557 if (code == QDF_DP_TRACE_DROP_PACKET_RECORD &&
2558 qdf_dp_proto_log_enable_check(pkt_type, QDF_TX_RX_STATUS_DROP))
2559 qdf_dp_log_proto_pkt_info(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET,
2560 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET,
2561 pkt_type,
2562 qdf_dp_get_pkt_subtype(nbuf, pkt_type),
2563 QDF_TX, msdu_id,
2564 QDF_TX_RX_STATUS_DROP);
2565
2566 buf.msdu_id = msdu_id;
2567 if (!qdf_dp_enable_check(nbuf, code, dir))
2568 return;
2569
2570 qdf_dp_add_record(code, pdev_id,
2571 nbuf ? qdf_nbuf_data(nbuf) : NULL,
2572 nbuf ? nbuf->len - nbuf->data_len : 0,
2573 (uint8_t *)&buf, sizeof(struct qdf_dp_trace_data_buf),
2574 (nbuf) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false);
2575 }
2576
2577 qdf_export_symbol(qdf_dp_trace_data_pkt);
2578
qdf_dp_display_record(struct qdf_dp_trace_record_s * record,uint16_t index,uint8_t pdev_id,uint8_t info)2579 void qdf_dp_display_record(struct qdf_dp_trace_record_s *record,
2580 uint16_t index, uint8_t pdev_id, uint8_t info)
2581 {
2582 int loc;
2583 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2584
2585 if (!(pdev_id == QDF_TRACE_DEFAULT_PDEV_ID ||
2586 pdev_id == record->pdev_id))
2587 return;
2588
2589 qdf_mem_zero(prepend_str, sizeof(prepend_str));
2590 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2591 index, info, record);
2592
2593 switch (record->code) {
2594 case QDF_DP_TRACE_HDD_TX_TIMEOUT:
2595 DPTRACE_PRINT(" %s: HDD TX Timeout", prepend_str);
2596 break;
2597 case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
2598 DPTRACE_PRINT(" %s: HDD SoftAP TX Timeout", prepend_str);
2599 break;
2600 case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
2601 DPTRACE_PRINT(" %s: CE Fast Packet Error", prepend_str);
2602 break;
2603 case QDF_DP_TRACE_LI_DP_NULL_RX_PACKET_RECORD:
2604 default:
2605 dump_dp_hex_trace(prepend_str, record->data, record->size);
2606 break;
2607 };
2608 }
2609 qdf_export_symbol(qdf_dp_display_record);
2610
2611 void
qdf_dp_display_data_pkt_record(struct qdf_dp_trace_record_s * record,uint16_t rec_index,uint8_t pdev_id,uint8_t info)2612 qdf_dp_display_data_pkt_record(struct qdf_dp_trace_record_s *record,
2613 uint16_t rec_index, uint8_t pdev_id,
2614 uint8_t info)
2615 {
2616 int loc;
2617 char prepend_str[DP_TRACE_META_DATA_STRLEN + 10];
2618 struct qdf_dp_trace_data_buf *buf =
2619 (struct qdf_dp_trace_data_buf *)record->data;
2620
2621 qdf_mem_zero(prepend_str, sizeof(prepend_str));
2622
2623 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2624 rec_index, info, record);
2625 if (loc < sizeof(prepend_str))
2626 loc += snprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2627 "[%d]", buf->msdu_id);
2628 dump_dp_hex_trace(prepend_str,
2629 &record->data[sizeof(struct qdf_dp_trace_data_buf)],
2630 record->size);
2631 }
2632
qdf_dp_trace(qdf_nbuf_t nbuf,enum QDF_DP_TRACE_ID code,uint8_t pdev_id,uint8_t * data,uint8_t size,enum qdf_proto_dir dir)2633 void qdf_dp_trace(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code, uint8_t pdev_id,
2634 uint8_t *data, uint8_t size, enum qdf_proto_dir dir)
2635 {
2636
2637 if (qdf_dp_enable_check(nbuf, code, dir) == false)
2638 return;
2639
2640 qdf_dp_add_record(code, pdev_id, nbuf ? qdf_nbuf_data(nbuf) : NULL,
2641 size, NULL, 0,
2642 (nbuf) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false);
2643 }
2644 qdf_export_symbol(qdf_dp_trace);
2645
qdf_dp_trace_spin_lock_init(void)2646 void qdf_dp_trace_spin_lock_init(void)
2647 {
2648 spin_lock_init(&l_dp_trace_lock);
2649 }
2650 qdf_export_symbol(qdf_dp_trace_spin_lock_init);
2651
qdf_dp_trace_disable_live_mode(void)2652 void qdf_dp_trace_disable_live_mode(void)
2653 {
2654 g_qdf_dp_trace_data.force_live_mode = 0;
2655 }
2656 qdf_export_symbol(qdf_dp_trace_disable_live_mode);
2657
qdf_dp_trace_enable_live_mode(void)2658 void qdf_dp_trace_enable_live_mode(void)
2659 {
2660 g_qdf_dp_trace_data.force_live_mode = 1;
2661 }
2662 qdf_export_symbol(qdf_dp_trace_enable_live_mode);
2663
qdf_dp_trace_clear_buffer(void)2664 void qdf_dp_trace_clear_buffer(void)
2665 {
2666 g_qdf_dp_trace_data.head = INVALID_QDF_DP_TRACE_ADDR;
2667 g_qdf_dp_trace_data.tail = INVALID_QDF_DP_TRACE_ADDR;
2668 g_qdf_dp_trace_data.num = 0;
2669 g_qdf_dp_trace_data.dump_counter = 0;
2670 g_qdf_dp_trace_data.num_records_to_dump = MAX_QDF_DP_TRACE_RECORDS;
2671 if (g_qdf_dp_trace_data.enable)
2672 memset(g_qdf_dp_trace_tbl, 0,
2673 MAX_QDF_DP_TRACE_RECORDS *
2674 sizeof(struct qdf_dp_trace_record_s));
2675 }
2676 qdf_export_symbol(qdf_dp_trace_clear_buffer);
2677
qdf_dp_trace_dump_stats(void)2678 void qdf_dp_trace_dump_stats(void)
2679 {
2680 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)",
2681 g_qdf_dp_trace_data.tx_count,
2682 g_qdf_dp_trace_data.rx_count,
2683 g_qdf_dp_trace_data.icmp_req,
2684 g_qdf_dp_trace_data.icmp_resp,
2685 g_qdf_dp_trace_data.arp_req,
2686 g_qdf_dp_trace_data.arp_resp,
2687 g_qdf_dp_trace_data.icmpv6_req,
2688 g_qdf_dp_trace_data.icmpv6_resp,
2689 g_qdf_dp_trace_data.icmpv6_ns,
2690 g_qdf_dp_trace_data.icmpv6_na,
2691 g_qdf_dp_trace_data.icmpv6_rs,
2692 g_qdf_dp_trace_data.icmpv6_ra,
2693 g_qdf_dp_trace_data.dhcp_disc,
2694 g_qdf_dp_trace_data.dhcp_off,
2695 g_qdf_dp_trace_data.dhcp_req,
2696 g_qdf_dp_trace_data.dhcp_ack,
2697 g_qdf_dp_trace_data.dhcp_nack,
2698 g_qdf_dp_trace_data.dhcp_others,
2699 g_qdf_dp_trace_data.eapol_m1,
2700 g_qdf_dp_trace_data.eapol_m2,
2701 g_qdf_dp_trace_data.eapol_m3,
2702 g_qdf_dp_trace_data.eapol_m4,
2703 g_qdf_dp_trace_data.eapol_others);
2704 }
2705 qdf_export_symbol(qdf_dp_trace_dump_stats);
2706
2707 /**
2708 * qdf_dpt_dump_hex_trace_debugfs() - read data in file
2709 * @file: file to read
2710 * @str: string to prepend the hexdump with.
2711 * @buf: buffer which contains data to be written
2712 * @buf_len: defines the size of the data to be written
2713 *
2714 * Return: None
2715 */
qdf_dpt_dump_hex_trace_debugfs(qdf_debugfs_file_t file,char * str,uint8_t * buf,uint8_t buf_len)2716 static void qdf_dpt_dump_hex_trace_debugfs(qdf_debugfs_file_t file,
2717 char *str, uint8_t *buf, uint8_t buf_len)
2718 {
2719 unsigned char linebuf[BUFFER_SIZE];
2720 const u8 *ptr = buf;
2721 int i, linelen, remaining = buf_len;
2722
2723 /* Dump the bytes in the last line */
2724 for (i = 0; i < buf_len; i += ROW_SIZE) {
2725 linelen = min(remaining, ROW_SIZE);
2726 remaining -= ROW_SIZE;
2727
2728 hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1,
2729 linebuf, sizeof(linebuf), false);
2730
2731 qdf_debugfs_printf(file, "%s %s\n", str, linebuf);
2732 }
2733 }
2734
2735 /**
2736 * qdf_dpt_display_proto_pkt_debugfs() - display proto packet
2737 * @file: file to read
2738 * @record: dptrace record
2739 * @index: index
2740 *
2741 * Return: none
2742 */
qdf_dpt_display_proto_pkt_debugfs(qdf_debugfs_file_t file,struct qdf_dp_trace_record_s * record,uint32_t index)2743 static void qdf_dpt_display_proto_pkt_debugfs(qdf_debugfs_file_t file,
2744 struct qdf_dp_trace_record_s *record,
2745 uint32_t index)
2746 {
2747 int loc;
2748 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2749 struct qdf_dp_trace_proto_buf *buf =
2750 (struct qdf_dp_trace_proto_buf *)record->data;
2751
2752 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2753 index, 0, record);
2754 qdf_debugfs_printf(file, "%s [%d] [%s] SA: "
2755 QDF_MAC_ADDR_FMT " %s DA: "
2756 QDF_MAC_ADDR_FMT,
2757 prepend_str,
2758 buf->cmn_info.vdev_id,
2759 qdf_dp_subtype_to_str(buf->cmn_info.subtype),
2760 QDF_MAC_ADDR_REF(buf->sa.bytes),
2761 qdf_dp_dir_to_str(buf->dir),
2762 QDF_MAC_ADDR_REF(buf->da.bytes));
2763 qdf_debugfs_printf(file, "\n");
2764 }
2765
2766 /**
2767 * qdf_dpt_display_mgmt_pkt_debugfs() - display mgmt packet
2768 * @file: file to read
2769 * @record: dptrace record
2770 * @index: index
2771 *
2772 * Return: none
2773 */
qdf_dpt_display_mgmt_pkt_debugfs(qdf_debugfs_file_t file,struct qdf_dp_trace_record_s * record,uint32_t index)2774 static void qdf_dpt_display_mgmt_pkt_debugfs(qdf_debugfs_file_t file,
2775 struct qdf_dp_trace_record_s *record,
2776 uint32_t index)
2777 {
2778
2779 int loc;
2780 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2781 struct qdf_dp_trace_mgmt_buf *buf =
2782 (struct qdf_dp_trace_mgmt_buf *)record->data;
2783
2784 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2785 index, 0, record);
2786
2787 qdf_debugfs_printf(file, "%s [%d] [%s %s]\n",
2788 prepend_str,
2789 buf->vdev_id,
2790 qdf_dp_type_to_str(buf->type),
2791 qdf_dp_subtype_to_str(buf->subtype));
2792 }
2793
2794 /**
2795 * qdf_dpt_display_event_record_debugfs() - display event records
2796 * @file: file to read
2797 * @record: dptrace record
2798 * @index: index
2799 *
2800 * Return: none
2801 */
qdf_dpt_display_event_record_debugfs(qdf_debugfs_file_t file,struct qdf_dp_trace_record_s * record,uint32_t index)2802 static void qdf_dpt_display_event_record_debugfs(qdf_debugfs_file_t file,
2803 struct qdf_dp_trace_record_s *record,
2804 uint32_t index)
2805 {
2806 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2807 struct qdf_dp_trace_event_buf *buf =
2808 (struct qdf_dp_trace_event_buf *)record->data;
2809
2810 qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2811 index, 0, record);
2812 qdf_debugfs_printf(file, "%s [%d] [%s %s]\n",
2813 prepend_str,
2814 buf->vdev_id,
2815 qdf_dp_type_to_str(buf->type),
2816 qdf_dp_subtype_to_str(buf->subtype));
2817 }
2818
2819 /**
2820 * qdf_dpt_display_ptr_record_debugfs() - display record ptr
2821 * @file: file to read
2822 * @record: dptrace record
2823 * @index: index
2824 *
2825 * Return: none
2826 */
qdf_dpt_display_ptr_record_debugfs(qdf_debugfs_file_t file,struct qdf_dp_trace_record_s * record,uint32_t index)2827 static void qdf_dpt_display_ptr_record_debugfs(qdf_debugfs_file_t file,
2828 struct qdf_dp_trace_record_s *record,
2829 uint32_t index)
2830 {
2831 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2832 int loc;
2833 struct qdf_dp_trace_ptr_buf *buf =
2834 (struct qdf_dp_trace_ptr_buf *)record->data;
2835 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2836 index, 0, record);
2837
2838 if (loc < sizeof(prepend_str))
2839 scnprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2840 "[msdu id %d %s %d]",
2841 buf->msdu_id,
2842 (record->code ==
2843 QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) ?
2844 "status" : "vdev_id",
2845 buf->status);
2846
2847 qdf_dpt_dump_hex_trace_debugfs(file, prepend_str,
2848 (uint8_t *)&buf->cookie,
2849 sizeof(buf->cookie));
2850 }
2851
2852 /**
2853 * qdf_dpt_display_record_debugfs() - display record
2854 * @file: file to read
2855 * @record: dptrace record
2856 * @index: index
2857 *
2858 * Return: none
2859 */
qdf_dpt_display_record_debugfs(qdf_debugfs_file_t file,struct qdf_dp_trace_record_s * record,uint32_t index)2860 static void qdf_dpt_display_record_debugfs(qdf_debugfs_file_t file,
2861 struct qdf_dp_trace_record_s *record,
2862 uint32_t index)
2863 {
2864 int loc;
2865 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE];
2866 struct qdf_dp_trace_data_buf *buf =
2867 (struct qdf_dp_trace_data_buf *)record->data;
2868
2869 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str),
2870 index, 0, record);
2871 if (loc < sizeof(prepend_str))
2872 loc += snprintf(&prepend_str[loc], sizeof(prepend_str) - loc,
2873 "[%d]", buf->msdu_id);
2874 qdf_dpt_dump_hex_trace_debugfs(file, prepend_str,
2875 record->data, record->size);
2876 }
2877
qdf_dpt_get_curr_pos_debugfs(qdf_debugfs_file_t file,enum qdf_dpt_debugfs_state state)2878 uint32_t qdf_dpt_get_curr_pos_debugfs(qdf_debugfs_file_t file,
2879 enum qdf_dpt_debugfs_state state)
2880 {
2881 uint32_t i = 0;
2882 uint32_t tail;
2883 uint32_t count = g_qdf_dp_trace_data.num;
2884
2885 if (!g_qdf_dp_trace_data.enable) {
2886 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
2887 "%s: Tracing Disabled", __func__);
2888 return QDF_STATUS_E_EMPTY;
2889 }
2890
2891 if (!count) {
2892 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG,
2893 "%s: no packets", __func__);
2894 return QDF_STATUS_E_EMPTY;
2895 }
2896
2897 if (state == QDF_DPT_DEBUGFS_STATE_SHOW_IN_PROGRESS)
2898 return g_qdf_dp_trace_data.curr_pos;
2899
2900 qdf_debugfs_printf(file,
2901 "DPT: config - bitmap 0x%x verb %u #rec %u rec_requested %u live_config %u thresh %u time_limit %u\n",
2902 g_qdf_dp_trace_data.proto_bitmap,
2903 g_qdf_dp_trace_data.verbosity,
2904 g_qdf_dp_trace_data.no_of_record,
2905 g_qdf_dp_trace_data.num_records_to_dump,
2906 g_qdf_dp_trace_data.live_mode_config,
2907 g_qdf_dp_trace_data.high_tput_thresh,
2908 g_qdf_dp_trace_data.thresh_time_limit);
2909
2910 qdf_debugfs_printf(file,
2911 "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",
2912 g_qdf_dp_trace_data.icmp_req,
2913 g_qdf_dp_trace_data.icmp_resp,
2914 g_qdf_dp_trace_data.arp_req,
2915 g_qdf_dp_trace_data.arp_resp,
2916 g_qdf_dp_trace_data.icmpv6_req,
2917 g_qdf_dp_trace_data.icmpv6_resp,
2918 g_qdf_dp_trace_data.icmpv6_ns,
2919 g_qdf_dp_trace_data.icmpv6_na,
2920 g_qdf_dp_trace_data.icmpv6_rs,
2921 g_qdf_dp_trace_data.icmpv6_ra,
2922 g_qdf_dp_trace_data.dhcp_disc,
2923 g_qdf_dp_trace_data.dhcp_off,
2924 g_qdf_dp_trace_data.dhcp_req,
2925 g_qdf_dp_trace_data.dhcp_ack,
2926 g_qdf_dp_trace_data.dhcp_nack,
2927 g_qdf_dp_trace_data.dhcp_others,
2928 g_qdf_dp_trace_data.eapol_m1,
2929 g_qdf_dp_trace_data.eapol_m2,
2930 g_qdf_dp_trace_data.eapol_m3,
2931 g_qdf_dp_trace_data.eapol_m4,
2932 g_qdf_dp_trace_data.eapol_others);
2933
2934 qdf_debugfs_printf(file,
2935 "DPT: Total Records: %d, Head: %d, Tail: %d\n",
2936 g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head,
2937 g_qdf_dp_trace_data.tail);
2938
2939 spin_lock_bh(&l_dp_trace_lock);
2940 if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) {
2941 i = g_qdf_dp_trace_data.head;
2942 tail = g_qdf_dp_trace_data.tail;
2943
2944 if (count > g_qdf_dp_trace_data.num)
2945 count = g_qdf_dp_trace_data.num;
2946
2947 if (tail >= (count - 1))
2948 i = tail - count + 1;
2949 else if (count != MAX_QDF_DP_TRACE_RECORDS)
2950 i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) -
2951 tail);
2952 g_qdf_dp_trace_data.curr_pos = 0;
2953 g_qdf_dp_trace_data.saved_tail = tail;
2954 }
2955 spin_unlock_bh(&l_dp_trace_lock);
2956
2957 return g_qdf_dp_trace_data.saved_tail;
2958 }
2959 qdf_export_symbol(qdf_dpt_get_curr_pos_debugfs);
2960
qdf_dpt_dump_stats_debugfs(qdf_debugfs_file_t file,uint32_t curr_pos)2961 QDF_STATUS qdf_dpt_dump_stats_debugfs(qdf_debugfs_file_t file,
2962 uint32_t curr_pos)
2963 {
2964 struct qdf_dp_trace_record_s p_record;
2965 uint32_t i = curr_pos;
2966 uint16_t num_records_to_dump = g_qdf_dp_trace_data.num_records_to_dump;
2967
2968 if (!g_qdf_dp_trace_data.enable) {
2969 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
2970 "%s: Tracing Disabled", __func__);
2971 return QDF_STATUS_E_FAILURE;
2972 }
2973
2974 if (num_records_to_dump > g_qdf_dp_trace_data.num)
2975 num_records_to_dump = g_qdf_dp_trace_data.num;
2976
2977 /*
2978 * Max dp trace record size should always be less than
2979 * QDF_DP_TRACE_PREPEND_STR_SIZE(100) + BUFFER_SIZE(121).
2980 */
2981 if (WARN_ON(QDF_DP_TRACE_MAX_RECORD_SIZE <
2982 QDF_DP_TRACE_PREPEND_STR_SIZE + BUFFER_SIZE))
2983 return QDF_STATUS_E_FAILURE;
2984
2985 spin_lock_bh(&l_dp_trace_lock);
2986 p_record = g_qdf_dp_trace_tbl[i];
2987 spin_unlock_bh(&l_dp_trace_lock);
2988
2989 for (;; ) {
2990 /*
2991 * Initially we get file as 1 page size, and
2992 * if remaining size in file is less than one record max size,
2993 * then return so that it gets an extra page.
2994 */
2995 if ((file->size - file->count) < QDF_DP_TRACE_MAX_RECORD_SIZE) {
2996 spin_lock_bh(&l_dp_trace_lock);
2997 g_qdf_dp_trace_data.curr_pos = i;
2998 spin_unlock_bh(&l_dp_trace_lock);
2999 return QDF_STATUS_E_FAILURE;
3000 }
3001
3002 switch (p_record.code) {
3003 case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD:
3004 case QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD:
3005 case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD:
3006 qdf_dpt_display_ptr_record_debugfs(file, &p_record, i);
3007 break;
3008
3009 case QDF_DP_TRACE_EAPOL_PACKET_RECORD:
3010 case QDF_DP_TRACE_DHCP_PACKET_RECORD:
3011 case QDF_DP_TRACE_ARP_PACKET_RECORD:
3012 case QDF_DP_TRACE_ICMP_PACKET_RECORD:
3013 case QDF_DP_TRACE_ICMPv6_PACKET_RECORD:
3014 qdf_dpt_display_proto_pkt_debugfs(file, &p_record, i);
3015 break;
3016
3017 case QDF_DP_TRACE_TX_CREDIT_RECORD:
3018 qdf_dpt_display_credit_record_debugfs(file, &p_record,
3019 i);
3020 break;
3021
3022 case QDF_DP_TRACE_MGMT_PACKET_RECORD:
3023 qdf_dpt_display_mgmt_pkt_debugfs(file, &p_record, i);
3024 break;
3025
3026 case QDF_DP_TRACE_EVENT_RECORD:
3027 qdf_dpt_display_event_record_debugfs(file, &p_record,
3028 i);
3029 break;
3030
3031 case QDF_DP_TRACE_HDD_TX_TIMEOUT:
3032 qdf_debugfs_printf(
3033 file, "DPT: %04d: %llu %s\n",
3034 i, p_record.time,
3035 qdf_dp_code_to_string(p_record.code));
3036 qdf_debugfs_printf(file, "HDD TX Timeout\n");
3037 break;
3038
3039 case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT:
3040 qdf_debugfs_printf(
3041 file, "DPT: %04d: %llu %s\n",
3042 i, p_record.time,
3043 qdf_dp_code_to_string(p_record.code));
3044 qdf_debugfs_printf(file, "HDD SoftAP TX Timeout\n");
3045 break;
3046
3047 case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD:
3048 qdf_debugfs_printf(
3049 file, "DPT: %04d: %llu %s\n",
3050 i, p_record.time,
3051 qdf_dp_code_to_string(p_record.code));
3052 qdf_debugfs_printf(file, "CE Fast Packet Error\n");
3053 break;
3054
3055 case QDF_DP_TRACE_MAX:
3056 qdf_debugfs_printf(file,
3057 "%s: QDF_DP_TRACE_MAX event should not be generated\n",
3058 __func__);
3059 break;
3060
3061 case QDF_DP_TRACE_HDD_TX_PACKET_RECORD:
3062 case QDF_DP_TRACE_HDD_RX_PACKET_RECORD:
3063 case QDF_DP_TRACE_TX_PACKET_RECORD:
3064 case QDF_DP_TRACE_RX_PACKET_RECORD:
3065 case QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD:
3066 case QDF_DP_TRACE_LI_DP_RX_PACKET_RECORD:
3067
3068 default:
3069 qdf_dpt_display_record_debugfs(file, &p_record, i);
3070 break;
3071 }
3072
3073 if (++g_qdf_dp_trace_data.dump_counter == num_records_to_dump)
3074 break;
3075
3076 spin_lock_bh(&l_dp_trace_lock);
3077 if (i == 0)
3078 i = MAX_QDF_DP_TRACE_RECORDS;
3079
3080 i -= 1;
3081 p_record = g_qdf_dp_trace_tbl[i];
3082 spin_unlock_bh(&l_dp_trace_lock);
3083 }
3084
3085 g_qdf_dp_trace_data.dump_counter = 0;
3086
3087 return QDF_STATUS_SUCCESS;
3088 }
3089 qdf_export_symbol(qdf_dpt_dump_stats_debugfs);
3090
qdf_dpt_set_value_debugfs(uint8_t proto_bitmap,uint8_t no_of_record,uint8_t verbosity,uint16_t num_records_to_dump)3091 void qdf_dpt_set_value_debugfs(uint8_t proto_bitmap, uint8_t no_of_record,
3092 uint8_t verbosity, uint16_t num_records_to_dump)
3093 {
3094 if (g_qdf_dp_trace_data.enable) {
3095 g_qdf_dp_trace_data.proto_bitmap = proto_bitmap;
3096 g_qdf_dp_trace_data.no_of_record = no_of_record;
3097 g_qdf_dp_trace_data.verbosity = verbosity;
3098 g_qdf_dp_trace_data.num_records_to_dump = num_records_to_dump;
3099 }
3100 }
3101 qdf_export_symbol(qdf_dpt_set_value_debugfs);
3102
3103
qdf_dp_trace_dump_all(uint32_t count,uint8_t pdev_id)3104 void qdf_dp_trace_dump_all(uint32_t count, uint8_t pdev_id)
3105 {
3106 struct qdf_dp_trace_record_s p_record;
3107 int32_t i, tail;
3108
3109 if (!g_qdf_dp_trace_data.enable) {
3110 DPTRACE_PRINT("Tracing Disabled");
3111 return;
3112 }
3113
3114 DPTRACE_PRINT(
3115 "DPT: config - bitmap 0x%x verb %u #rec %u live_config %u thresh %u time_limit %u",
3116 g_qdf_dp_trace_data.proto_bitmap,
3117 g_qdf_dp_trace_data.verbosity,
3118 g_qdf_dp_trace_data.no_of_record,
3119 g_qdf_dp_trace_data.live_mode_config,
3120 g_qdf_dp_trace_data.high_tput_thresh,
3121 g_qdf_dp_trace_data.thresh_time_limit);
3122
3123 qdf_dp_trace_dump_stats();
3124
3125 DPTRACE_PRINT("DPT: Total Records: %d, Head: %d, Tail: %d",
3126 g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head,
3127 g_qdf_dp_trace_data.tail);
3128
3129 /* acquire the lock so that only one thread at a time can read
3130 * the ring buffer
3131 */
3132 spin_lock_bh(&l_dp_trace_lock);
3133
3134 if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) {
3135 i = g_qdf_dp_trace_data.head;
3136 tail = g_qdf_dp_trace_data.tail;
3137
3138 if (count) {
3139 if (count > g_qdf_dp_trace_data.num)
3140 count = g_qdf_dp_trace_data.num;
3141 if (tail >= (count - 1))
3142 i = tail - count + 1;
3143 else if (count != MAX_QDF_DP_TRACE_RECORDS)
3144 i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) -
3145 tail);
3146 }
3147
3148 p_record = g_qdf_dp_trace_tbl[i];
3149 spin_unlock_bh(&l_dp_trace_lock);
3150 for (;; ) {
3151 qdf_dp_trace_cb_table[p_record.code](&p_record,
3152 (uint16_t)i, pdev_id, false);
3153 if (i == tail)
3154 break;
3155 i += 1;
3156
3157 spin_lock_bh(&l_dp_trace_lock);
3158 if (MAX_QDF_DP_TRACE_RECORDS == i)
3159 i = 0;
3160
3161 p_record = g_qdf_dp_trace_tbl[i];
3162 spin_unlock_bh(&l_dp_trace_lock);
3163 }
3164 } else {
3165 spin_unlock_bh(&l_dp_trace_lock);
3166 }
3167 }
3168 qdf_export_symbol(qdf_dp_trace_dump_all);
3169
qdf_dp_trace_throttle_live_mode(bool high_bw_request)3170 void qdf_dp_trace_throttle_live_mode(bool high_bw_request)
3171 {
3172 static int bw_interval_counter;
3173
3174 if (g_qdf_dp_trace_data.enable == false ||
3175 g_qdf_dp_trace_data.live_mode_config == false)
3176 return;
3177
3178 if (high_bw_request) {
3179 g_qdf_dp_trace_data.live_mode = 0;
3180 bw_interval_counter = 0;
3181 return;
3182 }
3183
3184 bw_interval_counter++;
3185
3186 if (0 == (bw_interval_counter %
3187 g_qdf_dp_trace_data.thresh_time_limit)) {
3188
3189 spin_lock_bh(&l_dp_trace_lock);
3190 if (g_qdf_dp_trace_data.print_pkt_cnt <=
3191 g_qdf_dp_trace_data.high_tput_thresh)
3192 g_qdf_dp_trace_data.live_mode = 1;
3193
3194 g_qdf_dp_trace_data.print_pkt_cnt = 0;
3195 spin_unlock_bh(&l_dp_trace_lock);
3196 }
3197 }
3198 qdf_export_symbol(qdf_dp_trace_throttle_live_mode);
3199
qdf_dp_trace_apply_tput_policy(bool is_data_traffic)3200 void qdf_dp_trace_apply_tput_policy(bool is_data_traffic)
3201 {
3202 if (g_qdf_dp_trace_data.dynamic_verbosity_modify) {
3203 goto check_live_mode;
3204 return;
3205 }
3206
3207 if (is_data_traffic) {
3208 g_qdf_dp_trace_data.verbosity =
3209 QDF_DP_TRACE_VERBOSITY_ULTRA_LOW;
3210 } else {
3211 g_qdf_dp_trace_data.verbosity =
3212 g_qdf_dp_trace_data.ini_conf_verbosity;
3213 }
3214 check_live_mode:
3215 qdf_dp_trace_throttle_live_mode(is_data_traffic);
3216 }
3217 #endif
3218
3219 struct qdf_print_ctrl print_ctrl_obj[MAX_PRINT_CONFIG_SUPPORTED];
3220
3221 struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = {
3222 [QDF_MODULE_ID_TDLS] = {"tdls"},
3223 [QDF_MODULE_ID_ACS] = {"ACS"},
3224 [QDF_MODULE_ID_SCAN_SM] = {"scan state machine"},
3225 [QDF_MODULE_ID_SCANENTRY] = {"scan entry"},
3226 [QDF_MODULE_ID_WDS] = {"WDS"},
3227 [QDF_MODULE_ID_ACTION] = {"action"},
3228 [QDF_MODULE_ID_ROAM] = {"STA roaming"},
3229 [QDF_MODULE_ID_INACT] = {"inactivity"},
3230 [QDF_MODULE_ID_DOTH] = {"11h"},
3231 [QDF_MODULE_ID_IQUE] = {"IQUE"},
3232 [QDF_MODULE_ID_WME] = {"WME"},
3233 [QDF_MODULE_ID_ACL] = {"ACL"},
3234 [QDF_MODULE_ID_WPA] = {"WPA/RSN"},
3235 [QDF_MODULE_ID_RADKEYS] = {"dump 802.1x keys"},
3236 [QDF_MODULE_ID_RADDUMP] = {"dump radius packet"},
3237 [QDF_MODULE_ID_RADIUS] = {"802.1x radius client"},
3238 [QDF_MODULE_ID_DOT1XSM] = {"802.1x state machine"},
3239 [QDF_MODULE_ID_DOT1X] = {"802.1x authenticator"},
3240 [QDF_MODULE_ID_POWER] = {"power save"},
3241 [QDF_MODULE_ID_STATE] = {"state"},
3242 [QDF_MODULE_ID_OUTPUT] = {"output"},
3243 [QDF_MODULE_ID_SCAN] = {"scan"},
3244 [QDF_MODULE_ID_AUTH] = {"authentication"},
3245 [QDF_MODULE_ID_ASSOC] = {"association"},
3246 [QDF_MODULE_ID_NODE] = {"node"},
3247 [QDF_MODULE_ID_ELEMID] = {"element ID"},
3248 [QDF_MODULE_ID_XRATE] = {"rate"},
3249 [QDF_MODULE_ID_INPUT] = {"input"},
3250 [QDF_MODULE_ID_CRYPTO] = {"crypto"},
3251 [QDF_MODULE_ID_DUMPPKTS] = {"dump packet"},
3252 [QDF_MODULE_ID_DEBUG] = {"debug"},
3253 [QDF_MODULE_ID_MLME] = {"mlme"},
3254 [QDF_MODULE_ID_RRM] = {"rrm"},
3255 [QDF_MODULE_ID_WNM] = {"wnm"},
3256 [QDF_MODULE_ID_P2P_PROT] = {"p2p_prot"},
3257 [QDF_MODULE_ID_PROXYARP] = {"proxyarp"},
3258 [QDF_MODULE_ID_L2TIF] = {"l2tif"},
3259 [QDF_MODULE_ID_WIFIPOS] = {"wifipos"},
3260 [QDF_MODULE_ID_WRAP] = {"wrap"},
3261 [QDF_MODULE_ID_DFS] = {"dfs"},
3262 [QDF_MODULE_ID_ATF] = {"atf"},
3263 [QDF_MODULE_ID_SPLITMAC] = {"splitmac"},
3264 [QDF_MODULE_ID_IOCTL] = {"ioctl"},
3265 [QDF_MODULE_ID_NAC] = {"nac"},
3266 [QDF_MODULE_ID_MESH] = {"mesh"},
3267 [QDF_MODULE_ID_MBO] = {"mbo"},
3268 [QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = {"extchanswitch"},
3269 [QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = {"extchanscan"},
3270 [QDF_MODULE_ID_TLSHIM] = {"tlshim"},
3271 [QDF_MODULE_ID_WMI] = {"WMI"},
3272 [QDF_MODULE_ID_HTT] = {"HTT"},
3273 [QDF_MODULE_ID_HDD] = {"HDD"},
3274 [QDF_MODULE_ID_SME] = {"SME"},
3275 [QDF_MODULE_ID_PE] = {"PE"},
3276 [QDF_MODULE_ID_WMA] = {"WMA"},
3277 [QDF_MODULE_ID_SYS] = {"SYS"},
3278 [QDF_MODULE_ID_QDF] = {"QDF"},
3279 [QDF_MODULE_ID_SAP] = {"SAP"},
3280 [QDF_MODULE_ID_HDD_SOFTAP] = {"HDD_SAP"},
3281 [QDF_MODULE_ID_HDD_DATA] = {"DATA"},
3282 [QDF_MODULE_ID_HDD_SAP_DATA] = {"SAP_DATA"},
3283 [QDF_MODULE_ID_HIF] = {"HIF"},
3284 [QDF_MODULE_ID_HTC] = {"HTC"},
3285 [QDF_MODULE_ID_TXRX] = {"TXRX"},
3286 [QDF_MODULE_ID_QDF_DEVICE] = {"QDF_DEV"},
3287 [QDF_MODULE_ID_CFG] = {"CFG"},
3288 [QDF_MODULE_ID_BMI] = {"BMI"},
3289 [QDF_MODULE_ID_EPPING] = {"EPPING"},
3290 [QDF_MODULE_ID_QVIT] = {"QVIT"},
3291 [QDF_MODULE_ID_DP] = {"DP"},
3292 [QDF_MODULE_ID_HAL] = {"HAL"},
3293 [QDF_MODULE_ID_SOC] = {"SOC"},
3294 [QDF_MODULE_ID_OS_IF] = {"OSIF"},
3295 [QDF_MODULE_ID_TARGET_IF] = {"TIF"},
3296 [QDF_MODULE_ID_SCHEDULER] = {"SCH"},
3297 [QDF_MODULE_ID_MGMT_TXRX] = {"MGMT_TXRX"},
3298 [QDF_MODULE_ID_PMO] = {"PMO"},
3299 [QDF_MODULE_ID_POLICY_MGR] = {"POLICY_MGR"},
3300 [QDF_MODULE_ID_SA_API] = {"SA_API"},
3301 [QDF_MODULE_ID_NAN] = {"NAN"},
3302 [QDF_MODULE_ID_SPECTRAL] = {"SPECTRAL"},
3303 [QDF_MODULE_ID_P2P] = {"P2P"},
3304 [QDF_MODULE_ID_OFFCHAN_TXRX] = {"OFFCHAN"},
3305 [QDF_MODULE_ID_REGULATORY] = {"REGULATORY"},
3306 [QDF_MODULE_ID_OBJ_MGR] = {"OBJMGR"},
3307 [QDF_MODULE_ID_SERIALIZATION] = {"SER"},
3308 [QDF_MODULE_ID_NSS] = {"NSS"},
3309 [QDF_MODULE_ID_ROAM_DEBUG] = {"roam debug"},
3310 [QDF_MODULE_ID_DIRECT_BUF_RX] = {"DIRECT_BUF_RX"},
3311 [QDF_MODULE_ID_DISA] = {"disa"},
3312 [QDF_MODULE_ID_GREEN_AP] = {"GREEN_AP"},
3313 [QDF_MODULE_ID_FD] = {"FILS discovery"},
3314 [QDF_MODULE_ID_FTM] = {"FTM"},
3315 [QDF_MODULE_ID_OCB] = {"OCB"},
3316 [QDF_MODULE_ID_CONFIG] = {"CONFIG"},
3317 [QDF_MODULE_ID_IPA] = {"IPA"},
3318 [QDF_MODULE_ID_CP_STATS] = {"CP_STATS"},
3319 [QDF_MODULE_ID_DCS] = {"DCS"},
3320 [QDF_MODULE_ID_ACTION_OUI] = {"action_oui"},
3321 [QDF_MODULE_ID_TARGET] = {"TARGET"},
3322 [QDF_MODULE_ID_MBSSIE] = {"MBSSIE"},
3323 [QDF_MODULE_ID_FWOL] = {"fwol"},
3324 [QDF_MODULE_ID_SM_ENGINE] = {"SM_ENG"},
3325 [QDF_MODULE_ID_CMN_MLME] = {"CMN_MLME"},
3326 [QDF_MODULE_ID_BSSCOLOR] = {"BSSCOLOR"},
3327 [QDF_MODULE_ID_CFR] = {"CFR"},
3328 [QDF_MODULE_ID_DP_TX_CAPTURE] = {"TX_CAPTURE_ENHANCE"},
3329 [QDF_MODULE_ID_INTEROP_ISSUES_AP] = {"INTEROP_ISSUES_AP"},
3330 [QDF_MODULE_ID_DENYLIST_MGR] = {"dlm"},
3331 [QDF_MODULE_ID_QLD] = {"QLD"},
3332 [QDF_MODULE_ID_DYNAMIC_MODE_CHG] = {"Dynamic Mode Change"},
3333 [QDF_MODULE_ID_COEX] = {"COEX"},
3334 [QDF_MODULE_ID_MON_FILTER] = {"Monitor Filter"},
3335 [QDF_MODULE_ID_PKT_CAPTURE] = {"pkt_capture"},
3336 [QDF_MODULE_ID_RPTR] = {"RPTR"},
3337 [QDF_MODULE_ID_6GHZ] = {"6GHZ"},
3338 [QDF_MODULE_ID_IOT_SIM] = {"IOT_SIM"},
3339 [QDF_MODULE_ID_MSCS] = {"MSCS"},
3340 [QDF_MODULE_ID_GPIO] = {"GPIO_CFG"},
3341 [QDF_MODULE_ID_IFMGR] = {"IF_MGR"},
3342 [QDF_MODULE_ID_DIAG] = {"DIAG"},
3343 [QDF_MODULE_ID_DP_INIT] = {"DP_INIT"},
3344 [QDF_MODULE_ID_DP_TX] = {"DP_TX"},
3345 [QDF_MODULE_ID_DP_RX] = {"DP_RX"},
3346 [QDF_MODULE_ID_DP_STATS] = {"DP_STATS"},
3347 [QDF_MODULE_ID_DP_HTT] = {"DP_HTT"},
3348 [QDF_MODULE_ID_DP_PEER] = {"DP_PEER"},
3349 [QDF_MODULE_ID_DP_RX_ERROR] = {"DP_RX_ERROR"},
3350 [QDF_MODULE_ID_DP_HTT_TX_STATS] = {"DP_HTT_TX_STATS"},
3351 [QDF_MODULE_ID_DP_RX_MON_STATUS] = {"DP_RX_MON_STATUS"},
3352 [QDF_MODULE_ID_DP_RX_MON_DEST] = {"DP_RX_MON_DEST"},
3353 [QDF_MODULE_ID_DP_REO] = {"DP_REO"},
3354 [QDF_MODULE_ID_DP_TX_COMP] = {"DP_TX_COMP"},
3355 [QDF_MODULE_ID_DP_VDEV] = {"DP_VDEV"},
3356 [QDF_MODULE_ID_DP_CDP] = {"DP_CDP"},
3357 [QDF_MODULE_ID_TSO] = {"TSO"},
3358 [QDF_MODULE_ID_ME] = {"ME"},
3359 [QDF_MODULE_ID_QWRAP] = {"QWRAP"},
3360 [QDF_MODULE_ID_DBDC_REP] = {"DBDC_REP"},
3361 [QDF_MODULE_ID_EXT_AP] = {"EXT_AP"},
3362 [QDF_MODULE_ID_MLO] = {"MLO_MGR"},
3363 [QDF_MODULE_ID_MGMT_RX_REO] = {"MGMT_RX_REO"},
3364 [QDF_MODULE_ID_MLOIE] = {"MLOIE"},
3365 [QDF_MODULE_ID_MBSS] = {"MBSS"},
3366 [QDF_MODULE_ID_MON] = {"MONITOR"},
3367 [QDF_MODULE_ID_AFC] = {"AFC"},
3368 [QDF_MODULE_ID_TWT] = {"TWT"},
3369 [QDF_MODULE_ID_SON] = {"SON"},
3370 [QDF_MODULE_ID_WLAN_PRE_CAC] = {"PRE_CAC"},
3371 [QDF_MODULE_ID_T2LM] = {"T2LM"},
3372 [QDF_MODULE_ID_DP_SAWF] = {"DP_SAWF"},
3373 [QDF_MODULE_ID_SCS] = {"SCS"},
3374 [QDF_MODULE_ID_DP_UMAC_RESET] = {"UMAC_HW_RESET"},
3375 [QDF_MODULE_ID_COAP] = {"COAP"},
3376 [QDF_MODULE_ID_FTM_TIME_SYNC] = {"Time Sync"},
3377 [QDF_MODULE_ID_WIFI_RADAR] = {"WIFI RADAR"},
3378 [QDF_MODULE_ID_CDP] = {"CDP"},
3379 [QDF_MODULE_ID_QMI] = {"QMI"},
3380 [QDF_MODULE_ID_SOUNDING] = {"SOUNDING"},
3381 [QDF_MODULE_ID_SAWF] = {"SAWF"},
3382 [QDF_MODULE_ID_EPCS] = {"EPCS"},
3383 [QDF_MODULE_ID_LL_SAP] = {"LL_SAP"},
3384 [QDF_MODULE_ID_COHOSTED_BSS] = {"COHOSTED_BSS"},
3385 [QDF_MODULE_ID_TELEMETRY_AGENT] = {"TELEMETRY_AGENT"},
3386 [QDF_MODULE_ID_RF_PATH_SWITCH] = {"Dynamic RF Path Switch"},
3387 [QDF_MODULE_ID_ANY] = {"ANY"},
3388 };
3389 qdf_export_symbol(g_qdf_category_name);
3390
qdf_trace_display(void)3391 void qdf_trace_display(void)
3392 {
3393 QDF_MODULE_ID module_id;
3394
3395 pr_err(" 1)FATAL 2)ERROR 3)WARN 4)INFO 5)INFO_H 6)INFO_M 7)INFO_L 8)DEBUG\n");
3396 for (module_id = 0; module_id < QDF_MODULE_ID_MAX; ++module_id) {
3397 pr_err("%2d)%s %s %s %s %s %s %s %s %s\n",
3398 (int)module_id,
3399 g_qdf_category_name[module_id].category_name_str,
3400 qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3401 QDF_TRACE_LEVEL_FATAL) ? "X" : " ",
3402 qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3403 QDF_TRACE_LEVEL_ERROR) ? "X" : " ",
3404 qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3405 QDF_TRACE_LEVEL_WARN) ? "X" : " ",
3406 qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3407 QDF_TRACE_LEVEL_INFO) ? "X" : " ",
3408 qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3409 QDF_TRACE_LEVEL_INFO_HIGH) ? "X" : " ",
3410 qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3411 QDF_TRACE_LEVEL_INFO_MED) ? "X" : " ",
3412 qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3413 QDF_TRACE_LEVEL_INFO_LOW) ? "X" : " ",
3414 qdf_print_is_verbose_enabled(qdf_pidx, module_id,
3415 QDF_TRACE_LEVEL_DEBUG) ? "X" : " ");
3416 }
3417 }
3418 qdf_export_symbol(qdf_trace_display);
3419
3420 #ifdef WLAN_MAX_LOGS_PER_SEC
3421 static qdf_time_t __log_window_end;
3422 static qdf_atomic_t __log_window_count;
3423 uint32_t qdf_rl_print_count = WLAN_MAX_LOGS_PER_SEC;
3424 uint32_t qdf_rl_print_time = 1;
3425 uint32_t qdf_rl_print_suppressed;
3426
qdf_detected_excessive_logging(void)3427 bool qdf_detected_excessive_logging(void)
3428 {
3429 qdf_time_t now = qdf_system_ticks();
3430 bool excessive_prints = false;
3431
3432 /*
3433 * If 'now' is more recent than the end of the window, reset.
3434 *
3435 * Note: This is not thread safe, and can result in more than one reset.
3436 * For our purposes, this is fine.
3437 */
3438 if (!qdf_atomic_read(&__log_window_count)) {
3439 __log_window_end = now + (qdf_system_ticks_per_sec * qdf_rl_print_time);
3440 } else if (qdf_system_time_after(now, __log_window_end)) {
3441 __log_window_end = now + (qdf_system_ticks_per_sec * qdf_rl_print_time);
3442 qdf_atomic_set(&__log_window_count, 0);
3443 }
3444
3445 if (qdf_atomic_inc_return(&__log_window_count) > qdf_rl_print_count)
3446 excessive_prints = true;
3447
3448 return excessive_prints;
3449 }
3450
qdf_rl_print_count_set(uint32_t rl_print_count)3451 void qdf_rl_print_count_set(uint32_t rl_print_count)
3452 {
3453 qdf_rl_print_count = rl_print_count;
3454 }
3455
3456 qdf_export_symbol(qdf_rl_print_count_set);
3457
qdf_rl_print_time_set(uint32_t rl_print_time)3458 void qdf_rl_print_time_set(uint32_t rl_print_time)
3459 {
3460 qdf_rl_print_time = rl_print_time;
3461 }
3462
3463 qdf_export_symbol(qdf_rl_print_time_set);
3464
qdf_rl_print_suppressed_log(void)3465 void qdf_rl_print_suppressed_log(void)
3466 {
3467 if (qdf_rl_print_suppressed) {
3468 pr_err("QDF Ratelimiting: %d prints suppressed",
3469 qdf_rl_print_suppressed);
3470 qdf_rl_print_suppressed = 0;
3471 }
3472 }
3473
qdf_rl_print_suppressed_inc(void)3474 void qdf_rl_print_suppressed_inc(void)
3475 {
3476 qdf_rl_print_suppressed++;
3477 }
3478 #else
3479 #define qdf_rl_print_suppressed_log()
3480 #define qdf_rl_print_suppressed_inc()
3481 #endif /* WLAN_MAX_LOGS_PER_SEC */
3482
3483 #ifdef QDF_TRACE_PRINT_ENABLE
print_to_console(char * str_buffer)3484 static inline void print_to_console(char *str_buffer)
3485 {
3486 if (qdf_in_interrupt() && qdf_detected_excessive_logging()) {
3487 qdf_rl_print_suppressed_inc();
3488 return;
3489 }
3490 qdf_rl_print_suppressed_log();
3491 pr_err("%s\n", str_buffer);
3492 }
3493 #else
3494
3495 #define print_to_console(str)
3496 #endif
3497
3498 #ifdef MULTI_IF_NAME
qdf_trace_wlan_modname(void)3499 static const char *qdf_trace_wlan_modname(void)
3500 {
3501 return MULTI_IF_NAME;
3502 }
3503 #else
qdf_trace_wlan_modname(void)3504 static const char *qdf_trace_wlan_modname(void)
3505 {
3506 return "wlan";
3507 }
3508 #endif
3509
qdf_trace_msg_cmn(unsigned int idx,QDF_MODULE_ID category,QDF_TRACE_LEVEL verbose,const char * str_format,va_list val)3510 void qdf_trace_msg_cmn(unsigned int idx,
3511 QDF_MODULE_ID category,
3512 QDF_TRACE_LEVEL verbose,
3513 const char *str_format, va_list val)
3514 {
3515 char str_buffer[QDF_TRACE_BUFFER_SIZE];
3516 int n;
3517
3518 /* Check if index passed is valid */
3519 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3520 pr_info("%s: Invalid index - %d\n", __func__, idx);
3521 return;
3522 }
3523
3524 /* Check if print control object is in use */
3525 if (!print_ctrl_obj[idx].in_use) {
3526 pr_info("%s: Invalid print control object\n", __func__);
3527 return;
3528 }
3529
3530 /* Check if category passed is valid */
3531 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
3532 vscnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, str_format, val);
3533 pr_info("%s: Invalid category: %d, log: %s\n",
3534 __func__, category, str_buffer);
3535 return;
3536 }
3537
3538 /* Check if verbose mask is valid */
3539 if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
3540 vscnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, str_format, val);
3541 pr_info("%s: Invalid verbose level %d, log: %s\n",
3542 __func__, verbose, str_buffer);
3543 return;
3544 }
3545
3546 /*
3547 * Print the trace message when the desired verbose level is set in
3548 * the desired category for the print control object
3549 */
3550 if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
3551 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
3552 static const char * const VERBOSE_STR[] = {
3553 [QDF_TRACE_LEVEL_NONE] = "",
3554 [QDF_TRACE_LEVEL_FATAL] = "F",
3555 [QDF_TRACE_LEVEL_ERROR] = "E",
3556 [QDF_TRACE_LEVEL_WARN] = "W",
3557 [QDF_TRACE_LEVEL_INFO] = "I",
3558 [QDF_TRACE_LEVEL_INFO_HIGH] = "IH",
3559 [QDF_TRACE_LEVEL_INFO_MED] = "IM",
3560 [QDF_TRACE_LEVEL_INFO_LOW] = "IL",
3561 [QDF_TRACE_LEVEL_DEBUG] = "D",
3562 [QDF_TRACE_LEVEL_TRACE] = "T",
3563 [QDF_TRACE_LEVEL_ALL] = "" };
3564
3565 /* print the prefix string into the string buffer... */
3566 n = scnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE,
3567 "%s: [%d:%s:%s] ", qdf_trace_wlan_modname(),
3568 in_interrupt() ? 0 : current->pid,
3569 VERBOSE_STR[verbose],
3570 g_qdf_category_name[category].category_name_str);
3571
3572 /* print the formatted log message after the prefix string */
3573 vscnprintf(str_buffer + n, QDF_TRACE_BUFFER_SIZE - n,
3574 str_format, val);
3575 #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE)
3576 wlan_log_to_user(verbose, (char *)str_buffer,
3577 strlen(str_buffer));
3578 if (qdf_unlikely(qdf_log_dump_at_kernel_enable))
3579 print_to_console(str_buffer);
3580 #else
3581 pr_err("%s\n", str_buffer);
3582 #endif
3583 }
3584 }
3585 qdf_export_symbol(qdf_trace_msg_cmn);
3586
qdf_print_setup(void)3587 QDF_STATUS qdf_print_setup(void)
3588 {
3589 int i;
3590
3591 /* Loop through all print ctrl objects */
3592 for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
3593 if (qdf_print_ctrl_cleanup(i))
3594 return QDF_STATUS_E_FAILURE;
3595 }
3596 return QDF_STATUS_SUCCESS;
3597 }
3598 qdf_export_symbol(qdf_print_setup);
3599
qdf_print_ctrl_cleanup(unsigned int idx)3600 QDF_STATUS qdf_print_ctrl_cleanup(unsigned int idx)
3601 {
3602 int i = 0;
3603
3604 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
3605 pr_info("%s: Invalid index - %d\n", __func__, idx);
3606 return QDF_STATUS_E_FAILURE;
3607 }
3608
3609 /* Clean up the print control object corresponding to that index
3610 * If success, callee to change print control index to -1
3611 */
3612
3613 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3614 print_ctrl_obj[idx].cat_info[i].category_verbose_mask =
3615 QDF_TRACE_LEVEL_NONE;
3616 }
3617 print_ctrl_obj[idx].custom_print = NULL;
3618 print_ctrl_obj[idx].custom_ctxt = NULL;
3619 qdf_print_clean_node_flag(idx);
3620 print_ctrl_obj[idx].in_use = false;
3621
3622 return QDF_STATUS_SUCCESS;
3623 }
3624 qdf_export_symbol(qdf_print_ctrl_cleanup);
3625
qdf_print_ctrl_register(const struct category_info * cinfo,void * custom_print_handler,void * custom_ctx,const char * pctrl_name)3626 int qdf_print_ctrl_register(const struct category_info *cinfo,
3627 void *custom_print_handler,
3628 void *custom_ctx,
3629 const char *pctrl_name)
3630 {
3631 int idx = -1;
3632 int i = 0;
3633
3634 for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) {
3635 if (!print_ctrl_obj[i].in_use) {
3636 idx = i;
3637 break;
3638 }
3639 }
3640
3641 /* Callee to handle idx -1 appropriately */
3642 if (idx == -1) {
3643 pr_info("%s: Allocation failed! No print control object free\n",
3644 __func__);
3645 return idx;
3646 }
3647
3648 print_ctrl_obj[idx].in_use = true;
3649
3650 /*
3651 * In case callee does not pass category info,
3652 * custom print handler, custom context and print control name,
3653 * we do not set any value here. Clean up for the print control
3654 * getting allocated would have taken care of initializing
3655 * default values.
3656 *
3657 * We need to only set in_use to 1 in such a case
3658 */
3659
3660 if (pctrl_name) {
3661 qdf_str_lcopy(print_ctrl_obj[idx].name, pctrl_name,
3662 sizeof(print_ctrl_obj[idx].name));
3663 }
3664
3665 if (custom_print_handler)
3666 print_ctrl_obj[idx].custom_print = custom_print_handler;
3667
3668 if (custom_ctx)
3669 print_ctrl_obj[idx].custom_ctxt = custom_ctx;
3670
3671 if (cinfo) {
3672 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3673 if (cinfo[i].category_verbose_mask ==
3674 QDF_TRACE_LEVEL_ALL) {
3675 print_ctrl_obj[idx].cat_info[i]
3676 .category_verbose_mask = 0xFFFF;
3677 } else if ((cinfo[i].category_verbose_mask ==
3678 QDF_TRACE_LEVEL_NONE) ||
3679 (cinfo[i].category_verbose_mask ==
3680 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(
3681 QDF_TRACE_LEVEL_NONE))) {
3682 print_ctrl_obj[idx].cat_info[i]
3683 .category_verbose_mask = 0;
3684 } else {
3685 print_ctrl_obj[idx].cat_info[i]
3686 .category_verbose_mask =
3687 cinfo[i].category_verbose_mask;
3688 }
3689 }
3690 }
3691
3692 return idx;
3693 }
3694 qdf_export_symbol(qdf_print_ctrl_register);
3695
3696 #ifdef QDF_TRACE_PRINT_ENABLE
qdf_shared_print_ctrl_cleanup(void)3697 void qdf_shared_print_ctrl_cleanup(void)
3698 {
3699 qdf_print_ctrl_cleanup(qdf_pidx);
3700 }
3701 qdf_export_symbol(qdf_shared_print_ctrl_cleanup);
3702
3703 /*
3704 * Set this to invalid value to differentiate with user-provided
3705 * value.
3706 */
3707 int qdf_dbg_mask = QDF_TRACE_LEVEL_MAX;
3708 qdf_export_symbol(qdf_dbg_mask);
3709 qdf_declare_param(qdf_dbg_mask, int);
3710
3711 /*
3712 * QDF can be passed parameters which indicate the
3713 * debug level for each module.
3714 * an array of string values are passed, each string hold the following form
3715 *
3716 * <module name string>=<integer debug level value>
3717 *
3718 * The array qdf_dbg_arr will hold these module-string=value strings
3719 * The variable qdf_dbg_arr_cnt will have the count of how many such
3720 * string values were passed.
3721 */
3722 static char *qdf_dbg_arr[QDF_MODULE_ID_MAX];
3723 static int qdf_dbg_arr_cnt;
3724 qdf_declare_param_array(qdf_dbg_arr, charp, &qdf_dbg_arr_cnt);
3725
set_cumulative_verbose_mask(QDF_TRACE_LEVEL max_level)3726 static uint16_t set_cumulative_verbose_mask(QDF_TRACE_LEVEL max_level)
3727 {
3728 uint16_t category_verbose_mask = 0;
3729 QDF_TRACE_LEVEL level;
3730
3731 for (level = QDF_TRACE_LEVEL_FATAL; level <= max_level; level++) {
3732 category_verbose_mask |=
3733 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level);
3734 }
3735 return category_verbose_mask;
3736 }
3737
find_qdf_module_from_string(char * str)3738 static QDF_MODULE_ID find_qdf_module_from_string(char *str)
3739 {
3740 QDF_MODULE_ID mod_id;
3741
3742 for (mod_id = 0; mod_id < QDF_MODULE_ID_MAX; mod_id++) {
3743 if (strcasecmp(str,
3744 g_qdf_category_name[mod_id].category_name_str)
3745 == 0) {
3746 break;
3747 }
3748 }
3749 return mod_id;
3750 }
3751
process_qdf_dbg_arr_param(struct category_info * cinfo,int array_index)3752 static void process_qdf_dbg_arr_param(struct category_info *cinfo,
3753 int array_index)
3754 {
3755 char *mod_val_str, *mod_str, *val_str;
3756 unsigned long dbg_level;
3757 QDF_MODULE_ID mod_id;
3758
3759 mod_val_str = qdf_dbg_arr[array_index];
3760 mod_str = strsep(&mod_val_str, "=");
3761 val_str = mod_val_str;
3762 if (!val_str) {
3763 pr_info("qdf_dbg_arr: %s not in the <mod>=<val> form\n",
3764 mod_str);
3765 return;
3766 }
3767
3768 mod_id = find_qdf_module_from_string(mod_str);
3769 if (mod_id >= QDF_MODULE_ID_MAX) {
3770 pr_info("ERROR!!Module name %s not in the list of modules\n",
3771 mod_str);
3772 return;
3773 }
3774
3775 if (kstrtol(val_str, 10, &dbg_level) < 0) {
3776 pr_info("ERROR!!Invalid debug level for module: %s\n",
3777 mod_str);
3778 return;
3779 }
3780
3781 if (dbg_level >= QDF_TRACE_LEVEL_MAX) {
3782 pr_info("ERROR!!Debug level for %s too high", mod_str);
3783 pr_info("max: %d given %lu\n", QDF_TRACE_LEVEL_MAX,
3784 dbg_level);
3785 return;
3786 }
3787
3788 pr_info("User passed setting module %s(%d) to level %lu\n",
3789 mod_str,
3790 mod_id,
3791 dbg_level);
3792 cinfo[mod_id].category_verbose_mask =
3793 set_cumulative_verbose_mask((QDF_TRACE_LEVEL)dbg_level);
3794 }
3795
set_default_trace_levels(struct category_info * cinfo)3796 static void set_default_trace_levels(struct category_info *cinfo)
3797 {
3798 int i;
3799 static QDF_TRACE_LEVEL module_trace_default_level[QDF_MODULE_ID_MAX] = {
3800 [QDF_MODULE_ID_TDLS] = QDF_TRACE_LEVEL_NONE,
3801 [QDF_MODULE_ID_ACS] = QDF_TRACE_LEVEL_NONE,
3802 [QDF_MODULE_ID_SCAN_SM] = QDF_TRACE_LEVEL_NONE,
3803 [QDF_MODULE_ID_SCANENTRY] = QDF_TRACE_LEVEL_NONE,
3804 [QDF_MODULE_ID_WDS] = QDF_TRACE_LEVEL_NONE,
3805 [QDF_MODULE_ID_ACTION] = QDF_TRACE_LEVEL_NONE,
3806 [QDF_MODULE_ID_ROAM] = QDF_TRACE_LEVEL_NONE,
3807 [QDF_MODULE_ID_INACT] = QDF_TRACE_LEVEL_NONE,
3808 [QDF_MODULE_ID_DOTH] = QDF_TRACE_LEVEL_NONE,
3809 [QDF_MODULE_ID_IQUE] = QDF_TRACE_LEVEL_NONE,
3810 [QDF_MODULE_ID_WME] = QDF_TRACE_LEVEL_NONE,
3811 [QDF_MODULE_ID_ACL] = QDF_TRACE_LEVEL_NONE,
3812 [QDF_MODULE_ID_WPA] = QDF_TRACE_LEVEL_NONE,
3813 [QDF_MODULE_ID_RADKEYS] = QDF_TRACE_LEVEL_NONE,
3814 [QDF_MODULE_ID_RADDUMP] = QDF_TRACE_LEVEL_NONE,
3815 [QDF_MODULE_ID_RADIUS] = QDF_TRACE_LEVEL_NONE,
3816 [QDF_MODULE_ID_DOT1XSM] = QDF_TRACE_LEVEL_NONE,
3817 [QDF_MODULE_ID_DOT1X] = QDF_TRACE_LEVEL_NONE,
3818 [QDF_MODULE_ID_POWER] = QDF_TRACE_LEVEL_NONE,
3819 [QDF_MODULE_ID_STATE] = QDF_TRACE_LEVEL_NONE,
3820 [QDF_MODULE_ID_OUTPUT] = QDF_TRACE_LEVEL_NONE,
3821 [QDF_MODULE_ID_SCAN] = QDF_TRACE_LEVEL_ERROR,
3822 [QDF_MODULE_ID_AUTH] = QDF_TRACE_LEVEL_NONE,
3823 [QDF_MODULE_ID_ASSOC] = QDF_TRACE_LEVEL_NONE,
3824 [QDF_MODULE_ID_NODE] = QDF_TRACE_LEVEL_NONE,
3825 [QDF_MODULE_ID_ELEMID] = QDF_TRACE_LEVEL_NONE,
3826 [QDF_MODULE_ID_XRATE] = QDF_TRACE_LEVEL_NONE,
3827 [QDF_MODULE_ID_INPUT] = QDF_TRACE_LEVEL_NONE,
3828 [QDF_MODULE_ID_CRYPTO] = QDF_TRACE_LEVEL_NONE,
3829 [QDF_MODULE_ID_DUMPPKTS] = QDF_TRACE_LEVEL_NONE,
3830 [QDF_MODULE_ID_DEBUG] = QDF_TRACE_LEVEL_NONE,
3831 [QDF_MODULE_ID_MLME] = QDF_TRACE_LEVEL_ERROR,
3832 [QDF_MODULE_ID_RRM] = QDF_TRACE_LEVEL_NONE,
3833 [QDF_MODULE_ID_WNM] = QDF_TRACE_LEVEL_NONE,
3834 [QDF_MODULE_ID_P2P_PROT] = QDF_TRACE_LEVEL_NONE,
3835 [QDF_MODULE_ID_PROXYARP] = QDF_TRACE_LEVEL_NONE,
3836 [QDF_MODULE_ID_L2TIF] = QDF_TRACE_LEVEL_NONE,
3837 [QDF_MODULE_ID_WIFIPOS] = QDF_TRACE_LEVEL_NONE,
3838 [QDF_MODULE_ID_WRAP] = QDF_TRACE_LEVEL_NONE,
3839 [QDF_MODULE_ID_DFS] = QDF_TRACE_LEVEL_NONE,
3840 [QDF_MODULE_ID_ATF] = QDF_TRACE_LEVEL_ERROR,
3841 [QDF_MODULE_ID_SPLITMAC] = QDF_TRACE_LEVEL_NONE,
3842 [QDF_MODULE_ID_IOCTL] = QDF_TRACE_LEVEL_NONE,
3843 [QDF_MODULE_ID_NAC] = QDF_TRACE_LEVEL_NONE,
3844 [QDF_MODULE_ID_MESH] = QDF_TRACE_LEVEL_NONE,
3845 [QDF_MODULE_ID_MBO] = QDF_TRACE_LEVEL_NONE,
3846 [QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = QDF_TRACE_LEVEL_NONE,
3847 [QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = QDF_TRACE_LEVEL_NONE,
3848 [QDF_MODULE_ID_TLSHIM] = QDF_TRACE_LEVEL_NONE,
3849 [QDF_MODULE_ID_WMI] = QDF_TRACE_LEVEL_ERROR,
3850 [QDF_MODULE_ID_HTT] = QDF_TRACE_LEVEL_NONE,
3851 [QDF_MODULE_ID_HDD] = QDF_TRACE_LEVEL_NONE,
3852 [QDF_MODULE_ID_SME] = QDF_TRACE_LEVEL_NONE,
3853 [QDF_MODULE_ID_PE] = QDF_TRACE_LEVEL_NONE,
3854 [QDF_MODULE_ID_WMA] = QDF_TRACE_LEVEL_NONE,
3855 [QDF_MODULE_ID_SYS] = QDF_TRACE_LEVEL_NONE,
3856 [QDF_MODULE_ID_QDF] = QDF_TRACE_LEVEL_ERROR,
3857 [QDF_MODULE_ID_SAP] = QDF_TRACE_LEVEL_NONE,
3858 [QDF_MODULE_ID_HDD_SOFTAP] = QDF_TRACE_LEVEL_NONE,
3859 [QDF_MODULE_ID_HDD_DATA] = QDF_TRACE_LEVEL_NONE,
3860 [QDF_MODULE_ID_HDD_SAP_DATA] = QDF_TRACE_LEVEL_NONE,
3861 [QDF_MODULE_ID_HIF] = QDF_TRACE_LEVEL_ERROR,
3862 [QDF_MODULE_ID_HTC] = QDF_TRACE_LEVEL_NONE,
3863 [QDF_MODULE_ID_TXRX] = QDF_TRACE_LEVEL_NONE,
3864 [QDF_MODULE_ID_QDF_DEVICE] = QDF_TRACE_LEVEL_NONE,
3865 [QDF_MODULE_ID_CFG] = QDF_TRACE_LEVEL_NONE,
3866 [QDF_MODULE_ID_BMI] = QDF_TRACE_LEVEL_NONE,
3867 [QDF_MODULE_ID_EPPING] = QDF_TRACE_LEVEL_NONE,
3868 [QDF_MODULE_ID_QVIT] = QDF_TRACE_LEVEL_NONE,
3869 [QDF_MODULE_ID_DP] = QDF_TRACE_LEVEL_FATAL,
3870 [QDF_MODULE_ID_HAL] = QDF_TRACE_LEVEL_NONE,
3871 [QDF_MODULE_ID_SOC] = QDF_TRACE_LEVEL_NONE,
3872 [QDF_MODULE_ID_OS_IF] = QDF_TRACE_LEVEL_NONE,
3873 [QDF_MODULE_ID_TARGET_IF] = QDF_TRACE_LEVEL_INFO,
3874 [QDF_MODULE_ID_SCHEDULER] = QDF_TRACE_LEVEL_FATAL,
3875 [QDF_MODULE_ID_MGMT_TXRX] = QDF_TRACE_LEVEL_NONE,
3876 [QDF_MODULE_ID_SERIALIZATION] = QDF_TRACE_LEVEL_ERROR,
3877 [QDF_MODULE_ID_PMO] = QDF_TRACE_LEVEL_NONE,
3878 [QDF_MODULE_ID_P2P] = QDF_TRACE_LEVEL_NONE,
3879 [QDF_MODULE_ID_POLICY_MGR] = QDF_TRACE_LEVEL_NONE,
3880 [QDF_MODULE_ID_CONFIG] = QDF_TRACE_LEVEL_ERROR,
3881 [QDF_MODULE_ID_REGULATORY] = QDF_TRACE_LEVEL_NONE,
3882 [QDF_MODULE_ID_SA_API] = QDF_TRACE_LEVEL_NONE,
3883 [QDF_MODULE_ID_NAN] = QDF_TRACE_LEVEL_NONE,
3884 [QDF_MODULE_ID_OFFCHAN_TXRX] = QDF_TRACE_LEVEL_NONE,
3885 [QDF_MODULE_ID_SON] = QDF_TRACE_LEVEL_NONE,
3886 [QDF_MODULE_ID_SPECTRAL] = QDF_TRACE_LEVEL_ERROR,
3887 [QDF_MODULE_ID_OBJ_MGR] = QDF_TRACE_LEVEL_FATAL,
3888 [QDF_MODULE_ID_NSS] = QDF_TRACE_LEVEL_ERROR,
3889 [QDF_MODULE_ID_ROAM_DEBUG] = QDF_TRACE_LEVEL_ERROR,
3890 [QDF_MODULE_ID_CDP] = QDF_TRACE_LEVEL_NONE,
3891 [QDF_MODULE_ID_DIRECT_BUF_RX] = QDF_TRACE_LEVEL_ERROR,
3892 [QDF_MODULE_ID_DISA] = QDF_TRACE_LEVEL_NONE,
3893 [QDF_MODULE_ID_GREEN_AP] = QDF_TRACE_LEVEL_ERROR,
3894 [QDF_MODULE_ID_FTM] = QDF_TRACE_LEVEL_ERROR,
3895 [QDF_MODULE_ID_FD] = QDF_TRACE_LEVEL_ERROR,
3896 [QDF_MODULE_ID_OCB] = QDF_TRACE_LEVEL_ERROR,
3897 [QDF_MODULE_ID_IPA] = QDF_TRACE_LEVEL_NONE,
3898 [QDF_MODULE_ID_ACTION_OUI] = QDF_TRACE_LEVEL_NONE,
3899 [QDF_MODULE_ID_CP_STATS] = QDF_TRACE_LEVEL_ERROR,
3900 [QDF_MODULE_ID_DCS] = QDF_TRACE_LEVEL_ERROR,
3901 [QDF_MODULE_ID_MBSSIE] = QDF_TRACE_LEVEL_INFO,
3902 [QDF_MODULE_ID_FWOL] = QDF_TRACE_LEVEL_NONE,
3903 [QDF_MODULE_ID_SM_ENGINE] = QDF_TRACE_LEVEL_ERROR,
3904 [QDF_MODULE_ID_CMN_MLME] = QDF_TRACE_LEVEL_INFO,
3905 [QDF_MODULE_ID_BSSCOLOR] = QDF_TRACE_LEVEL_ERROR,
3906 [QDF_MODULE_ID_CFR] = QDF_TRACE_LEVEL_ERROR,
3907 [QDF_MODULE_ID_DP_TX_CAPTURE] = QDF_TRACE_LEVEL_FATAL,
3908 [QDF_MODULE_ID_INTEROP_ISSUES_AP] = QDF_TRACE_LEVEL_NONE,
3909 [QDF_MODULE_ID_DENYLIST_MGR] = QDF_TRACE_LEVEL_NONE,
3910 [QDF_MODULE_ID_QLD] = QDF_TRACE_LEVEL_ERROR,
3911 [QDF_MODULE_ID_DYNAMIC_MODE_CHG] = QDF_TRACE_LEVEL_INFO,
3912 [QDF_MODULE_ID_COEX] = QDF_TRACE_LEVEL_ERROR,
3913 [QDF_MODULE_ID_MON_FILTER] = QDF_TRACE_LEVEL_INFO,
3914 [QDF_MODULE_ID_PKT_CAPTURE] = QDF_TRACE_LEVEL_NONE,
3915 [QDF_MODULE_ID_RPTR] = QDF_TRACE_LEVEL_INFO,
3916 [QDF_MODULE_ID_6GHZ] = QDF_TRACE_LEVEL_ERROR,
3917 [QDF_MODULE_ID_IOT_SIM] = QDF_TRACE_LEVEL_ERROR,
3918 [QDF_MODULE_ID_MSCS] = QDF_TRACE_LEVEL_INFO,
3919 [QDF_MODULE_ID_GPIO] = QDF_TRACE_LEVEL_NONE,
3920 [QDF_MODULE_ID_IFMGR] = QDF_TRACE_LEVEL_ERROR,
3921 [QDF_MODULE_ID_DIAG] = QDF_TRACE_LEVEL_ERROR,
3922 [QDF_MODULE_ID_DP_INIT] = QDF_TRACE_LEVEL_FATAL,
3923 [QDF_MODULE_ID_DP_TX] = QDF_TRACE_LEVEL_FATAL,
3924 [QDF_MODULE_ID_DP_RX] = QDF_TRACE_LEVEL_FATAL,
3925 [QDF_MODULE_ID_DP_STATS] = QDF_TRACE_LEVEL_FATAL,
3926 [QDF_MODULE_ID_DP_HTT] = QDF_TRACE_LEVEL_FATAL,
3927 [QDF_MODULE_ID_DP_PEER] = QDF_TRACE_LEVEL_FATAL,
3928 [QDF_MODULE_ID_DP_RX_ERROR] = QDF_TRACE_LEVEL_FATAL,
3929 [QDF_MODULE_ID_DP_HTT_TX_STATS] = QDF_TRACE_LEVEL_FATAL,
3930 [QDF_MODULE_ID_DP_RX_MON_STATUS] = QDF_TRACE_LEVEL_FATAL,
3931 [QDF_MODULE_ID_DP_RX_MON_DEST] = QDF_TRACE_LEVEL_FATAL,
3932 [QDF_MODULE_ID_DP_REO] = QDF_TRACE_LEVEL_FATAL,
3933 [QDF_MODULE_ID_DP_TX_COMP] = QDF_TRACE_LEVEL_FATAL,
3934 [QDF_MODULE_ID_DP_VDEV] = QDF_TRACE_LEVEL_FATAL,
3935 [QDF_MODULE_ID_DP_CDP] = QDF_TRACE_LEVEL_FATAL,
3936 [QDF_MODULE_ID_TSO] = QDF_TRACE_LEVEL_FATAL,
3937 [QDF_MODULE_ID_ME] = QDF_TRACE_LEVEL_INFO,
3938 [QDF_MODULE_ID_QWRAP] = QDF_TRACE_LEVEL_FATAL,
3939 [QDF_MODULE_ID_DBDC_REP] = QDF_TRACE_LEVEL_FATAL,
3940 [QDF_MODULE_ID_EXT_AP] = QDF_TRACE_LEVEL_NONE,
3941 [QDF_MODULE_ID_MLO] = QDF_TRACE_LEVEL_INFO,
3942 [QDF_MODULE_ID_MLOIE] = QDF_TRACE_LEVEL_INFO,
3943 [QDF_MODULE_ID_MBSS] = QDF_TRACE_LEVEL_ERROR,
3944 [QDF_MODULE_ID_MON] = QDF_TRACE_LEVEL_ERROR,
3945 [QDF_MODULE_ID_MGMT_RX_REO] = QDF_TRACE_LEVEL_WARN,
3946 [QDF_MODULE_ID_TWT] = QDF_TRACE_LEVEL_ERROR,
3947 [QDF_MODULE_ID_WLAN_PRE_CAC] = QDF_TRACE_LEVEL_ERROR,
3948 [QDF_MODULE_ID_T2LM] = QDF_TRACE_LEVEL_ERROR,
3949 [QDF_MODULE_ID_DP_SAWF] = QDF_TRACE_LEVEL_ERROR,
3950 [QDF_MODULE_ID_SCS] = QDF_TRACE_LEVEL_ERROR,
3951 [QDF_MODULE_ID_DP_UMAC_RESET] = QDF_TRACE_LEVEL_ERROR,
3952 [QDF_MODULE_ID_COAP] = QDF_TRACE_LEVEL_ERROR,
3953 [QDF_MODULE_ID_FTM_TIME_SYNC] = QDF_TRACE_LEVEL_NONE,
3954 [QDF_MODULE_ID_AFC] = QDF_TRACE_LEVEL_NONE,
3955 [QDF_MODULE_ID_WIFI_RADAR] = QDF_TRACE_LEVEL_NONE,
3956 [QDF_MODULE_ID_TARGET] = QDF_TRACE_LEVEL_NONE,
3957 [QDF_MODULE_ID_QMI] = QDF_TRACE_LEVEL_ERROR,
3958 [QDF_MODULE_ID_SOUNDING] = QDF_TRACE_LEVEL_ERROR,
3959 [QDF_MODULE_ID_SAWF] = QDF_TRACE_LEVEL_INFO,
3960 [QDF_MODULE_ID_EPCS] = QDF_TRACE_LEVEL_INFO,
3961 [QDF_MODULE_ID_LL_SAP] = QDF_TRACE_LEVEL_NONE,
3962 [QDF_MODULE_ID_COHOSTED_BSS] = QDF_TRACE_LEVEL_INFO,
3963 [QDF_MODULE_ID_TELEMETRY_AGENT] = QDF_TRACE_LEVEL_ERROR,
3964 [QDF_MODULE_ID_RF_PATH_SWITCH] = QDF_TRACE_LEVEL_INFO,
3965 [QDF_MODULE_ID_ANY] = QDF_TRACE_LEVEL_INFO,
3966 };
3967
3968 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3969 cinfo[i].category_verbose_mask = set_cumulative_verbose_mask(
3970 module_trace_default_level[i]);
3971 }
3972 }
3973
qdf_shared_print_ctrl_init(void)3974 void qdf_shared_print_ctrl_init(void)
3975 {
3976 int i;
3977 struct category_info cinfo[MAX_SUPPORTED_CATEGORY];
3978
3979 set_default_trace_levels(cinfo);
3980
3981 /*
3982 * User specified across-module single debug level
3983 */
3984 if ((qdf_dbg_mask >= 0) && (qdf_dbg_mask < QDF_TRACE_LEVEL_MAX)) {
3985 pr_info("User specified module debug level of %d\n",
3986 qdf_dbg_mask);
3987 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) {
3988 cinfo[i].category_verbose_mask =
3989 set_cumulative_verbose_mask(qdf_dbg_mask);
3990 }
3991 } else if (qdf_dbg_mask != QDF_TRACE_LEVEL_MAX) {
3992 pr_info("qdf_dbg_mask value is invalid\n");
3993 pr_info("Using the default module debug levels instead\n");
3994 }
3995
3996 /*
3997 * Module ID-Level specified as array during module load
3998 */
3999 for (i = 0; i < qdf_dbg_arr_cnt; i++) {
4000 process_qdf_dbg_arr_param(cinfo, i);
4001 }
4002 qdf_pidx = qdf_print_ctrl_register(cinfo, NULL, NULL,
4003 "LOG_SHARED_OBJ");
4004 }
4005 qdf_export_symbol(qdf_shared_print_ctrl_init);
4006 #endif
4007
4008 #ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI
qdf_module_param_handler(void * context,const char * str_param,const char * str)4009 QDF_STATUS qdf_module_param_handler(void *context, const char *str_param,
4010 const char *str)
4011 {
4012 QDF_STATUS status = QDF_STATUS_E_FAILURE;
4013 uint16_t param = 0;
4014 uint32_t flush_tmr_prd;
4015 bool dump_flag;
4016
4017 while (param < QDF_PARAM_MAX) {
4018 if (qdf_str_eq(qdf_module_param[param], str_param)) {
4019 switch (param) {
4020 case MEM_DEBUG_DISABLED:
4021 status = qdf_mem_debug_disabled_config_set(str);
4022 break;
4023 case QDF_DBG_MASK:
4024 status = qdf_int32_parse(str, &qdf_dbg_mask);
4025 break;
4026 case PREALLOC_DISABLED:
4027 status = qdf_prealloc_disabled_config_set(str);
4028 break;
4029 case QDF_LOG_DUMP_AT_KERNEL_ENABLE:
4030 status = qdf_bool_parse(str, &dump_flag);
4031 qdf_log_dump_at_kernel_enable = dump_flag;
4032 break;
4033 case QDF_DBG_ARR:
4034 qdf_dbg_arr[0] = (char *)str;
4035 status = QDF_STATUS_SUCCESS;
4036 break;
4037 case QDF_LOG_FLUSH_TIMER_PERIOD:
4038 status = qdf_uint32_parse(str, &flush_tmr_prd);
4039 qdf_log_flush_timer_period = flush_tmr_prd;
4040 break;
4041 default:
4042 break;
4043 }
4044 return status;
4045 }
4046 param++;
4047 }
4048
4049 return QDF_STATUS_SUCCESS;
4050 }
4051
qdf_initialize_module_param_from_ini(void)4052 void qdf_initialize_module_param_from_ini(void)
4053 {
4054 QDF_STATUS status;
4055 char *path = QDF_WIFI_MODULE_PARAMS_FILE;
4056
4057 status = qdf_ini_parse(path, NULL, qdf_module_param_handler, NULL);
4058 if (QDF_IS_STATUS_ERROR(status)) {
4059 QDF_TRACE_ERROR(QDF_MODULE_ID_QDF,
4060 "Failed to parse *.ini file @ %s; status:%d",
4061 path, status);
4062 return;
4063 }
4064 }
4065 #endif
4066
qdf_print_set_category_verbose(unsigned int idx,QDF_MODULE_ID category,QDF_TRACE_LEVEL verbose,bool is_set)4067 QDF_STATUS qdf_print_set_category_verbose(unsigned int idx,
4068 QDF_MODULE_ID category,
4069 QDF_TRACE_LEVEL verbose,
4070 bool is_set)
4071 {
4072 /* Check if index passed is valid */
4073 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4074 pr_err("%s: Invalid index - %d\n", __func__, idx);
4075 return QDF_STATUS_E_FAILURE;
4076 }
4077
4078 /* Check if print control object is in use */
4079 if (!print_ctrl_obj[idx].in_use) {
4080 pr_err("%s: Invalid print control object\n", __func__);
4081 return QDF_STATUS_E_FAILURE;
4082 }
4083
4084 /* Check if category passed is valid */
4085 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
4086 pr_err("%s: Invalid category: %d\n", __func__, category);
4087 return QDF_STATUS_E_FAILURE;
4088 }
4089
4090 /* Check if verbose mask is valid */
4091 if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) {
4092 pr_err("%s: Invalid verbose level %d\n", __func__, verbose);
4093 return QDF_STATUS_E_FAILURE;
4094 }
4095
4096 if (verbose == QDF_TRACE_LEVEL_ALL) {
4097 print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
4098 0xFFFF;
4099 return QDF_STATUS_SUCCESS;
4100 }
4101
4102 if (verbose == QDF_TRACE_LEVEL_NONE) {
4103 print_ctrl_obj[idx].cat_info[category].category_verbose_mask =
4104 QDF_TRACE_LEVEL_NONE;
4105 return QDF_STATUS_SUCCESS;
4106 }
4107
4108 if (!is_set) {
4109 if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask
4110 & QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) {
4111 print_ctrl_obj[idx].cat_info[category]
4112 .category_verbose_mask &=
4113 ~QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
4114 }
4115 } else {
4116 print_ctrl_obj[idx].cat_info[category].category_verbose_mask |=
4117 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose);
4118 }
4119
4120 pr_debug("%s: Print control object %d, Category %d, Verbose level %d\n",
4121 __func__,
4122 idx,
4123 category,
4124 print_ctrl_obj[idx].cat_info[category].category_verbose_mask);
4125
4126 return QDF_STATUS_SUCCESS;
4127 }
4128 qdf_export_symbol(qdf_print_set_category_verbose);
4129
qdf_log_dump_at_kernel_level(bool enable)4130 void qdf_log_dump_at_kernel_level(bool enable)
4131 {
4132 if (qdf_log_dump_at_kernel_enable == enable) {
4133 QDF_TRACE_INFO(QDF_MODULE_ID_QDF,
4134 "qdf_log_dump_at_kernel_enable is already %d\n",
4135 enable);
4136 }
4137 qdf_log_dump_at_kernel_enable = enable;
4138 }
4139
4140 qdf_export_symbol(qdf_log_dump_at_kernel_level);
4141
qdf_print_get_category_verbose(unsigned int idx,QDF_MODULE_ID category)4142 QDF_TRACE_LEVEL qdf_print_get_category_verbose(unsigned int idx,
4143 QDF_MODULE_ID category)
4144 {
4145 /* Check if index passed is valid */
4146 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4147 pr_info("%s: Invalid index - %d\n", __func__, idx);
4148 return false;
4149 }
4150
4151 /* Check if print control object is in use */
4152 if (!print_ctrl_obj[idx].in_use) {
4153 pr_info("%s: Invalid print control object\n", __func__);
4154 return false;
4155 }
4156
4157 /* Check if category passed is valid */
4158 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
4159 pr_info("%s: Invalid category: %d\n", __func__, category);
4160 return false;
4161 }
4162
4163 return print_ctrl_obj[idx].cat_info[category].category_verbose_mask;
4164 }
4165
4166 qdf_export_symbol(qdf_print_get_category_verbose);
4167
qdf_print_is_category_enabled(unsigned int idx,QDF_MODULE_ID category)4168 bool qdf_print_is_category_enabled(unsigned int idx, QDF_MODULE_ID category)
4169 {
4170 QDF_TRACE_LEVEL verbose_mask;
4171
4172 verbose_mask = qdf_print_get_category_verbose(idx, category);
4173
4174 if (verbose_mask == QDF_TRACE_LEVEL_NONE)
4175 return false;
4176 else
4177 return true;
4178 }
4179
4180 qdf_export_symbol(qdf_print_is_category_enabled);
4181
qdf_print_is_verbose_enabled(unsigned int idx,QDF_MODULE_ID category,QDF_TRACE_LEVEL verbose)4182 bool qdf_print_is_verbose_enabled(unsigned int idx, QDF_MODULE_ID category,
4183 QDF_TRACE_LEVEL verbose)
4184 {
4185 bool verbose_enabled = false;
4186
4187 /* Check if index passed is valid */
4188 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4189 pr_info("%s: Invalid index - %d\n", __func__, idx);
4190 return verbose_enabled;
4191 }
4192
4193 /* Check if print control object is in use */
4194 if (!print_ctrl_obj[idx].in_use) {
4195 pr_info("%s: Invalid print control object\n", __func__);
4196 return verbose_enabled;
4197 }
4198
4199 /* Check if category passed is valid */
4200 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) {
4201 pr_info("%s: Invalid category: %d\n", __func__, category);
4202 return verbose_enabled;
4203 }
4204
4205 if ((verbose == QDF_TRACE_LEVEL_NONE) ||
4206 (verbose >= QDF_TRACE_LEVEL_MAX)) {
4207 verbose_enabled = false;
4208 } else if (verbose == QDF_TRACE_LEVEL_ALL) {
4209 if (print_ctrl_obj[idx].cat_info[category]
4210 .category_verbose_mask == 0xFFFF)
4211 verbose_enabled = true;
4212 } else {
4213 verbose_enabled =
4214 (print_ctrl_obj[idx].cat_info[category].category_verbose_mask &
4215 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) ? true : false;
4216 }
4217
4218 return verbose_enabled;
4219 }
4220 qdf_export_symbol(qdf_print_is_verbose_enabled);
4221
4222 #ifdef DBG_LVL_MAC_FILTERING
4223
qdf_print_set_node_flag(unsigned int idx,uint8_t enable)4224 QDF_STATUS qdf_print_set_node_flag(unsigned int idx, uint8_t enable)
4225 {
4226 /* Check if index passed is valid */
4227 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4228 pr_info("%s: Invalid index - %d\n", __func__, idx);
4229 return QDF_STATUS_E_FAILURE;
4230 }
4231
4232 /* Check if print control object is in use */
4233 if (!print_ctrl_obj[idx].in_use) {
4234 pr_info("%s: Invalid print control object\n", __func__);
4235 return QDF_STATUS_E_FAILURE;
4236 }
4237
4238 if (enable > 1) {
4239 pr_info("%s: Incorrect input: Use 1 or 0 to enable or disable\n",
4240 __func__);
4241 return QDF_STATUS_E_FAILURE;
4242 }
4243
4244 print_ctrl_obj[idx].dbglvlmac_on = enable;
4245 pr_info("%s: DbgLVLmac feature %s\n",
4246 __func__,
4247 ((enable) ? "enabled" : "disabled"));
4248
4249 return QDF_STATUS_SUCCESS;
4250 }
4251 qdf_export_symbol(qdf_print_set_node_flag);
4252
qdf_print_get_node_flag(unsigned int idx)4253 bool qdf_print_get_node_flag(unsigned int idx)
4254 {
4255 bool node_flag = false;
4256
4257 /* Check if index passed is valid */
4258 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) {
4259 pr_info("%s: Invalid index - %d\n", __func__, idx);
4260 return node_flag;
4261 }
4262
4263 /* Check if print control object is in use */
4264 if (!print_ctrl_obj[idx].in_use) {
4265 pr_info("%s: Invalid print control object\n", __func__);
4266 return node_flag;
4267 }
4268
4269 if (print_ctrl_obj[idx].dbglvlmac_on)
4270 node_flag = true;
4271
4272 return node_flag;
4273 }
4274 qdf_export_symbol(qdf_print_get_node_flag);
4275
qdf_print_clean_node_flag(unsigned int idx)4276 void qdf_print_clean_node_flag(unsigned int idx)
4277 {
4278 /* Disable dbglvlmac_on during cleanup */
4279 print_ctrl_obj[idx].dbglvlmac_on = 0;
4280 }
4281
4282 #else
4283
qdf_print_clean_node_flag(unsigned int idx)4284 void qdf_print_clean_node_flag(unsigned int idx)
4285 {
4286 /* No operation in case of no support for DBG_LVL_MAC_FILTERING */
4287 return;
4288 }
4289 #endif
4290
QDF_PRINT_INFO(unsigned int idx,QDF_MODULE_ID module,QDF_TRACE_LEVEL level,char * str_format,...)4291 void QDF_PRINT_INFO(unsigned int idx, QDF_MODULE_ID module,
4292 QDF_TRACE_LEVEL level,
4293 char *str_format, ...)
4294 {
4295 va_list args;
4296
4297 /* Generic wrapper API will compile qdf_vprint in order to
4298 * log the message. Once QDF converged debug framework is in
4299 * place, this will be changed to adapt to the framework, compiling
4300 * call to converged tracing API
4301 */
4302 va_start(args, str_format);
4303 qdf_vprint(str_format, args);
4304 va_end(args);
4305 }
4306 qdf_export_symbol(QDF_PRINT_INFO);
4307
4308 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
qdf_logging_init(void)4309 void qdf_logging_init(void)
4310 {
4311 wlan_logging_sock_init_svc();
4312 nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY);
4313 wlan_logging_notifier_init(qdf_log_dump_at_kernel_enable);
4314 wlan_logging_set_flush_timer(qdf_log_flush_timer_period);
4315 }
4316
qdf_logging_exit(void)4317 void qdf_logging_exit(void)
4318 {
4319 wlan_logging_notifier_deinit(qdf_log_dump_at_kernel_enable);
4320 nl_srv_exit();
4321 wlan_logging_sock_deinit_svc();
4322 }
4323
qdf_logging_set_flush_timer(uint32_t milliseconds)4324 int qdf_logging_set_flush_timer(uint32_t milliseconds)
4325 {
4326 if (wlan_logging_set_flush_timer(milliseconds) == 0)
4327 return QDF_STATUS_SUCCESS;
4328 else
4329 return QDF_STATUS_E_FAILURE;
4330 }
4331
qdf_logging_flush_logs(void)4332 void qdf_logging_flush_logs(void)
4333 {
4334 wlan_flush_host_logs_for_fatal();
4335 }
4336
4337 #else
qdf_logging_init(void)4338 void qdf_logging_init(void)
4339 {
4340 nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY);
4341 }
4342
qdf_logging_exit(void)4343 void qdf_logging_exit(void)
4344 {
4345 nl_srv_exit();
4346 }
4347
qdf_logging_set_flush_timer(uint32_t milliseconds)4348 int qdf_logging_set_flush_timer(uint32_t milliseconds)
4349 {
4350 return QDF_STATUS_E_FAILURE;
4351 }
4352
qdf_logging_flush_logs(void)4353 void qdf_logging_flush_logs(void)
4354 {
4355 }
4356 #endif
4357
4358 qdf_export_symbol(qdf_logging_set_flush_timer);
4359 qdf_export_symbol(qdf_logging_flush_logs);
4360
4361 #ifdef CONFIG_KALLSYMS
qdf_sprint_symbol(char * buffer,void * addr)4362 inline int qdf_sprint_symbol(char *buffer, void *addr)
4363 {
4364 return sprint_symbol(buffer, (unsigned long)addr);
4365 }
4366 #else
qdf_sprint_symbol(char * buffer,void * addr)4367 int qdf_sprint_symbol(char *buffer, void *addr)
4368 {
4369 if (!buffer)
4370 return 0;
4371
4372 buffer[0] = '\0';
4373 return 1;
4374 }
4375 #endif
4376 qdf_export_symbol(qdf_sprint_symbol);
4377
qdf_set_pidx(int pidx)4378 void qdf_set_pidx(int pidx)
4379 {
4380 qdf_pidx = pidx;
4381 }
4382 qdf_export_symbol(qdf_set_pidx);
4383
qdf_get_pidx(void)4384 int qdf_get_pidx(void)
4385 {
4386 return qdf_pidx;
4387 }
4388 qdf_export_symbol(qdf_get_pidx);
4389
4390 #ifdef PANIC_ON_BUG
4391 #ifdef CONFIG_SLUB_DEBUG
__qdf_bug(void)4392 void __qdf_bug(void)
4393 {
4394 BUG();
4395 }
4396 qdf_export_symbol(__qdf_bug);
4397 #endif /* CONFIG_SLUB_DEBUG */
4398 #endif /* PANIC_ON_BUG */
4399
4400 #ifdef WLAN_QCOM_VA_MINIDUMP
4401 static bool qdf_va_md_initialized;
4402 static qdf_list_t qdf_va_md_list;
4403 static qdf_spinlock_t qdf_va_md_list_lock;
4404 #define QDF_MINIDUMP_LIST_SIZE 128
4405
4406 struct qdf_va_md_entry {
4407 qdf_list_node_t node;
4408 struct va_md_entry data;
4409 };
4410
qdf_va_md_notif_handler(struct notifier_block * this,unsigned long event,void * ptr)4411 static int qdf_va_md_notif_handler(struct notifier_block *this,
4412 unsigned long event, void *ptr)
4413 {
4414 struct qdf_va_md_entry *entry;
4415 struct qdf_va_md_entry *next;
4416
4417 qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4418 qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) {
4419 qcom_va_md_add_region(&entry->data);
4420 }
4421
4422 qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4423 return NOTIFY_OK;
4424 }
4425
4426 static struct notifier_block qdf_va_md_notif_blk = {
4427 .notifier_call = qdf_va_md_notif_handler,
4428 .priority = INT_MAX,
4429 };
4430
__qdf_minidump_init(void)4431 void __qdf_minidump_init(void)
4432 {
4433 int ret;
4434
4435 if (qdf_va_md_initialized)
4436 return;
4437
4438 qdf_spinlock_create(&qdf_va_md_list_lock);
4439 qdf_list_create(&qdf_va_md_list, QDF_MINIDUMP_LIST_SIZE);
4440 ret = qcom_va_md_register(qdf_trace_wlan_modname(),
4441 &qdf_va_md_notif_blk);
4442 qdf_va_md_initialized = !ret;
4443 }
4444
4445 qdf_export_symbol(__qdf_minidump_init);
4446
__qdf_minidump_deinit(void)4447 void __qdf_minidump_deinit(void)
4448 {
4449 struct qdf_va_md_entry *entry;
4450 struct qdf_va_md_entry *next;
4451
4452 if (!qdf_va_md_initialized)
4453 return;
4454
4455 qdf_va_md_initialized = false;
4456 qcom_va_md_unregister(qdf_trace_wlan_modname(),
4457 &qdf_va_md_notif_blk);
4458 qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4459 qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) {
4460 qdf_list_remove_node(&qdf_va_md_list, &entry->node);
4461 qdf_mem_free(entry);
4462 }
4463
4464 qdf_list_destroy(&qdf_va_md_list);
4465 qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4466 qdf_spinlock_destroy(&qdf_va_md_list_lock);
4467 }
4468
4469 qdf_export_symbol(__qdf_minidump_deinit);
4470
__qdf_minidump_log(void * start_addr,size_t size,const char * name)4471 void __qdf_minidump_log(void *start_addr, size_t size, const char *name)
4472 {
4473 struct qdf_va_md_entry *entry;
4474 QDF_STATUS status;
4475
4476 if (!qdf_va_md_initialized)
4477 return;
4478
4479 entry = qdf_mem_malloc(sizeof(*entry));
4480 if (!entry) {
4481 qdf_err("malloc failed for %s: %pK, %zu",
4482 name, start_addr, size);
4483 return;
4484 }
4485
4486 qdf_str_lcopy(entry->data.owner, name, sizeof(entry->data.owner));
4487 entry->data.vaddr = (unsigned long)start_addr;
4488 entry->data.size = size;
4489
4490 qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4491 status = qdf_list_insert_front(&qdf_va_md_list, &entry->node);
4492 qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4493 if (QDF_IS_STATUS_ERROR(status)) {
4494 qdf_err("Failed to insert qdf va md entry, status %d", status);
4495 qdf_mem_free(entry);
4496 }
4497 }
4498
4499 qdf_export_symbol(__qdf_minidump_log);
4500
__qdf_minidump_remove(void * addr,size_t size,const char * name)4501 void __qdf_minidump_remove(void *addr, size_t size, const char *name)
4502 {
4503 struct qdf_va_md_entry *entry;
4504 struct qdf_va_md_entry *next;
4505
4506 if (!qdf_va_md_initialized)
4507 return;
4508
4509 qdf_spin_lock_irqsave(&qdf_va_md_list_lock);
4510 qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) {
4511 if (entry->data.vaddr == (unsigned long)addr &&
4512 entry->data.size == size &&
4513 !qdf_str_cmp(entry->data.owner, name)) {
4514 qdf_list_remove_node(&qdf_va_md_list, &entry->node);
4515 qdf_mem_free(entry);
4516 break;
4517 }
4518 }
4519
4520 qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock);
4521 }
4522
4523 qdf_export_symbol(__qdf_minidump_remove);
4524 #endif
4525