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