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 struct qdf_dp_trace_proto_cmn cmn_info; 1509 1510 if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMPv6) && 1511 ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ICMPv6 == 1512 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) || 1513 (dir == QDF_RX && qdf_nbuf_is_icmpv6_pkt(skb) == true))) { 1514 1515 subtype = qdf_nbuf_get_icmpv6_subtype(skb); 1516 1517 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false; 1518 if (dir == QDF_TX) 1519 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1; 1520 else if (dir == QDF_RX) 1521 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1; 1522 1523 cmn_info.vdev_id = vdev_id; 1524 cmn_info.type = QDF_PROTO_TYPE_ICMPv6; 1525 cmn_info.subtype = subtype; 1526 cmn_info.proto_priv_data = 0; 1527 cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb); 1528 DPTRACE(qdf_dp_trace_proto_pkt( 1529 QDF_DP_TRACE_ICMPv6_PACKET_RECORD, 1530 (skb->data + QDF_NBUF_SRC_MAC_OFFSET), 1531 (skb->data + QDF_NBUF_DEST_MAC_OFFSET), 1532 dir, pdev_id, false, &cmn_info)); 1533 1534 switch (subtype) { 1535 case QDF_PROTO_ICMPV6_REQ: 1536 g_qdf_dp_trace_data.icmpv6_req++; 1537 break; 1538 case QDF_PROTO_ICMPV6_RES: 1539 g_qdf_dp_trace_data.icmpv6_resp++; 1540 break; 1541 case QDF_PROTO_ICMPV6_RS: 1542 g_qdf_dp_trace_data.icmpv6_rs++; 1543 break; 1544 case QDF_PROTO_ICMPV6_RA: 1545 g_qdf_dp_trace_data.icmpv6_ra++; 1546 break; 1547 case QDF_PROTO_ICMPV6_NS: 1548 g_qdf_dp_trace_data.icmpv6_ns++; 1549 break; 1550 case QDF_PROTO_ICMPV6_NA: 1551 g_qdf_dp_trace_data.icmpv6_na++; 1552 break; 1553 default: 1554 break; 1555 } 1556 return true; 1557 } 1558 1559 return false; 1560 } 1561 1562 /** 1563 * qdf_log_icmp_pkt() - log ICMP packet 1564 * @vdev_id: ID of the vdev 1565 * @skb: skb pointer 1566 * @dir: direction 1567 * @pdev_id: ID of the pdev 1568 * 1569 * Return: true/false 1570 */ 1571 static bool qdf_log_icmp_pkt(uint8_t vdev_id, struct sk_buff *skb, 1572 enum qdf_proto_dir dir, uint8_t pdev_id) 1573 { 1574 uint8_t *data = NULL; 1575 uint16_t seq_num = 0; 1576 uint16_t icmp_id = 0; 1577 struct qdf_dp_trace_proto_cmn cmn_info; 1578 1579 if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMP) && 1580 (qdf_nbuf_is_icmp_pkt(skb) == true)) { 1581 1582 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false; 1583 cmn_info.subtype = qdf_nbuf_get_icmp_subtype(skb); 1584 1585 data = qdf_nbuf_data(skb); 1586 icmp_id = qdf_cpu_to_be16(*(uint16_t *)(data + ICMP_ID_OFFSET)); 1587 seq_num = qdf_cpu_to_be16(*(uint16_t *)(data + ICMP_SEQ_NUM_OFFSET)); 1588 1589 cmn_info.proto_priv_data = ((uint32_t)icmp_id) << 16; 1590 cmn_info.proto_priv_data |= (uint32_t)seq_num; 1591 cmn_info.type = QDF_PROTO_TYPE_ICMP; 1592 cmn_info.vdev_id = vdev_id; 1593 cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb); 1594 1595 if (QDF_TX == dir) 1596 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1; 1597 else if (QDF_RX == dir) 1598 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1; 1599 1600 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ICMP_PACKET_RECORD, 1601 skb->data + 1602 QDF_NBUF_SRC_MAC_OFFSET, 1603 skb->data + 1604 QDF_NBUF_DEST_MAC_OFFSET, 1605 dir, pdev_id, 1606 false, &cmn_info)); 1607 1608 if (cmn_info.subtype == QDF_PROTO_ICMP_REQ) 1609 g_qdf_dp_trace_data.icmp_req++; 1610 else 1611 g_qdf_dp_trace_data.icmp_resp++; 1612 1613 return true; 1614 } 1615 return false; 1616 } 1617 1618 #ifdef CONNECTIVITY_DIAG_EVENT 1619 enum diag_tx_status wlan_get_diag_tx_status(enum qdf_dp_tx_rx_status tx_status) 1620 { 1621 switch (tx_status) { 1622 case DIAG_TX_RX_STATUS_FW_DISCARD: 1623 case DIAG_TX_RX_STATUS_INVALID: 1624 case DIAG_TX_RX_STATUS_DROP: 1625 case DIAG_TX_RX_STATUS_DOWNLOAD_SUCC: 1626 case DIAG_TX_RX_STATUS_DEFAULT: 1627 default: 1628 return DIAG_TX_STATUS_FAIL; 1629 case DIAG_TX_RX_STATUS_NO_ACK: 1630 return DIAG_TX_STATUS_NO_ACK; 1631 case DIAG_TX_RX_STATUS_OK: 1632 return DIAG_TX_STATUS_ACK; 1633 } 1634 1635 return DIAG_TX_STATUS_FAIL; 1636 } 1637 1638 /** 1639 * qdf_subtype_to_wlan_main_tag() - Convert qdf subtype to wlan main tag 1640 * @subtype: EAPoL key subtype 1641 * 1642 * Return: Wlan main tag subtype 1643 */ 1644 static int qdf_subtype_to_wlan_main_tag(enum qdf_proto_subtype subtype) 1645 { 1646 switch (subtype) { 1647 case QDF_PROTO_DHCP_DISCOVER: 1648 return WLAN_CONN_DIAG_DHCP_DISC_EVENT; 1649 case QDF_PROTO_DHCP_REQUEST: 1650 return WLAN_CONN_DIAG_DHCP_REQUEST_EVENT; 1651 case QDF_PROTO_DHCP_OFFER: 1652 return WLAN_CONN_DIAG_DHCP_OFFER_EVENT; 1653 case QDF_PROTO_DHCP_ACK: 1654 return WLAN_CONN_DIAG_DHCP_ACK_EVENT; 1655 case QDF_PROTO_DHCP_NACK: 1656 return WLAN_CONN_DIAG_DHCP_NACK_EVENT; 1657 case QDF_PROTO_EAPOL_M1: 1658 return WLAN_CONN_DIAG_EAPOL_M1_EVENT; 1659 case QDF_PROTO_EAPOL_M2: 1660 return WLAN_CONN_DIAG_EAPOL_M2_EVENT; 1661 case QDF_PROTO_EAPOL_M3: 1662 return WLAN_CONN_DIAG_EAPOL_M3_EVENT; 1663 case QDF_PROTO_EAPOL_M4: 1664 return WLAN_CONN_DIAG_EAPOL_M4_EVENT; 1665 case QDF_PROTO_EAP_REQUEST: 1666 return WLAN_CONN_DIAG_EAP_REQ_EVENT; 1667 case QDF_PROTO_EAP_RESPONSE: 1668 return WLAN_CONN_DIAG_EAP_RESP_EVENT; 1669 case QDF_PROTO_EAP_SUCCESS: 1670 return WLAN_CONN_DIAG_EAP_SUCC_EVENT; 1671 case QDF_PROTO_EAP_FAILURE: 1672 return WLAN_CONN_DIAG_EAP_FAIL_EVENT; 1673 case QDF_PROTO_EAPOL_START: 1674 return WLAN_CONN_DIAG_EAP_START_EVENT; 1675 default: 1676 return WLAN_CONN_DIAG_MAX; 1677 } 1678 } 1679 1680 /** 1681 * qdf_get_wlan_eap_code() - Get EAP code 1682 * @data: skb data pointer 1683 * 1684 * Return: EAP code value 1685 */ 1686 static int qdf_get_wlan_eap_code(uint8_t *data) 1687 { 1688 uint8_t code = *(data + EAP_CODE_OFFSET); 1689 1690 switch (code) { 1691 case QDF_EAP_REQUEST: 1692 return WLAN_CONN_DIAG_EAP_REQ_EVENT; 1693 case QDF_EAP_RESPONSE: 1694 return WLAN_CONN_DIAG_EAP_RESP_EVENT; 1695 case QDF_EAP_SUCCESS: 1696 return WLAN_CONN_DIAG_EAP_SUCC_EVENT; 1697 case QDF_EAP_FAILURE: 1698 return WLAN_CONN_DIAG_EAP_FAIL_EVENT; 1699 default: 1700 return WLAN_CONN_DIAG_MAX; 1701 } 1702 } 1703 1704 /** 1705 * qdf_eapol_get_key_type() - Get EAPOL key type 1706 * @data: skb data pointer 1707 * @subtype: EAPoL key subtype 1708 * 1709 * Return: EAPOL key type 1710 */ 1711 static 1712 uint8_t qdf_eapol_get_key_type(uint8_t *data, enum qdf_proto_subtype subtype) 1713 { 1714 uint16_t key_info = *(uint16_t *)(data + EAPOL_KEY_INFO_OFFSET); 1715 1716 /* If key type is PTK, key type will be set in EAPOL Key info */ 1717 if (key_info & EAPOL_KEY_TYPE_MASK) 1718 return qdf_subtype_to_wlan_main_tag(subtype); 1719 else if (key_info & EAPOL_KEY_ENCRYPTED_MASK) 1720 return WLAN_CONN_DIAG_GTK_M1_EVENT; 1721 else 1722 return WLAN_CONN_DIAG_GTK_M2_EVENT; 1723 } 1724 1725 /** 1726 * qdf_skip_wlan_connectivity_log() - Check if connectivity log need to skip 1727 * @type: Protocol type 1728 * @subtype: Protocol subtype 1729 * @dir: Rx or Tx 1730 * @op_mode: Vdev Operation mode 1731 * 1732 * Return: true or false 1733 */ 1734 static inline 1735 bool qdf_skip_wlan_connectivity_log(enum qdf_proto_type type, 1736 enum qdf_proto_subtype subtype, 1737 enum qdf_proto_dir dir, 1738 enum QDF_OPMODE op_mode) 1739 { 1740 if (op_mode != QDF_STA_MODE) 1741 return true; 1742 1743 if (dir == QDF_RX && type == QDF_PROTO_TYPE_DHCP && 1744 (subtype == QDF_PROTO_DHCP_DISCOVER || 1745 subtype == QDF_PROTO_DHCP_REQUEST)) 1746 return true; 1747 return false; 1748 } 1749 1750 /** 1751 * qdf_fill_wlan_connectivity_log() - Fill and queue protocol packet to logging 1752 * the logging queue 1753 * @type: Protocol type 1754 * @subtype: Protocol subtype 1755 * @dir: Rx or Tx 1756 * @qdf_tx_status: Tx completion status 1757 * @op_mode: Vdev Operation mode 1758 * @vdev_id: DP vdev ID 1759 * @data: skb data pointer 1760 * @band: band 1761 * 1762 * Return: None 1763 */ 1764 static 1765 void qdf_fill_wlan_connectivity_log(enum qdf_proto_type type, 1766 enum qdf_proto_subtype subtype, 1767 enum qdf_proto_dir dir, 1768 enum qdf_dp_tx_rx_status qdf_tx_status, 1769 enum QDF_OPMODE op_mode, 1770 uint8_t vdev_id, uint8_t *data, 1771 uint8_t band) 1772 { 1773 uint8_t pkt_type; 1774 1775 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_packet_info); 1776 1777 if (qdf_skip_wlan_connectivity_log(type, subtype, dir, op_mode)) 1778 return; 1779 1780 qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event)); 1781 1782 wlan_diag_event.diag_cmn.timestamp_us = 1783 qdf_get_time_of_the_day_ms() * 1000; 1784 wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get()); 1785 wlan_diag_event.diag_cmn.vdev_id = vdev_id; 1786 1787 wlan_diag_event.version = DIAG_MGMT_VERSION_V2; 1788 1789 if (type == QDF_PROTO_TYPE_DHCP) { 1790 wlan_diag_event.subtype = 1791 qdf_subtype_to_wlan_main_tag(subtype); 1792 } else if (type == QDF_PROTO_TYPE_EAPOL) { 1793 pkt_type = *(data + EAPOL_PACKET_TYPE_OFFSET); 1794 if (pkt_type == EAPOL_PACKET_TYPE_EAP) { 1795 wlan_diag_event.subtype = 1796 qdf_get_wlan_eap_code(data); 1797 wlan_diag_event.eap_type = 1798 *(data + EAP_TYPE_OFFSET); 1799 wlan_diag_event.eap_len = 1800 qdf_ntohs(*(uint16_t *)(data + EAP_LENGTH_OFFSET)); 1801 } else if (pkt_type == EAPOL_PACKET_TYPE_KEY) { 1802 wlan_diag_event.subtype = 1803 qdf_eapol_get_key_type(data, subtype); 1804 } else if (pkt_type == EAPOL_PACKET_TYPE_START) { 1805 wlan_diag_event.subtype = 1806 WLAN_CONN_DIAG_EAP_START_EVENT; 1807 wlan_diag_event.eap_len = 1808 qdf_ntohs(*(uint16_t *)(data + EAPOL_PKT_LEN_OFFSET)); 1809 } else { 1810 return; 1811 } 1812 } else { 1813 return; 1814 } 1815 1816 wlan_diag_event.supported_links = band; 1817 1818 /*Tx completion status needs to be logged*/ 1819 if (dir == QDF_TX) { 1820 wlan_diag_event.is_tx = 1; 1821 wlan_diag_event.tx_status = 1822 wlan_get_diag_tx_status(qdf_tx_status); 1823 } 1824 1825 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_CONN_DP); 1826 } 1827 1828 #else 1829 static inline 1830 void qdf_fill_wlan_connectivity_log(enum qdf_proto_type type, 1831 enum qdf_proto_subtype subtype, 1832 enum qdf_proto_dir dir, 1833 enum qdf_dp_tx_rx_status qdf_tx_status, 1834 enum QDF_OPMODE op_mode, 1835 uint8_t vdev_id, uint8_t *data, 1836 uint8_t band) 1837 { 1838 } 1839 #endif 1840 1841 /** 1842 * qdf_log_eapol_pkt() - log EAPOL packet 1843 * @vdev_id: ID of the vdev 1844 * @skb: skb pointer 1845 * @dir: direction 1846 * @pdev_id: ID of the pdev 1847 * @op_mode: Vdev Operation mode 1848 * 1849 * Return: true/false 1850 */ 1851 static bool qdf_log_eapol_pkt(uint8_t vdev_id, struct sk_buff *skb, 1852 enum qdf_proto_dir dir, uint8_t pdev_id, 1853 enum QDF_OPMODE op_mode) 1854 { 1855 enum qdf_proto_subtype subtype; 1856 uint32_t dp_eap_trace; 1857 uint32_t dp_eap_event; 1858 struct qdf_dp_trace_proto_cmn cmn_info; 1859 1860 dp_eap_trace = qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_EAPOL; 1861 dp_eap_event = qdf_dp_get_proto_event_bitmap() & 1862 QDF_NBUF_PKT_TRAC_TYPE_EAPOL; 1863 1864 if (!dp_eap_trace && !dp_eap_event) 1865 return false; 1866 1867 if (!((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_EAPOL == 1868 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) || 1869 (dir == QDF_RX && qdf_nbuf_is_ipv4_eapol_pkt(skb) == true))) 1870 return false; 1871 1872 subtype = qdf_nbuf_get_eapol_subtype(skb); 1873 1874 if (dp_eap_event && dir == QDF_RX) { 1875 qdf_dp_log_proto_pkt_info(skb->data + QDF_NBUF_SRC_MAC_OFFSET, 1876 skb->data + QDF_NBUF_DEST_MAC_OFFSET, 1877 QDF_PROTO_TYPE_EAPOL, subtype, dir, 1878 QDF_TRACE_DEFAULT_MSDU_ID, 1879 QDF_TX_RX_STATUS_INVALID); 1880 qdf_fill_wlan_connectivity_log(QDF_PROTO_TYPE_EAPOL, subtype, 1881 QDF_RX, 0, op_mode, 1882 vdev_id, skb->data, 1883 qdf_nbuf_rx_get_band(skb)); 1884 } 1885 1886 if (dp_eap_trace) { 1887 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true; 1888 if (QDF_TX == dir) 1889 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1; 1890 else if (QDF_RX == dir) 1891 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1; 1892 1893 cmn_info.vdev_id = vdev_id; 1894 cmn_info.type = QDF_PROTO_TYPE_EAPOL; 1895 cmn_info.subtype = subtype; 1896 cmn_info.proto_priv_data = 0; 1897 cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb); 1898 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_EAPOL_PACKET_RECORD, 1899 skb->data + 1900 QDF_NBUF_SRC_MAC_OFFSET, 1901 skb->data + 1902 QDF_NBUF_DEST_MAC_OFFSET, 1903 dir, pdev_id, true, &cmn_info)); 1904 1905 switch (subtype) { 1906 case QDF_PROTO_EAPOL_M1: 1907 g_qdf_dp_trace_data.eapol_m1++; 1908 break; 1909 case QDF_PROTO_EAPOL_M2: 1910 g_qdf_dp_trace_data.eapol_m2++; 1911 break; 1912 case QDF_PROTO_EAPOL_M3: 1913 g_qdf_dp_trace_data.eapol_m3++; 1914 break; 1915 case QDF_PROTO_EAPOL_M4: 1916 g_qdf_dp_trace_data.eapol_m4++; 1917 break; 1918 default: 1919 g_qdf_dp_trace_data.eapol_others++; 1920 break; 1921 } 1922 } 1923 1924 return true; 1925 } 1926 1927 /** 1928 * qdf_log_dhcp_pkt() - log DHCP packet 1929 * @vdev_id: ID of the vdev 1930 * @skb: skb pointer 1931 * @dir: direction 1932 * @pdev_id: ID of the pdev 1933 * @op_mode: Vdev Operation mode 1934 * 1935 * Return: true/false 1936 */ 1937 static bool qdf_log_dhcp_pkt(uint8_t vdev_id, struct sk_buff *skb, 1938 enum qdf_proto_dir dir, uint8_t pdev_id, 1939 enum QDF_OPMODE op_mode) 1940 { 1941 enum qdf_proto_subtype subtype = QDF_PROTO_INVALID; 1942 uint32_t dp_dhcp_trace; 1943 uint32_t dp_dhcp_event; 1944 struct qdf_dp_trace_proto_cmn cmn_info; 1945 1946 dp_dhcp_trace = qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_DHCP; 1947 dp_dhcp_event = qdf_dp_get_proto_event_bitmap() & 1948 QDF_NBUF_PKT_TRAC_TYPE_DHCP; 1949 1950 if (!dp_dhcp_trace && !dp_dhcp_event) 1951 return false; 1952 1953 if (!((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_DHCP == 1954 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) || 1955 (dir == QDF_RX && qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true))) 1956 return false; 1957 1958 subtype = qdf_nbuf_get_dhcp_subtype(skb); 1959 1960 if (dp_dhcp_event && dir == QDF_RX) { 1961 qdf_dp_log_proto_pkt_info(skb->data + QDF_NBUF_SRC_MAC_OFFSET, 1962 skb->data + QDF_NBUF_DEST_MAC_OFFSET, 1963 QDF_PROTO_TYPE_DHCP, subtype, dir, 1964 QDF_TRACE_DEFAULT_MSDU_ID, 1965 QDF_TX_RX_STATUS_INVALID); 1966 qdf_fill_wlan_connectivity_log(QDF_PROTO_TYPE_DHCP, subtype, 1967 QDF_RX, 0, op_mode, vdev_id, 0, 1968 qdf_nbuf_rx_get_band(skb)); 1969 } 1970 1971 if (dp_dhcp_trace) { 1972 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true; 1973 if (QDF_TX == dir) 1974 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1; 1975 else if (QDF_RX == dir) 1976 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1; 1977 1978 cmn_info.vdev_id = vdev_id; 1979 cmn_info.type = QDF_PROTO_TYPE_DHCP; 1980 cmn_info.subtype = subtype; 1981 cmn_info.proto_priv_data = 0; 1982 cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb); 1983 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_DHCP_PACKET_RECORD, 1984 skb->data + 1985 QDF_NBUF_SRC_MAC_OFFSET, 1986 skb->data + 1987 QDF_NBUF_DEST_MAC_OFFSET, 1988 dir, pdev_id, true, &cmn_info)); 1989 1990 switch (subtype) { 1991 case QDF_PROTO_DHCP_DISCOVER: 1992 g_qdf_dp_trace_data.dhcp_disc++; 1993 break; 1994 case QDF_PROTO_DHCP_OFFER: 1995 g_qdf_dp_trace_data.dhcp_off++; 1996 break; 1997 case QDF_PROTO_DHCP_REQUEST: 1998 g_qdf_dp_trace_data.dhcp_req++; 1999 break; 2000 case QDF_PROTO_DHCP_ACK: 2001 g_qdf_dp_trace_data.dhcp_ack++; 2002 break; 2003 case QDF_PROTO_DHCP_NACK: 2004 g_qdf_dp_trace_data.dhcp_nack++; 2005 break; 2006 default: 2007 g_qdf_dp_trace_data.eapol_others++; 2008 break; 2009 } 2010 } 2011 2012 return true; 2013 } 2014 2015 /** 2016 * qdf_log_arp_pkt() - log ARP packet 2017 * @vdev_id: ID of the vdev 2018 * @skb: skb pointer 2019 * @dir: direction 2020 * @pdev_id: ID of the pdev 2021 * 2022 * Return: true/false 2023 */ 2024 static bool qdf_log_arp_pkt(uint8_t vdev_id, struct sk_buff *skb, 2025 enum qdf_proto_dir dir, uint8_t pdev_id) 2026 { 2027 enum qdf_proto_subtype proto_subtype; 2028 struct qdf_dp_trace_proto_cmn cmn_info; 2029 2030 if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ARP) && 2031 ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ARP == 2032 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) || 2033 (dir == QDF_RX && qdf_nbuf_is_ipv4_arp_pkt(skb) == true))) { 2034 2035 proto_subtype = qdf_nbuf_get_arp_subtype(skb); 2036 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true; 2037 if (QDF_TX == dir) 2038 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1; 2039 else if (QDF_RX == dir) 2040 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1; 2041 2042 cmn_info.vdev_id = vdev_id; 2043 cmn_info.type = QDF_PROTO_TYPE_ARP; 2044 cmn_info.subtype = proto_subtype; 2045 cmn_info.proto_priv_data = 0; 2046 cmn_info.mpdu_seq = qdf_nbuf_get_mpdu_seq_num(skb); 2047 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ARP_PACKET_RECORD, 2048 skb->data + 2049 QDF_NBUF_SRC_MAC_OFFSET, 2050 skb->data + 2051 QDF_NBUF_DEST_MAC_OFFSET, 2052 dir, pdev_id, true, 2053 &cmn_info)); 2054 2055 if (QDF_PROTO_ARP_REQ == proto_subtype) 2056 g_qdf_dp_trace_data.arp_req++; 2057 else 2058 g_qdf_dp_trace_data.arp_resp++; 2059 2060 return true; 2061 } 2062 return false; 2063 } 2064 2065 2066 bool qdf_dp_trace_log_pkt(uint8_t vdev_id, struct sk_buff *skb, 2067 enum qdf_proto_dir dir, uint8_t pdev_id, 2068 enum QDF_OPMODE op_mode) 2069 { 2070 if (!qdf_dp_get_proto_bitmap() && !qdf_dp_get_proto_event_bitmap()) 2071 return false; 2072 if (qdf_log_arp_pkt(vdev_id, skb, dir, pdev_id)) 2073 return true; 2074 if (qdf_log_dhcp_pkt(vdev_id, skb, dir, pdev_id, op_mode)) 2075 return true; 2076 if (qdf_log_eapol_pkt(vdev_id, skb, dir, pdev_id, op_mode)) 2077 return true; 2078 if (qdf_log_icmp_pkt(vdev_id, skb, dir, pdev_id)) 2079 return true; 2080 if (qdf_log_icmpv6_pkt(vdev_id, skb, dir, pdev_id)) 2081 return true; 2082 return false; 2083 } 2084 qdf_export_symbol(qdf_dp_trace_log_pkt); 2085 2086 void qdf_dp_display_mgmt_pkt(struct qdf_dp_trace_record_s *record, 2087 uint16_t index, uint8_t pdev_id, uint8_t info) 2088 { 2089 int loc; 2090 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2091 struct qdf_dp_trace_mgmt_buf *buf = 2092 (struct qdf_dp_trace_mgmt_buf *)record->data; 2093 2094 qdf_mem_zero(prepend_str, sizeof(prepend_str)); 2095 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2096 index, info, record); 2097 2098 DPTRACE_PRINT("%s [%d] [%s %s]", 2099 prepend_str, 2100 buf->vdev_id, 2101 qdf_dp_type_to_str(buf->type), 2102 qdf_dp_subtype_to_str(buf->subtype)); 2103 } 2104 qdf_export_symbol(qdf_dp_display_mgmt_pkt); 2105 2106 2107 void qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id, 2108 uint8_t pdev_id, enum qdf_proto_type type, 2109 enum qdf_proto_subtype subtype) 2110 { 2111 struct qdf_dp_trace_mgmt_buf buf; 2112 int buf_size = sizeof(struct qdf_dp_trace_mgmt_buf); 2113 2114 if (qdf_dp_enable_check(NULL, code, QDF_NA) == false) 2115 return; 2116 2117 if (buf_size > QDF_DP_TRACE_RECORD_SIZE) 2118 QDF_BUG(0); 2119 2120 buf.type = type; 2121 buf.subtype = subtype; 2122 buf.vdev_id = vdev_id; 2123 qdf_dp_add_record(code, pdev_id, (uint8_t *)&buf, buf_size, 2124 NULL, 0, true); 2125 } 2126 qdf_export_symbol(qdf_dp_trace_mgmt_pkt); 2127 2128 static void 2129 qdf_dpt_display_credit_record_debugfs(qdf_debugfs_file_t file, 2130 struct qdf_dp_trace_record_s *record, 2131 uint32_t index) 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, 0, record); 2140 if (buf->operation == QDF_OP_NA) 2141 qdf_debugfs_printf(file, "%s [%s] [T: %d G0: %d G1: %d]\n", 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 qdf_debugfs_printf(file, 2148 "%s [%s] [T: %d G0: %d G1: %d] [%s %d]\n", 2149 prepend_str, 2150 qdf_dp_credit_source_to_str(buf->source), 2151 buf->total_credits, buf->g0_credit, 2152 buf->g1_credit, 2153 qdf_dp_operation_to_str(buf->operation), 2154 buf->delta); 2155 } 2156 2157 void qdf_dp_display_credit_record(struct qdf_dp_trace_record_s *record, 2158 uint16_t index, uint8_t pdev_id, uint8_t info) 2159 { 2160 int loc; 2161 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2162 struct qdf_dp_trace_credit_record *buf = 2163 (struct qdf_dp_trace_credit_record *)record->data; 2164 2165 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2166 index, info, record); 2167 if (buf->operation == QDF_OP_NA) 2168 DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d]", 2169 prepend_str, 2170 qdf_dp_credit_source_to_str(buf->source), 2171 buf->total_credits, buf->g0_credit, 2172 buf->g1_credit); 2173 else 2174 DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d] [%s %d]", 2175 prepend_str, 2176 qdf_dp_credit_source_to_str(buf->source), 2177 buf->total_credits, buf->g0_credit, 2178 buf->g1_credit, 2179 qdf_dp_operation_to_str(buf->operation), 2180 buf->delta); 2181 } 2182 2183 void qdf_dp_trace_credit_record(enum QDF_CREDIT_UPDATE_SOURCE source, 2184 enum QDF_CREDIT_OPERATION operation, 2185 int delta, int total_credits, 2186 int g0_credit, int g1_credit) 2187 { 2188 struct qdf_dp_trace_credit_record buf; 2189 int buf_size = sizeof(struct qdf_dp_trace_credit_record); 2190 enum QDF_DP_TRACE_ID code = QDF_DP_TRACE_TX_CREDIT_RECORD; 2191 2192 if (qdf_dp_enable_check(NULL, code, QDF_NA) == false) 2193 return; 2194 2195 if (!(qdf_dp_get_proto_bitmap() & QDF_HL_CREDIT_TRACKING)) 2196 return; 2197 2198 if (buf_size > QDF_DP_TRACE_RECORD_SIZE) 2199 QDF_BUG(0); 2200 2201 buf.source = source; 2202 buf.operation = operation; 2203 buf.delta = delta; 2204 buf.total_credits = total_credits; 2205 buf.g0_credit = g0_credit; 2206 buf.g1_credit = g1_credit; 2207 2208 qdf_dp_add_record(code, QDF_TRACE_DEFAULT_PDEV_ID, (uint8_t *)&buf, 2209 buf_size, NULL, 0, false); 2210 } 2211 qdf_export_symbol(qdf_dp_trace_credit_record); 2212 2213 void qdf_dp_display_event_record(struct qdf_dp_trace_record_s *record, 2214 uint16_t index, uint8_t pdev_id, uint8_t info) 2215 { 2216 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2217 struct qdf_dp_trace_event_buf *buf = 2218 (struct qdf_dp_trace_event_buf *)record->data; 2219 2220 qdf_mem_zero(prepend_str, sizeof(prepend_str)); 2221 qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2222 index, info, record); 2223 2224 DPTRACE_PRINT("%s [%d] [%s %s]", 2225 prepend_str, 2226 buf->vdev_id, 2227 qdf_dp_type_to_str(buf->type), 2228 qdf_dp_subtype_to_str(buf->subtype)); 2229 } 2230 qdf_export_symbol(qdf_dp_display_event_record); 2231 2232 void qdf_dp_trace_record_event(enum QDF_DP_TRACE_ID code, uint8_t vdev_id, 2233 uint8_t pdev_id, enum qdf_proto_type type, 2234 enum qdf_proto_subtype subtype) 2235 { 2236 struct qdf_dp_trace_event_buf buf; 2237 int buf_size = sizeof(struct qdf_dp_trace_event_buf); 2238 2239 if (qdf_dp_enable_check(NULL, code, QDF_NA) == false) 2240 return; 2241 2242 if (buf_size > QDF_DP_TRACE_RECORD_SIZE) 2243 QDF_BUG(0); 2244 2245 buf.type = type; 2246 buf.subtype = subtype; 2247 buf.vdev_id = vdev_id; 2248 qdf_dp_add_record(code, pdev_id, 2249 (uint8_t *)&buf, buf_size, NULL, 0, true); 2250 } 2251 qdf_export_symbol(qdf_dp_trace_record_event); 2252 2253 2254 void qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s *record, 2255 uint16_t index, uint8_t pdev_id, uint8_t info) 2256 { 2257 int loc; 2258 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2259 struct qdf_dp_trace_proto_buf *buf = 2260 (struct qdf_dp_trace_proto_buf *)record->data; 2261 2262 qdf_mem_zero(prepend_str, sizeof(prepend_str)); 2263 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2264 index, info, record); 2265 2266 if (QDF_RX == buf->dir) 2267 DPTRACE_PRINT("%s [%d] [%d] [%s] SA: " 2268 QDF_MAC_ADDR_FMT " %s DA:" 2269 QDF_MAC_ADDR_FMT " proto priv data = %08x", 2270 prepend_str, 2271 buf->cmn_info.vdev_id, 2272 buf->cmn_info.mpdu_seq, 2273 qdf_dp_subtype_to_str(buf->cmn_info.subtype), 2274 QDF_MAC_ADDR_REF(buf->sa.bytes), 2275 qdf_dp_dir_to_str(buf->dir), 2276 QDF_MAC_ADDR_REF(buf->da.bytes), 2277 buf->cmn_info.proto_priv_data); 2278 else 2279 DPTRACE_PRINT("%s [%d] [%s] SA: " 2280 QDF_MAC_ADDR_FMT " %s DA:" 2281 QDF_MAC_ADDR_FMT " proto priv data = %08x", 2282 prepend_str, 2283 buf->cmn_info.vdev_id, 2284 qdf_dp_subtype_to_str(buf->cmn_info.subtype), 2285 QDF_MAC_ADDR_REF(buf->sa.bytes), 2286 qdf_dp_dir_to_str(buf->dir), 2287 QDF_MAC_ADDR_REF(buf->da.bytes), 2288 buf->cmn_info.proto_priv_data); 2289 } 2290 qdf_export_symbol(qdf_dp_display_proto_pkt); 2291 2292 void qdf_dp_trace_proto_pkt(enum QDF_DP_TRACE_ID code, 2293 uint8_t *sa, uint8_t *da, 2294 enum qdf_proto_dir dir, 2295 uint8_t pdev_id, bool print, 2296 struct qdf_dp_trace_proto_cmn *cmn_info) 2297 { 2298 struct qdf_dp_trace_proto_buf buf; 2299 int buf_size = sizeof(struct qdf_dp_trace_proto_buf); 2300 2301 if (qdf_dp_enable_check(NULL, code, dir) == false) 2302 return; 2303 2304 if (buf_size > QDF_DP_TRACE_RECORD_SIZE) 2305 QDF_BUG(0); 2306 2307 memcpy(&buf.sa, sa, QDF_NET_ETH_LEN); 2308 memcpy(&buf.da, da, QDF_NET_ETH_LEN); 2309 memcpy(&buf.cmn_info, cmn_info, sizeof(*cmn_info)); 2310 buf.dir = dir; 2311 qdf_dp_add_record(code, pdev_id, 2312 (uint8_t *)&buf, buf_size, NULL, 0, print); 2313 } 2314 qdf_export_symbol(qdf_dp_trace_proto_pkt); 2315 2316 void qdf_dp_display_ptr_record(struct qdf_dp_trace_record_s *record, 2317 uint16_t index, uint8_t pdev_id, uint8_t info) 2318 { 2319 int loc; 2320 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2321 struct qdf_dp_trace_ptr_buf *buf = 2322 (struct qdf_dp_trace_ptr_buf *)record->data; 2323 bool is_free_pkt_ptr_record = false; 2324 2325 if ((record->code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) || 2326 (record->code == QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD)) 2327 is_free_pkt_ptr_record = true; 2328 2329 qdf_mem_zero(prepend_str, sizeof(prepend_str)); 2330 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2331 index, info, record); 2332 2333 if (loc < sizeof(prepend_str)) 2334 scnprintf(&prepend_str[loc], sizeof(prepend_str) - loc, 2335 "[msdu id %d %s %d]", 2336 buf->msdu_id, 2337 is_free_pkt_ptr_record ? "status" : "vdev_id", 2338 buf->status); 2339 2340 if (info & QDF_DP_TRACE_RECORD_INFO_LIVE) { 2341 /* In live mode donot dump the contents of the cookie */ 2342 DPTRACE_PRINT("%s", prepend_str); 2343 } else { 2344 dump_dp_hex_trace(prepend_str, (uint8_t *)&buf->cookie, 2345 sizeof(buf->cookie)); 2346 } 2347 } 2348 qdf_export_symbol(qdf_dp_display_ptr_record); 2349 2350 static 2351 enum qdf_proto_type qdf_dp_get_pkt_proto_type(qdf_nbuf_t nbuf) 2352 { 2353 uint8_t pkt_type; 2354 2355 if (!nbuf) 2356 return QDF_PROTO_TYPE_MAX; 2357 2358 if (qdf_nbuf_data_is_dns_query(nbuf) || 2359 qdf_nbuf_data_is_dns_response(nbuf)) 2360 return QDF_PROTO_TYPE_DNS; 2361 2362 pkt_type = QDF_NBUF_CB_GET_PACKET_TYPE(nbuf); 2363 2364 switch (pkt_type) { 2365 case QDF_NBUF_CB_PACKET_TYPE_EAPOL: 2366 return QDF_PROTO_TYPE_EAPOL; 2367 case QDF_NBUF_CB_PACKET_TYPE_ARP: 2368 return QDF_PROTO_TYPE_ARP; 2369 case QDF_NBUF_CB_PACKET_TYPE_DHCP: 2370 return QDF_PROTO_TYPE_DHCP; 2371 default: 2372 return QDF_PROTO_TYPE_MAX; 2373 } 2374 } 2375 2376 static 2377 enum qdf_proto_subtype qdf_dp_get_pkt_subtype(qdf_nbuf_t nbuf, 2378 enum qdf_proto_type pkt_type) 2379 { 2380 switch (pkt_type) { 2381 case QDF_PROTO_TYPE_EAPOL: 2382 return qdf_nbuf_get_eapol_subtype(nbuf); 2383 case QDF_PROTO_TYPE_ARP: 2384 return qdf_nbuf_get_arp_subtype(nbuf); 2385 case QDF_PROTO_TYPE_DHCP: 2386 return qdf_nbuf_get_dhcp_subtype(nbuf); 2387 case QDF_PROTO_TYPE_DNS: 2388 return (qdf_nbuf_data_is_dns_query(nbuf)) ? 2389 QDF_PROTO_DNS_QUERY : QDF_PROTO_DNS_RES; 2390 default: 2391 return QDF_PROTO_INVALID; 2392 } 2393 } 2394 2395 static 2396 bool qdf_dp_proto_log_enable_check(enum qdf_proto_type pkt_type, 2397 uint16_t status) 2398 { 2399 if (pkt_type == QDF_PROTO_TYPE_MAX) 2400 return false; 2401 2402 switch (pkt_type) { 2403 case QDF_PROTO_TYPE_EAPOL: 2404 return qdf_dp_get_proto_event_bitmap() & 2405 QDF_NBUF_PKT_TRAC_TYPE_EAPOL; 2406 case QDF_PROTO_TYPE_DHCP: 2407 return qdf_dp_get_proto_event_bitmap() & 2408 QDF_NBUF_PKT_TRAC_TYPE_DHCP; 2409 case QDF_PROTO_TYPE_ARP: 2410 if (status == QDF_TX_RX_STATUS_OK) 2411 return false; 2412 else 2413 return qdf_dp_get_proto_event_bitmap() & 2414 QDF_NBUF_PKT_TRAC_TYPE_ARP; 2415 case QDF_PROTO_TYPE_DNS: 2416 if (status == QDF_TX_RX_STATUS_OK) 2417 return false; 2418 else 2419 return qdf_dp_get_proto_event_bitmap() & 2420 QDF_NBUF_PKT_TRAC_TYPE_DNS; 2421 default: 2422 return false; 2423 } 2424 } 2425 2426 void qdf_dp_track_noack_check(qdf_nbuf_t nbuf, enum qdf_proto_subtype *subtype) 2427 { 2428 enum qdf_proto_type pkt_type = qdf_dp_get_pkt_proto_type(nbuf); 2429 uint16_t dp_track = 0; 2430 2431 switch (pkt_type) { 2432 case QDF_PROTO_TYPE_EAPOL: 2433 dp_track = qdf_dp_get_proto_bitmap() & 2434 QDF_NBUF_PKT_TRAC_TYPE_EAPOL; 2435 break; 2436 case QDF_PROTO_TYPE_DHCP: 2437 dp_track = qdf_dp_get_proto_bitmap() & 2438 QDF_NBUF_PKT_TRAC_TYPE_DHCP; 2439 break; 2440 case QDF_PROTO_TYPE_ARP: 2441 dp_track = qdf_dp_get_proto_bitmap() & 2442 QDF_NBUF_PKT_TRAC_TYPE_ARP; 2443 break; 2444 case QDF_PROTO_TYPE_DNS: 2445 dp_track = qdf_dp_get_proto_bitmap() & 2446 QDF_NBUF_PKT_TRAC_TYPE_DNS; 2447 break; 2448 default: 2449 break; 2450 } 2451 2452 if (!dp_track) { 2453 *subtype = QDF_PROTO_INVALID; 2454 return; 2455 } 2456 2457 *subtype = qdf_dp_get_pkt_subtype(nbuf, pkt_type); 2458 } 2459 qdf_export_symbol(qdf_dp_track_noack_check); 2460 2461 enum qdf_dp_tx_rx_status qdf_dp_get_status_from_a_status(uint8_t status) 2462 { 2463 if (status == QDF_A_STATUS_ERROR) 2464 return QDF_TX_RX_STATUS_INVALID; 2465 else if (status == QDF_A_STATUS_OK) 2466 return QDF_TX_RX_STATUS_OK; 2467 else 2468 return QDF_TX_RX_STATUS_MAX; 2469 } 2470 qdf_export_symbol(qdf_dp_get_status_from_a_status); 2471 2472 void qdf_dp_trace_ptr(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code, 2473 uint8_t pdev_id, uint8_t *data, uint8_t size, 2474 uint16_t msdu_id, uint16_t buf_arg_status, 2475 enum qdf_dp_tx_rx_status qdf_tx_status, 2476 enum QDF_OPMODE op_mode) 2477 { 2478 struct qdf_dp_trace_ptr_buf buf; 2479 int buf_size = sizeof(struct qdf_dp_trace_ptr_buf); 2480 enum qdf_proto_type pkt_type; 2481 enum qdf_proto_subtype subtype; 2482 2483 pkt_type = qdf_dp_get_pkt_proto_type(nbuf); 2484 if ((code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD || 2485 code == QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD) && 2486 qdf_dp_proto_log_enable_check(pkt_type, qdf_tx_status)) { 2487 subtype = qdf_dp_get_pkt_subtype(nbuf, pkt_type); 2488 qdf_dp_log_proto_pkt_info(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET, 2489 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET, 2490 pkt_type, subtype, 2491 QDF_TX, msdu_id, qdf_tx_status); 2492 qdf_fill_wlan_connectivity_log(pkt_type, subtype, 2493 QDF_TX, qdf_tx_status, op_mode, 2494 QDF_NBUF_CB_TX_VDEV_CTX(nbuf), 2495 nbuf->data, 2496 qdf_nbuf_tx_get_band(nbuf)); 2497 } 2498 2499 if (qdf_dp_enable_check(nbuf, code, QDF_TX) == false) 2500 return; 2501 2502 if (buf_size > QDF_DP_TRACE_RECORD_SIZE) 2503 QDF_BUG(0); 2504 2505 qdf_mem_copy(&buf.cookie, data, size); 2506 buf.msdu_id = msdu_id; 2507 buf.status = buf_arg_status; 2508 qdf_dp_add_record(code, pdev_id, (uint8_t *)&buf, buf_size, NULL, 0, 2509 QDF_NBUF_CB_DP_TRACE_PRINT(nbuf)); 2510 } 2511 qdf_export_symbol(qdf_dp_trace_ptr); 2512 2513 void qdf_dp_trace_data_pkt(qdf_nbuf_t nbuf, uint8_t pdev_id, 2514 enum QDF_DP_TRACE_ID code, uint16_t msdu_id, 2515 enum qdf_proto_dir dir) 2516 { 2517 struct qdf_dp_trace_data_buf buf; 2518 enum qdf_proto_type pkt_type; 2519 2520 pkt_type = qdf_dp_get_pkt_proto_type(nbuf); 2521 if (code == QDF_DP_TRACE_DROP_PACKET_RECORD && 2522 qdf_dp_proto_log_enable_check(pkt_type, QDF_TX_RX_STATUS_DROP)) 2523 qdf_dp_log_proto_pkt_info(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET, 2524 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET, 2525 pkt_type, 2526 qdf_dp_get_pkt_subtype(nbuf, pkt_type), 2527 QDF_TX, msdu_id, 2528 QDF_TX_RX_STATUS_DROP); 2529 2530 buf.msdu_id = msdu_id; 2531 if (!qdf_dp_enable_check(nbuf, code, dir)) 2532 return; 2533 2534 qdf_dp_add_record(code, pdev_id, 2535 nbuf ? qdf_nbuf_data(nbuf) : NULL, 2536 nbuf ? nbuf->len - nbuf->data_len : 0, 2537 (uint8_t *)&buf, sizeof(struct qdf_dp_trace_data_buf), 2538 (nbuf) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false); 2539 } 2540 2541 qdf_export_symbol(qdf_dp_trace_data_pkt); 2542 2543 void qdf_dp_display_record(struct qdf_dp_trace_record_s *record, 2544 uint16_t index, uint8_t pdev_id, uint8_t info) 2545 { 2546 int loc; 2547 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2548 2549 if (!(pdev_id == QDF_TRACE_DEFAULT_PDEV_ID || 2550 pdev_id == record->pdev_id)) 2551 return; 2552 2553 qdf_mem_zero(prepend_str, sizeof(prepend_str)); 2554 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2555 index, info, record); 2556 2557 switch (record->code) { 2558 case QDF_DP_TRACE_HDD_TX_TIMEOUT: 2559 DPTRACE_PRINT(" %s: HDD TX Timeout", prepend_str); 2560 break; 2561 case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT: 2562 DPTRACE_PRINT(" %s: HDD SoftAP TX Timeout", prepend_str); 2563 break; 2564 case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD: 2565 DPTRACE_PRINT(" %s: CE Fast Packet Error", prepend_str); 2566 break; 2567 case QDF_DP_TRACE_LI_DP_NULL_RX_PACKET_RECORD: 2568 default: 2569 dump_dp_hex_trace(prepend_str, record->data, record->size); 2570 break; 2571 }; 2572 } 2573 qdf_export_symbol(qdf_dp_display_record); 2574 2575 void 2576 qdf_dp_display_data_pkt_record(struct qdf_dp_trace_record_s *record, 2577 uint16_t rec_index, uint8_t pdev_id, 2578 uint8_t info) 2579 { 2580 int loc; 2581 char prepend_str[DP_TRACE_META_DATA_STRLEN + 10]; 2582 struct qdf_dp_trace_data_buf *buf = 2583 (struct qdf_dp_trace_data_buf *)record->data; 2584 2585 qdf_mem_zero(prepend_str, sizeof(prepend_str)); 2586 2587 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2588 rec_index, info, record); 2589 if (loc < sizeof(prepend_str)) 2590 loc += snprintf(&prepend_str[loc], sizeof(prepend_str) - loc, 2591 "[%d]", buf->msdu_id); 2592 dump_dp_hex_trace(prepend_str, 2593 &record->data[sizeof(struct qdf_dp_trace_data_buf)], 2594 record->size); 2595 } 2596 2597 void qdf_dp_trace(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code, uint8_t pdev_id, 2598 uint8_t *data, uint8_t size, enum qdf_proto_dir dir) 2599 { 2600 2601 if (qdf_dp_enable_check(nbuf, code, dir) == false) 2602 return; 2603 2604 qdf_dp_add_record(code, pdev_id, nbuf ? qdf_nbuf_data(nbuf) : NULL, 2605 size, NULL, 0, 2606 (nbuf) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false); 2607 } 2608 qdf_export_symbol(qdf_dp_trace); 2609 2610 void qdf_dp_trace_spin_lock_init(void) 2611 { 2612 spin_lock_init(&l_dp_trace_lock); 2613 } 2614 qdf_export_symbol(qdf_dp_trace_spin_lock_init); 2615 2616 void qdf_dp_trace_disable_live_mode(void) 2617 { 2618 g_qdf_dp_trace_data.force_live_mode = 0; 2619 } 2620 qdf_export_symbol(qdf_dp_trace_disable_live_mode); 2621 2622 void qdf_dp_trace_enable_live_mode(void) 2623 { 2624 g_qdf_dp_trace_data.force_live_mode = 1; 2625 } 2626 qdf_export_symbol(qdf_dp_trace_enable_live_mode); 2627 2628 void qdf_dp_trace_clear_buffer(void) 2629 { 2630 g_qdf_dp_trace_data.head = INVALID_QDF_DP_TRACE_ADDR; 2631 g_qdf_dp_trace_data.tail = INVALID_QDF_DP_TRACE_ADDR; 2632 g_qdf_dp_trace_data.num = 0; 2633 g_qdf_dp_trace_data.dump_counter = 0; 2634 g_qdf_dp_trace_data.num_records_to_dump = MAX_QDF_DP_TRACE_RECORDS; 2635 if (g_qdf_dp_trace_data.enable) 2636 memset(g_qdf_dp_trace_tbl, 0, 2637 MAX_QDF_DP_TRACE_RECORDS * 2638 sizeof(struct qdf_dp_trace_record_s)); 2639 } 2640 qdf_export_symbol(qdf_dp_trace_clear_buffer); 2641 2642 void qdf_dp_trace_dump_stats(void) 2643 { 2644 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)", 2645 g_qdf_dp_trace_data.tx_count, 2646 g_qdf_dp_trace_data.rx_count, 2647 g_qdf_dp_trace_data.icmp_req, 2648 g_qdf_dp_trace_data.icmp_resp, 2649 g_qdf_dp_trace_data.arp_req, 2650 g_qdf_dp_trace_data.arp_resp, 2651 g_qdf_dp_trace_data.icmpv6_req, 2652 g_qdf_dp_trace_data.icmpv6_resp, 2653 g_qdf_dp_trace_data.icmpv6_ns, 2654 g_qdf_dp_trace_data.icmpv6_na, 2655 g_qdf_dp_trace_data.icmpv6_rs, 2656 g_qdf_dp_trace_data.icmpv6_ra, 2657 g_qdf_dp_trace_data.dhcp_disc, 2658 g_qdf_dp_trace_data.dhcp_off, 2659 g_qdf_dp_trace_data.dhcp_req, 2660 g_qdf_dp_trace_data.dhcp_ack, 2661 g_qdf_dp_trace_data.dhcp_nack, 2662 g_qdf_dp_trace_data.dhcp_others, 2663 g_qdf_dp_trace_data.eapol_m1, 2664 g_qdf_dp_trace_data.eapol_m2, 2665 g_qdf_dp_trace_data.eapol_m3, 2666 g_qdf_dp_trace_data.eapol_m4, 2667 g_qdf_dp_trace_data.eapol_others); 2668 } 2669 qdf_export_symbol(qdf_dp_trace_dump_stats); 2670 2671 /** 2672 * qdf_dpt_dump_hex_trace_debugfs() - read data in file 2673 * @file: file to read 2674 * @str: string to prepend the hexdump with. 2675 * @buf: buffer which contains data to be written 2676 * @buf_len: defines the size of the data to be written 2677 * 2678 * Return: None 2679 */ 2680 static void qdf_dpt_dump_hex_trace_debugfs(qdf_debugfs_file_t file, 2681 char *str, uint8_t *buf, uint8_t buf_len) 2682 { 2683 unsigned char linebuf[BUFFER_SIZE]; 2684 const u8 *ptr = buf; 2685 int i, linelen, remaining = buf_len; 2686 2687 /* Dump the bytes in the last line */ 2688 for (i = 0; i < buf_len; i += ROW_SIZE) { 2689 linelen = min(remaining, ROW_SIZE); 2690 remaining -= ROW_SIZE; 2691 2692 hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1, 2693 linebuf, sizeof(linebuf), false); 2694 2695 qdf_debugfs_printf(file, "%s %s\n", str, linebuf); 2696 } 2697 } 2698 2699 /** 2700 * qdf_dpt_display_proto_pkt_debugfs() - display proto packet 2701 * @file: file to read 2702 * @record: dptrace record 2703 * @index: index 2704 * 2705 * Return: none 2706 */ 2707 static void qdf_dpt_display_proto_pkt_debugfs(qdf_debugfs_file_t file, 2708 struct qdf_dp_trace_record_s *record, 2709 uint32_t index) 2710 { 2711 int loc; 2712 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2713 struct qdf_dp_trace_proto_buf *buf = 2714 (struct qdf_dp_trace_proto_buf *)record->data; 2715 2716 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2717 index, 0, record); 2718 qdf_debugfs_printf(file, "%s [%d] [%s] SA: " 2719 QDF_MAC_ADDR_FMT " %s DA: " 2720 QDF_MAC_ADDR_FMT, 2721 prepend_str, 2722 buf->cmn_info.vdev_id, 2723 qdf_dp_subtype_to_str(buf->cmn_info.subtype), 2724 QDF_MAC_ADDR_REF(buf->sa.bytes), 2725 qdf_dp_dir_to_str(buf->dir), 2726 QDF_MAC_ADDR_REF(buf->da.bytes)); 2727 qdf_debugfs_printf(file, "\n"); 2728 } 2729 2730 /** 2731 * qdf_dpt_display_mgmt_pkt_debugfs() - display mgmt packet 2732 * @file: file to read 2733 * @record: dptrace record 2734 * @index: index 2735 * 2736 * Return: none 2737 */ 2738 static void qdf_dpt_display_mgmt_pkt_debugfs(qdf_debugfs_file_t file, 2739 struct qdf_dp_trace_record_s *record, 2740 uint32_t index) 2741 { 2742 2743 int loc; 2744 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2745 struct qdf_dp_trace_mgmt_buf *buf = 2746 (struct qdf_dp_trace_mgmt_buf *)record->data; 2747 2748 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2749 index, 0, record); 2750 2751 qdf_debugfs_printf(file, "%s [%d] [%s %s]\n", 2752 prepend_str, 2753 buf->vdev_id, 2754 qdf_dp_type_to_str(buf->type), 2755 qdf_dp_subtype_to_str(buf->subtype)); 2756 } 2757 2758 /** 2759 * qdf_dpt_display_event_record_debugfs() - display event records 2760 * @file: file to read 2761 * @record: dptrace record 2762 * @index: index 2763 * 2764 * Return: none 2765 */ 2766 static void qdf_dpt_display_event_record_debugfs(qdf_debugfs_file_t file, 2767 struct qdf_dp_trace_record_s *record, 2768 uint32_t index) 2769 { 2770 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2771 struct qdf_dp_trace_event_buf *buf = 2772 (struct qdf_dp_trace_event_buf *)record->data; 2773 2774 qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2775 index, 0, record); 2776 qdf_debugfs_printf(file, "%s [%d] [%s %s]\n", 2777 prepend_str, 2778 buf->vdev_id, 2779 qdf_dp_type_to_str(buf->type), 2780 qdf_dp_subtype_to_str(buf->subtype)); 2781 } 2782 2783 /** 2784 * qdf_dpt_display_ptr_record_debugfs() - display record ptr 2785 * @file: file to read 2786 * @record: dptrace record 2787 * @index: index 2788 * 2789 * Return: none 2790 */ 2791 static void qdf_dpt_display_ptr_record_debugfs(qdf_debugfs_file_t file, 2792 struct qdf_dp_trace_record_s *record, 2793 uint32_t index) 2794 { 2795 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2796 int loc; 2797 struct qdf_dp_trace_ptr_buf *buf = 2798 (struct qdf_dp_trace_ptr_buf *)record->data; 2799 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2800 index, 0, record); 2801 2802 if (loc < sizeof(prepend_str)) 2803 scnprintf(&prepend_str[loc], sizeof(prepend_str) - loc, 2804 "[msdu id %d %s %d]", 2805 buf->msdu_id, 2806 (record->code == 2807 QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) ? 2808 "status" : "vdev_id", 2809 buf->status); 2810 2811 qdf_dpt_dump_hex_trace_debugfs(file, prepend_str, 2812 (uint8_t *)&buf->cookie, 2813 sizeof(buf->cookie)); 2814 } 2815 2816 /** 2817 * qdf_dpt_display_record_debugfs() - display record 2818 * @file: file to read 2819 * @record: dptrace record 2820 * @index: index 2821 * 2822 * Return: none 2823 */ 2824 static void qdf_dpt_display_record_debugfs(qdf_debugfs_file_t file, 2825 struct qdf_dp_trace_record_s *record, 2826 uint32_t index) 2827 { 2828 int loc; 2829 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2830 struct qdf_dp_trace_data_buf *buf = 2831 (struct qdf_dp_trace_data_buf *)record->data; 2832 2833 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2834 index, 0, record); 2835 if (loc < sizeof(prepend_str)) 2836 loc += snprintf(&prepend_str[loc], sizeof(prepend_str) - loc, 2837 "[%d]", buf->msdu_id); 2838 qdf_dpt_dump_hex_trace_debugfs(file, prepend_str, 2839 record->data, record->size); 2840 } 2841 2842 uint32_t qdf_dpt_get_curr_pos_debugfs(qdf_debugfs_file_t file, 2843 enum qdf_dpt_debugfs_state state) 2844 { 2845 uint32_t i = 0; 2846 uint32_t tail; 2847 uint32_t count = g_qdf_dp_trace_data.num; 2848 2849 if (!g_qdf_dp_trace_data.enable) { 2850 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, 2851 "%s: Tracing Disabled", __func__); 2852 return QDF_STATUS_E_EMPTY; 2853 } 2854 2855 if (!count) { 2856 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, 2857 "%s: no packets", __func__); 2858 return QDF_STATUS_E_EMPTY; 2859 } 2860 2861 if (state == QDF_DPT_DEBUGFS_STATE_SHOW_IN_PROGRESS) 2862 return g_qdf_dp_trace_data.curr_pos; 2863 2864 qdf_debugfs_printf(file, 2865 "DPT: config - bitmap 0x%x verb %u #rec %u rec_requested %u live_config %u thresh %u time_limit %u\n", 2866 g_qdf_dp_trace_data.proto_bitmap, 2867 g_qdf_dp_trace_data.verbosity, 2868 g_qdf_dp_trace_data.no_of_record, 2869 g_qdf_dp_trace_data.num_records_to_dump, 2870 g_qdf_dp_trace_data.live_mode_config, 2871 g_qdf_dp_trace_data.high_tput_thresh, 2872 g_qdf_dp_trace_data.thresh_time_limit); 2873 2874 qdf_debugfs_printf(file, 2875 "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", 2876 g_qdf_dp_trace_data.icmp_req, 2877 g_qdf_dp_trace_data.icmp_resp, 2878 g_qdf_dp_trace_data.arp_req, 2879 g_qdf_dp_trace_data.arp_resp, 2880 g_qdf_dp_trace_data.icmpv6_req, 2881 g_qdf_dp_trace_data.icmpv6_resp, 2882 g_qdf_dp_trace_data.icmpv6_ns, 2883 g_qdf_dp_trace_data.icmpv6_na, 2884 g_qdf_dp_trace_data.icmpv6_rs, 2885 g_qdf_dp_trace_data.icmpv6_ra, 2886 g_qdf_dp_trace_data.dhcp_disc, 2887 g_qdf_dp_trace_data.dhcp_off, 2888 g_qdf_dp_trace_data.dhcp_req, 2889 g_qdf_dp_trace_data.dhcp_ack, 2890 g_qdf_dp_trace_data.dhcp_nack, 2891 g_qdf_dp_trace_data.dhcp_others, 2892 g_qdf_dp_trace_data.eapol_m1, 2893 g_qdf_dp_trace_data.eapol_m2, 2894 g_qdf_dp_trace_data.eapol_m3, 2895 g_qdf_dp_trace_data.eapol_m4, 2896 g_qdf_dp_trace_data.eapol_others); 2897 2898 qdf_debugfs_printf(file, 2899 "DPT: Total Records: %d, Head: %d, Tail: %d\n", 2900 g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head, 2901 g_qdf_dp_trace_data.tail); 2902 2903 spin_lock_bh(&l_dp_trace_lock); 2904 if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) { 2905 i = g_qdf_dp_trace_data.head; 2906 tail = g_qdf_dp_trace_data.tail; 2907 2908 if (count > g_qdf_dp_trace_data.num) 2909 count = g_qdf_dp_trace_data.num; 2910 2911 if (tail >= (count - 1)) 2912 i = tail - count + 1; 2913 else if (count != MAX_QDF_DP_TRACE_RECORDS) 2914 i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) - 2915 tail); 2916 g_qdf_dp_trace_data.curr_pos = 0; 2917 g_qdf_dp_trace_data.saved_tail = tail; 2918 } 2919 spin_unlock_bh(&l_dp_trace_lock); 2920 2921 return g_qdf_dp_trace_data.saved_tail; 2922 } 2923 qdf_export_symbol(qdf_dpt_get_curr_pos_debugfs); 2924 2925 QDF_STATUS qdf_dpt_dump_stats_debugfs(qdf_debugfs_file_t file, 2926 uint32_t curr_pos) 2927 { 2928 struct qdf_dp_trace_record_s p_record; 2929 uint32_t i = curr_pos; 2930 uint16_t num_records_to_dump = g_qdf_dp_trace_data.num_records_to_dump; 2931 2932 if (!g_qdf_dp_trace_data.enable) { 2933 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2934 "%s: Tracing Disabled", __func__); 2935 return QDF_STATUS_E_FAILURE; 2936 } 2937 2938 if (num_records_to_dump > g_qdf_dp_trace_data.num) 2939 num_records_to_dump = g_qdf_dp_trace_data.num; 2940 2941 /* 2942 * Max dp trace record size should always be less than 2943 * QDF_DP_TRACE_PREPEND_STR_SIZE(100) + BUFFER_SIZE(121). 2944 */ 2945 if (WARN_ON(QDF_DP_TRACE_MAX_RECORD_SIZE < 2946 QDF_DP_TRACE_PREPEND_STR_SIZE + BUFFER_SIZE)) 2947 return QDF_STATUS_E_FAILURE; 2948 2949 spin_lock_bh(&l_dp_trace_lock); 2950 p_record = g_qdf_dp_trace_tbl[i]; 2951 spin_unlock_bh(&l_dp_trace_lock); 2952 2953 for (;; ) { 2954 /* 2955 * Initially we get file as 1 page size, and 2956 * if remaining size in file is less than one record max size, 2957 * then return so that it gets an extra page. 2958 */ 2959 if ((file->size - file->count) < QDF_DP_TRACE_MAX_RECORD_SIZE) { 2960 spin_lock_bh(&l_dp_trace_lock); 2961 g_qdf_dp_trace_data.curr_pos = i; 2962 spin_unlock_bh(&l_dp_trace_lock); 2963 return QDF_STATUS_E_FAILURE; 2964 } 2965 2966 switch (p_record.code) { 2967 case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD: 2968 case QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD: 2969 case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD: 2970 qdf_dpt_display_ptr_record_debugfs(file, &p_record, i); 2971 break; 2972 2973 case QDF_DP_TRACE_EAPOL_PACKET_RECORD: 2974 case QDF_DP_TRACE_DHCP_PACKET_RECORD: 2975 case QDF_DP_TRACE_ARP_PACKET_RECORD: 2976 case QDF_DP_TRACE_ICMP_PACKET_RECORD: 2977 case QDF_DP_TRACE_ICMPv6_PACKET_RECORD: 2978 qdf_dpt_display_proto_pkt_debugfs(file, &p_record, i); 2979 break; 2980 2981 case QDF_DP_TRACE_TX_CREDIT_RECORD: 2982 qdf_dpt_display_credit_record_debugfs(file, &p_record, 2983 i); 2984 break; 2985 2986 case QDF_DP_TRACE_MGMT_PACKET_RECORD: 2987 qdf_dpt_display_mgmt_pkt_debugfs(file, &p_record, i); 2988 break; 2989 2990 case QDF_DP_TRACE_EVENT_RECORD: 2991 qdf_dpt_display_event_record_debugfs(file, &p_record, 2992 i); 2993 break; 2994 2995 case QDF_DP_TRACE_HDD_TX_TIMEOUT: 2996 qdf_debugfs_printf( 2997 file, "DPT: %04d: %llu %s\n", 2998 i, p_record.time, 2999 qdf_dp_code_to_string(p_record.code)); 3000 qdf_debugfs_printf(file, "HDD TX Timeout\n"); 3001 break; 3002 3003 case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT: 3004 qdf_debugfs_printf( 3005 file, "DPT: %04d: %llu %s\n", 3006 i, p_record.time, 3007 qdf_dp_code_to_string(p_record.code)); 3008 qdf_debugfs_printf(file, "HDD SoftAP TX Timeout\n"); 3009 break; 3010 3011 case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD: 3012 qdf_debugfs_printf( 3013 file, "DPT: %04d: %llu %s\n", 3014 i, p_record.time, 3015 qdf_dp_code_to_string(p_record.code)); 3016 qdf_debugfs_printf(file, "CE Fast Packet Error\n"); 3017 break; 3018 3019 case QDF_DP_TRACE_MAX: 3020 qdf_debugfs_printf(file, 3021 "%s: QDF_DP_TRACE_MAX event should not be generated\n", 3022 __func__); 3023 break; 3024 3025 case QDF_DP_TRACE_HDD_TX_PACKET_RECORD: 3026 case QDF_DP_TRACE_HDD_RX_PACKET_RECORD: 3027 case QDF_DP_TRACE_TX_PACKET_RECORD: 3028 case QDF_DP_TRACE_RX_PACKET_RECORD: 3029 case QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD: 3030 case QDF_DP_TRACE_LI_DP_RX_PACKET_RECORD: 3031 3032 default: 3033 qdf_dpt_display_record_debugfs(file, &p_record, i); 3034 break; 3035 } 3036 3037 if (++g_qdf_dp_trace_data.dump_counter == num_records_to_dump) 3038 break; 3039 3040 spin_lock_bh(&l_dp_trace_lock); 3041 if (i == 0) 3042 i = MAX_QDF_DP_TRACE_RECORDS; 3043 3044 i -= 1; 3045 p_record = g_qdf_dp_trace_tbl[i]; 3046 spin_unlock_bh(&l_dp_trace_lock); 3047 } 3048 3049 g_qdf_dp_trace_data.dump_counter = 0; 3050 3051 return QDF_STATUS_SUCCESS; 3052 } 3053 qdf_export_symbol(qdf_dpt_dump_stats_debugfs); 3054 3055 void qdf_dpt_set_value_debugfs(uint8_t proto_bitmap, uint8_t no_of_record, 3056 uint8_t verbosity, uint16_t num_records_to_dump) 3057 { 3058 if (g_qdf_dp_trace_data.enable) { 3059 g_qdf_dp_trace_data.proto_bitmap = proto_bitmap; 3060 g_qdf_dp_trace_data.no_of_record = no_of_record; 3061 g_qdf_dp_trace_data.verbosity = verbosity; 3062 g_qdf_dp_trace_data.num_records_to_dump = num_records_to_dump; 3063 } 3064 } 3065 qdf_export_symbol(qdf_dpt_set_value_debugfs); 3066 3067 3068 void qdf_dp_trace_dump_all(uint32_t count, uint8_t pdev_id) 3069 { 3070 struct qdf_dp_trace_record_s p_record; 3071 int32_t i, tail; 3072 3073 if (!g_qdf_dp_trace_data.enable) { 3074 DPTRACE_PRINT("Tracing Disabled"); 3075 return; 3076 } 3077 3078 DPTRACE_PRINT( 3079 "DPT: config - bitmap 0x%x verb %u #rec %u live_config %u thresh %u time_limit %u", 3080 g_qdf_dp_trace_data.proto_bitmap, 3081 g_qdf_dp_trace_data.verbosity, 3082 g_qdf_dp_trace_data.no_of_record, 3083 g_qdf_dp_trace_data.live_mode_config, 3084 g_qdf_dp_trace_data.high_tput_thresh, 3085 g_qdf_dp_trace_data.thresh_time_limit); 3086 3087 qdf_dp_trace_dump_stats(); 3088 3089 DPTRACE_PRINT("DPT: Total Records: %d, Head: %d, Tail: %d", 3090 g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head, 3091 g_qdf_dp_trace_data.tail); 3092 3093 /* acquire the lock so that only one thread at a time can read 3094 * the ring buffer 3095 */ 3096 spin_lock_bh(&l_dp_trace_lock); 3097 3098 if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) { 3099 i = g_qdf_dp_trace_data.head; 3100 tail = g_qdf_dp_trace_data.tail; 3101 3102 if (count) { 3103 if (count > g_qdf_dp_trace_data.num) 3104 count = g_qdf_dp_trace_data.num; 3105 if (tail >= (count - 1)) 3106 i = tail - count + 1; 3107 else if (count != MAX_QDF_DP_TRACE_RECORDS) 3108 i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) - 3109 tail); 3110 } 3111 3112 p_record = g_qdf_dp_trace_tbl[i]; 3113 spin_unlock_bh(&l_dp_trace_lock); 3114 for (;; ) { 3115 qdf_dp_trace_cb_table[p_record.code](&p_record, 3116 (uint16_t)i, pdev_id, false); 3117 if (i == tail) 3118 break; 3119 i += 1; 3120 3121 spin_lock_bh(&l_dp_trace_lock); 3122 if (MAX_QDF_DP_TRACE_RECORDS == i) 3123 i = 0; 3124 3125 p_record = g_qdf_dp_trace_tbl[i]; 3126 spin_unlock_bh(&l_dp_trace_lock); 3127 } 3128 } else { 3129 spin_unlock_bh(&l_dp_trace_lock); 3130 } 3131 } 3132 qdf_export_symbol(qdf_dp_trace_dump_all); 3133 3134 void qdf_dp_trace_throttle_live_mode(bool high_bw_request) 3135 { 3136 static int bw_interval_counter; 3137 3138 if (g_qdf_dp_trace_data.enable == false || 3139 g_qdf_dp_trace_data.live_mode_config == false) 3140 return; 3141 3142 if (high_bw_request) { 3143 g_qdf_dp_trace_data.live_mode = 0; 3144 bw_interval_counter = 0; 3145 return; 3146 } 3147 3148 bw_interval_counter++; 3149 3150 if (0 == (bw_interval_counter % 3151 g_qdf_dp_trace_data.thresh_time_limit)) { 3152 3153 spin_lock_bh(&l_dp_trace_lock); 3154 if (g_qdf_dp_trace_data.print_pkt_cnt <= 3155 g_qdf_dp_trace_data.high_tput_thresh) 3156 g_qdf_dp_trace_data.live_mode = 1; 3157 3158 g_qdf_dp_trace_data.print_pkt_cnt = 0; 3159 spin_unlock_bh(&l_dp_trace_lock); 3160 } 3161 } 3162 qdf_export_symbol(qdf_dp_trace_throttle_live_mode); 3163 3164 void qdf_dp_trace_apply_tput_policy(bool is_data_traffic) 3165 { 3166 if (g_qdf_dp_trace_data.dynamic_verbosity_modify) { 3167 goto check_live_mode; 3168 return; 3169 } 3170 3171 if (is_data_traffic) { 3172 g_qdf_dp_trace_data.verbosity = 3173 QDF_DP_TRACE_VERBOSITY_ULTRA_LOW; 3174 } else { 3175 g_qdf_dp_trace_data.verbosity = 3176 g_qdf_dp_trace_data.ini_conf_verbosity; 3177 } 3178 check_live_mode: 3179 qdf_dp_trace_throttle_live_mode(is_data_traffic); 3180 } 3181 #endif 3182 3183 struct qdf_print_ctrl print_ctrl_obj[MAX_PRINT_CONFIG_SUPPORTED]; 3184 3185 struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = { 3186 [QDF_MODULE_ID_TDLS] = {"tdls"}, 3187 [QDF_MODULE_ID_ACS] = {"ACS"}, 3188 [QDF_MODULE_ID_SCAN_SM] = {"scan state machine"}, 3189 [QDF_MODULE_ID_SCANENTRY] = {"scan entry"}, 3190 [QDF_MODULE_ID_WDS] = {"WDS"}, 3191 [QDF_MODULE_ID_ACTION] = {"action"}, 3192 [QDF_MODULE_ID_ROAM] = {"STA roaming"}, 3193 [QDF_MODULE_ID_INACT] = {"inactivity"}, 3194 [QDF_MODULE_ID_DOTH] = {"11h"}, 3195 [QDF_MODULE_ID_IQUE] = {"IQUE"}, 3196 [QDF_MODULE_ID_WME] = {"WME"}, 3197 [QDF_MODULE_ID_ACL] = {"ACL"}, 3198 [QDF_MODULE_ID_WPA] = {"WPA/RSN"}, 3199 [QDF_MODULE_ID_RADKEYS] = {"dump 802.1x keys"}, 3200 [QDF_MODULE_ID_RADDUMP] = {"dump radius packet"}, 3201 [QDF_MODULE_ID_RADIUS] = {"802.1x radius client"}, 3202 [QDF_MODULE_ID_DOT1XSM] = {"802.1x state machine"}, 3203 [QDF_MODULE_ID_DOT1X] = {"802.1x authenticator"}, 3204 [QDF_MODULE_ID_POWER] = {"power save"}, 3205 [QDF_MODULE_ID_STATE] = {"state"}, 3206 [QDF_MODULE_ID_OUTPUT] = {"output"}, 3207 [QDF_MODULE_ID_SCAN] = {"scan"}, 3208 [QDF_MODULE_ID_AUTH] = {"authentication"}, 3209 [QDF_MODULE_ID_ASSOC] = {"association"}, 3210 [QDF_MODULE_ID_NODE] = {"node"}, 3211 [QDF_MODULE_ID_ELEMID] = {"element ID"}, 3212 [QDF_MODULE_ID_XRATE] = {"rate"}, 3213 [QDF_MODULE_ID_INPUT] = {"input"}, 3214 [QDF_MODULE_ID_CRYPTO] = {"crypto"}, 3215 [QDF_MODULE_ID_DUMPPKTS] = {"dump packet"}, 3216 [QDF_MODULE_ID_DEBUG] = {"debug"}, 3217 [QDF_MODULE_ID_MLME] = {"mlme"}, 3218 [QDF_MODULE_ID_RRM] = {"rrm"}, 3219 [QDF_MODULE_ID_WNM] = {"wnm"}, 3220 [QDF_MODULE_ID_P2P_PROT] = {"p2p_prot"}, 3221 [QDF_MODULE_ID_PROXYARP] = {"proxyarp"}, 3222 [QDF_MODULE_ID_L2TIF] = {"l2tif"}, 3223 [QDF_MODULE_ID_WIFIPOS] = {"wifipos"}, 3224 [QDF_MODULE_ID_WRAP] = {"wrap"}, 3225 [QDF_MODULE_ID_DFS] = {"dfs"}, 3226 [QDF_MODULE_ID_ATF] = {"atf"}, 3227 [QDF_MODULE_ID_SPLITMAC] = {"splitmac"}, 3228 [QDF_MODULE_ID_IOCTL] = {"ioctl"}, 3229 [QDF_MODULE_ID_NAC] = {"nac"}, 3230 [QDF_MODULE_ID_MESH] = {"mesh"}, 3231 [QDF_MODULE_ID_MBO] = {"mbo"}, 3232 [QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = {"extchanswitch"}, 3233 [QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = {"extchanscan"}, 3234 [QDF_MODULE_ID_TLSHIM] = {"tlshim"}, 3235 [QDF_MODULE_ID_WMI] = {"WMI"}, 3236 [QDF_MODULE_ID_HTT] = {"HTT"}, 3237 [QDF_MODULE_ID_HDD] = {"HDD"}, 3238 [QDF_MODULE_ID_SME] = {"SME"}, 3239 [QDF_MODULE_ID_PE] = {"PE"}, 3240 [QDF_MODULE_ID_WMA] = {"WMA"}, 3241 [QDF_MODULE_ID_SYS] = {"SYS"}, 3242 [QDF_MODULE_ID_QDF] = {"QDF"}, 3243 [QDF_MODULE_ID_SAP] = {"SAP"}, 3244 [QDF_MODULE_ID_HDD_SOFTAP] = {"HDD_SAP"}, 3245 [QDF_MODULE_ID_HDD_DATA] = {"DATA"}, 3246 [QDF_MODULE_ID_HDD_SAP_DATA] = {"SAP_DATA"}, 3247 [QDF_MODULE_ID_HIF] = {"HIF"}, 3248 [QDF_MODULE_ID_HTC] = {"HTC"}, 3249 [QDF_MODULE_ID_TXRX] = {"TXRX"}, 3250 [QDF_MODULE_ID_QDF_DEVICE] = {"QDF_DEV"}, 3251 [QDF_MODULE_ID_CFG] = {"CFG"}, 3252 [QDF_MODULE_ID_BMI] = {"BMI"}, 3253 [QDF_MODULE_ID_EPPING] = {"EPPING"}, 3254 [QDF_MODULE_ID_QVIT] = {"QVIT"}, 3255 [QDF_MODULE_ID_DP] = {"DP"}, 3256 [QDF_MODULE_ID_HAL] = {"HAL"}, 3257 [QDF_MODULE_ID_SOC] = {"SOC"}, 3258 [QDF_MODULE_ID_OS_IF] = {"OSIF"}, 3259 [QDF_MODULE_ID_TARGET_IF] = {"TIF"}, 3260 [QDF_MODULE_ID_SCHEDULER] = {"SCH"}, 3261 [QDF_MODULE_ID_MGMT_TXRX] = {"MGMT_TXRX"}, 3262 [QDF_MODULE_ID_PMO] = {"PMO"}, 3263 [QDF_MODULE_ID_POLICY_MGR] = {"POLICY_MGR"}, 3264 [QDF_MODULE_ID_SA_API] = {"SA_API"}, 3265 [QDF_MODULE_ID_NAN] = {"NAN"}, 3266 [QDF_MODULE_ID_SPECTRAL] = {"SPECTRAL"}, 3267 [QDF_MODULE_ID_P2P] = {"P2P"}, 3268 [QDF_MODULE_ID_OFFCHAN_TXRX] = {"OFFCHAN"}, 3269 [QDF_MODULE_ID_REGULATORY] = {"REGULATORY"}, 3270 [QDF_MODULE_ID_OBJ_MGR] = {"OBJMGR"}, 3271 [QDF_MODULE_ID_SERIALIZATION] = {"SER"}, 3272 [QDF_MODULE_ID_NSS] = {"NSS"}, 3273 [QDF_MODULE_ID_ROAM_DEBUG] = {"roam debug"}, 3274 [QDF_MODULE_ID_DIRECT_BUF_RX] = {"DIRECT_BUF_RX"}, 3275 [QDF_MODULE_ID_DISA] = {"disa"}, 3276 [QDF_MODULE_ID_GREEN_AP] = {"GREEN_AP"}, 3277 [QDF_MODULE_ID_FD] = {"FILS discovery"}, 3278 [QDF_MODULE_ID_FTM] = {"FTM"}, 3279 [QDF_MODULE_ID_OCB] = {"OCB"}, 3280 [QDF_MODULE_ID_CONFIG] = {"CONFIG"}, 3281 [QDF_MODULE_ID_IPA] = {"IPA"}, 3282 [QDF_MODULE_ID_CP_STATS] = {"CP_STATS"}, 3283 [QDF_MODULE_ID_DCS] = {"DCS"}, 3284 [QDF_MODULE_ID_ACTION_OUI] = {"action_oui"}, 3285 [QDF_MODULE_ID_TARGET] = {"TARGET"}, 3286 [QDF_MODULE_ID_MBSSIE] = {"MBSSIE"}, 3287 [QDF_MODULE_ID_FWOL] = {"fwol"}, 3288 [QDF_MODULE_ID_SM_ENGINE] = {"SM_ENG"}, 3289 [QDF_MODULE_ID_CMN_MLME] = {"CMN_MLME"}, 3290 [QDF_MODULE_ID_BSSCOLOR] = {"BSSCOLOR"}, 3291 [QDF_MODULE_ID_CFR] = {"CFR"}, 3292 [QDF_MODULE_ID_DP_TX_CAPTURE] = {"TX_CAPTURE_ENHANCE"}, 3293 [QDF_MODULE_ID_INTEROP_ISSUES_AP] = {"INTEROP_ISSUES_AP"}, 3294 [QDF_MODULE_ID_DENYLIST_MGR] = {"dlm"}, 3295 [QDF_MODULE_ID_QLD] = {"QLD"}, 3296 [QDF_MODULE_ID_DYNAMIC_MODE_CHG] = {"Dynamic Mode Change"}, 3297 [QDF_MODULE_ID_COEX] = {"COEX"}, 3298 [QDF_MODULE_ID_MON_FILTER] = {"Monitor Filter"}, 3299 [QDF_MODULE_ID_PKT_CAPTURE] = {"pkt_capture"}, 3300 [QDF_MODULE_ID_RPTR] = {"RPTR"}, 3301 [QDF_MODULE_ID_6GHZ] = {"6GHZ"}, 3302 [QDF_MODULE_ID_IOT_SIM] = {"IOT_SIM"}, 3303 [QDF_MODULE_ID_MSCS] = {"MSCS"}, 3304 [QDF_MODULE_ID_GPIO] = {"GPIO_CFG"}, 3305 [QDF_MODULE_ID_IFMGR] = {"IF_MGR"}, 3306 [QDF_MODULE_ID_DIAG] = {"DIAG"}, 3307 [QDF_MODULE_ID_DP_INIT] = {"DP_INIT"}, 3308 [QDF_MODULE_ID_DP_TX] = {"DP_TX"}, 3309 [QDF_MODULE_ID_DP_RX] = {"DP_RX"}, 3310 [QDF_MODULE_ID_DP_STATS] = {"DP_STATS"}, 3311 [QDF_MODULE_ID_DP_HTT] = {"DP_HTT"}, 3312 [QDF_MODULE_ID_DP_PEER] = {"DP_PEER"}, 3313 [QDF_MODULE_ID_DP_RX_ERROR] = {"DP_RX_ERROR"}, 3314 [QDF_MODULE_ID_DP_HTT_TX_STATS] = {"DP_HTT_TX_STATS"}, 3315 [QDF_MODULE_ID_DP_RX_MON_STATUS] = {"DP_RX_MON_STATUS"}, 3316 [QDF_MODULE_ID_DP_RX_MON_DEST] = {"DP_RX_MON_DEST"}, 3317 [QDF_MODULE_ID_DP_REO] = {"DP_REO"}, 3318 [QDF_MODULE_ID_DP_TX_COMP] = {"DP_TX_COMP"}, 3319 [QDF_MODULE_ID_DP_VDEV] = {"DP_VDEV"}, 3320 [QDF_MODULE_ID_DP_CDP] = {"DP_CDP"}, 3321 [QDF_MODULE_ID_TSO] = {"TSO"}, 3322 [QDF_MODULE_ID_ME] = {"ME"}, 3323 [QDF_MODULE_ID_QWRAP] = {"QWRAP"}, 3324 [QDF_MODULE_ID_DBDC_REP] = {"DBDC_REP"}, 3325 [QDF_MODULE_ID_EXT_AP] = {"EXT_AP"}, 3326 [QDF_MODULE_ID_MLO] = {"MLO_MGR"}, 3327 [QDF_MODULE_ID_MGMT_RX_REO] = {"MGMT_RX_REO"}, 3328 [QDF_MODULE_ID_MLOIE] = {"MLOIE"}, 3329 [QDF_MODULE_ID_MBSS] = {"MBSS"}, 3330 [QDF_MODULE_ID_MON] = {"MONITOR"}, 3331 [QDF_MODULE_ID_AFC] = {"AFC"}, 3332 [QDF_MODULE_ID_TWT] = {"TWT"}, 3333 [QDF_MODULE_ID_SON] = {"SON"}, 3334 [QDF_MODULE_ID_WLAN_PRE_CAC] = {"PRE_CAC"}, 3335 [QDF_MODULE_ID_T2LM] = {"T2LM"}, 3336 [QDF_MODULE_ID_DP_SAWF] = {"DP_SAWF"}, 3337 [QDF_MODULE_ID_SCS] = {"SCS"}, 3338 [QDF_MODULE_ID_DP_UMAC_RESET] = {"UMAC_HW_RESET"}, 3339 [QDF_MODULE_ID_COAP] = {"COAP"}, 3340 [QDF_MODULE_ID_FTM_TIME_SYNC] = {"Time Sync"}, 3341 [QDF_MODULE_ID_WIFI_RADAR] = {"WIFI RADAR"}, 3342 [QDF_MODULE_ID_CDP] = {"CDP"}, 3343 [QDF_MODULE_ID_QMI] = {"QMI"}, 3344 [QDF_MODULE_ID_SOUNDING] = {"SOUNDING"}, 3345 [QDF_MODULE_ID_SAWF] = {"SAWF"}, 3346 [QDF_MODULE_ID_EPCS] = {"EPCS"}, 3347 [QDF_MODULE_ID_LL_SAP] = {"LL_SAP"}, 3348 [QDF_MODULE_ID_COHOSTED_BSS] = {"COHOSTED_BSS"}, 3349 [QDF_MODULE_ID_TELEMETRY_AGENT] = {"TELEMETRY_AGENT"}, 3350 [QDF_MODULE_ID_RF_PATH_SWITCH] = {"Dynamic RF Path Switch"}, 3351 [QDF_MODULE_ID_ANY] = {"ANY"}, 3352 }; 3353 qdf_export_symbol(g_qdf_category_name); 3354 3355 void qdf_trace_display(void) 3356 { 3357 QDF_MODULE_ID module_id; 3358 3359 pr_err(" 1)FATAL 2)ERROR 3)WARN 4)INFO 5)INFO_H 6)INFO_M 7)INFO_L 8)DEBUG\n"); 3360 for (module_id = 0; module_id < QDF_MODULE_ID_MAX; ++module_id) { 3361 pr_err("%2d)%s %s %s %s %s %s %s %s %s\n", 3362 (int)module_id, 3363 g_qdf_category_name[module_id].category_name_str, 3364 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3365 QDF_TRACE_LEVEL_FATAL) ? "X" : " ", 3366 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3367 QDF_TRACE_LEVEL_ERROR) ? "X" : " ", 3368 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3369 QDF_TRACE_LEVEL_WARN) ? "X" : " ", 3370 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3371 QDF_TRACE_LEVEL_INFO) ? "X" : " ", 3372 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3373 QDF_TRACE_LEVEL_INFO_HIGH) ? "X" : " ", 3374 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3375 QDF_TRACE_LEVEL_INFO_MED) ? "X" : " ", 3376 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3377 QDF_TRACE_LEVEL_INFO_LOW) ? "X" : " ", 3378 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3379 QDF_TRACE_LEVEL_DEBUG) ? "X" : " "); 3380 } 3381 } 3382 qdf_export_symbol(qdf_trace_display); 3383 3384 #ifdef WLAN_MAX_LOGS_PER_SEC 3385 static qdf_time_t __log_window_end; 3386 static qdf_atomic_t __log_window_count; 3387 uint32_t qdf_rl_print_count = WLAN_MAX_LOGS_PER_SEC; 3388 uint32_t qdf_rl_print_time = 1; 3389 uint32_t qdf_rl_print_suppressed; 3390 3391 bool qdf_detected_excessive_logging(void) 3392 { 3393 qdf_time_t now = qdf_system_ticks(); 3394 bool excessive_prints = false; 3395 3396 /* 3397 * If 'now' is more recent than the end of the window, reset. 3398 * 3399 * Note: This is not thread safe, and can result in more than one reset. 3400 * For our purposes, this is fine. 3401 */ 3402 if (!qdf_atomic_read(&__log_window_count)) { 3403 __log_window_end = now + (qdf_system_ticks_per_sec * qdf_rl_print_time); 3404 } else if (qdf_system_time_after(now, __log_window_end)) { 3405 __log_window_end = now + (qdf_system_ticks_per_sec * qdf_rl_print_time); 3406 qdf_atomic_set(&__log_window_count, 0); 3407 } 3408 3409 if (qdf_atomic_inc_return(&__log_window_count) > qdf_rl_print_count) 3410 excessive_prints = true; 3411 3412 return excessive_prints; 3413 } 3414 3415 void qdf_rl_print_count_set(uint32_t rl_print_count) 3416 { 3417 qdf_rl_print_count = rl_print_count; 3418 } 3419 3420 qdf_export_symbol(qdf_rl_print_count_set); 3421 3422 void qdf_rl_print_time_set(uint32_t rl_print_time) 3423 { 3424 qdf_rl_print_time = rl_print_time; 3425 } 3426 3427 qdf_export_symbol(qdf_rl_print_time_set); 3428 3429 void qdf_rl_print_suppressed_log(void) 3430 { 3431 if (qdf_rl_print_suppressed) { 3432 pr_err("QDF Ratelimiting: %d prints suppressed", 3433 qdf_rl_print_suppressed); 3434 qdf_rl_print_suppressed = 0; 3435 } 3436 } 3437 3438 void qdf_rl_print_suppressed_inc(void) 3439 { 3440 qdf_rl_print_suppressed++; 3441 } 3442 #else 3443 #define qdf_rl_print_suppressed_log() 3444 #define qdf_rl_print_suppressed_inc() 3445 #endif /* WLAN_MAX_LOGS_PER_SEC */ 3446 3447 #ifdef QDF_TRACE_PRINT_ENABLE 3448 static inline void print_to_console(char *str_buffer) 3449 { 3450 if (qdf_in_interrupt() && qdf_detected_excessive_logging()) { 3451 qdf_rl_print_suppressed_inc(); 3452 return; 3453 } 3454 qdf_rl_print_suppressed_log(); 3455 pr_err("%s\n", str_buffer); 3456 } 3457 #else 3458 3459 #define print_to_console(str) 3460 #endif 3461 3462 #ifdef MULTI_IF_NAME 3463 static const char *qdf_trace_wlan_modname(void) 3464 { 3465 return MULTI_IF_NAME; 3466 } 3467 #else 3468 static const char *qdf_trace_wlan_modname(void) 3469 { 3470 return "wlan"; 3471 } 3472 #endif 3473 3474 void qdf_trace_msg_cmn(unsigned int idx, 3475 QDF_MODULE_ID category, 3476 QDF_TRACE_LEVEL verbose, 3477 const char *str_format, va_list val) 3478 { 3479 char str_buffer[QDF_TRACE_BUFFER_SIZE]; 3480 int n; 3481 3482 /* Check if index passed is valid */ 3483 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 3484 pr_info("%s: Invalid index - %d\n", __func__, idx); 3485 return; 3486 } 3487 3488 /* Check if print control object is in use */ 3489 if (!print_ctrl_obj[idx].in_use) { 3490 pr_info("%s: Invalid print control object\n", __func__); 3491 return; 3492 } 3493 3494 /* Check if category passed is valid */ 3495 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) { 3496 vscnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, str_format, val); 3497 pr_info("%s: Invalid category: %d, log: %s\n", 3498 __func__, category, str_buffer); 3499 return; 3500 } 3501 3502 /* Check if verbose mask is valid */ 3503 if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) { 3504 vscnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, str_format, val); 3505 pr_info("%s: Invalid verbose level %d, log: %s\n", 3506 __func__, verbose, str_buffer); 3507 return; 3508 } 3509 3510 /* 3511 * Print the trace message when the desired verbose level is set in 3512 * the desired category for the print control object 3513 */ 3514 if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask & 3515 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) { 3516 static const char * const VERBOSE_STR[] = { 3517 [QDF_TRACE_LEVEL_NONE] = "", 3518 [QDF_TRACE_LEVEL_FATAL] = "F", 3519 [QDF_TRACE_LEVEL_ERROR] = "E", 3520 [QDF_TRACE_LEVEL_WARN] = "W", 3521 [QDF_TRACE_LEVEL_INFO] = "I", 3522 [QDF_TRACE_LEVEL_INFO_HIGH] = "IH", 3523 [QDF_TRACE_LEVEL_INFO_MED] = "IM", 3524 [QDF_TRACE_LEVEL_INFO_LOW] = "IL", 3525 [QDF_TRACE_LEVEL_DEBUG] = "D", 3526 [QDF_TRACE_LEVEL_TRACE] = "T", 3527 [QDF_TRACE_LEVEL_ALL] = "" }; 3528 3529 /* print the prefix string into the string buffer... */ 3530 n = scnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, 3531 "%s: [%d:%s:%s] ", qdf_trace_wlan_modname(), 3532 in_interrupt() ? 0 : current->pid, 3533 VERBOSE_STR[verbose], 3534 g_qdf_category_name[category].category_name_str); 3535 3536 /* print the formatted log message after the prefix string */ 3537 vscnprintf(str_buffer + n, QDF_TRACE_BUFFER_SIZE - n, 3538 str_format, val); 3539 #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE) 3540 wlan_log_to_user(verbose, (char *)str_buffer, 3541 strlen(str_buffer)); 3542 if (qdf_unlikely(qdf_log_dump_at_kernel_enable)) 3543 print_to_console(str_buffer); 3544 #else 3545 pr_err("%s\n", str_buffer); 3546 #endif 3547 } 3548 } 3549 qdf_export_symbol(qdf_trace_msg_cmn); 3550 3551 QDF_STATUS qdf_print_setup(void) 3552 { 3553 int i; 3554 3555 /* Loop through all print ctrl objects */ 3556 for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) { 3557 if (qdf_print_ctrl_cleanup(i)) 3558 return QDF_STATUS_E_FAILURE; 3559 } 3560 return QDF_STATUS_SUCCESS; 3561 } 3562 qdf_export_symbol(qdf_print_setup); 3563 3564 QDF_STATUS qdf_print_ctrl_cleanup(unsigned int idx) 3565 { 3566 int i = 0; 3567 3568 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 3569 pr_info("%s: Invalid index - %d\n", __func__, idx); 3570 return QDF_STATUS_E_FAILURE; 3571 } 3572 3573 /* Clean up the print control object corresponding to that index 3574 * If success, callee to change print control index to -1 3575 */ 3576 3577 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) { 3578 print_ctrl_obj[idx].cat_info[i].category_verbose_mask = 3579 QDF_TRACE_LEVEL_NONE; 3580 } 3581 print_ctrl_obj[idx].custom_print = NULL; 3582 print_ctrl_obj[idx].custom_ctxt = NULL; 3583 qdf_print_clean_node_flag(idx); 3584 print_ctrl_obj[idx].in_use = false; 3585 3586 return QDF_STATUS_SUCCESS; 3587 } 3588 qdf_export_symbol(qdf_print_ctrl_cleanup); 3589 3590 int qdf_print_ctrl_register(const struct category_info *cinfo, 3591 void *custom_print_handler, 3592 void *custom_ctx, 3593 const char *pctrl_name) 3594 { 3595 int idx = -1; 3596 int i = 0; 3597 3598 for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) { 3599 if (!print_ctrl_obj[i].in_use) { 3600 idx = i; 3601 break; 3602 } 3603 } 3604 3605 /* Callee to handle idx -1 appropriately */ 3606 if (idx == -1) { 3607 pr_info("%s: Allocation failed! No print control object free\n", 3608 __func__); 3609 return idx; 3610 } 3611 3612 print_ctrl_obj[idx].in_use = true; 3613 3614 /* 3615 * In case callee does not pass category info, 3616 * custom print handler, custom context and print control name, 3617 * we do not set any value here. Clean up for the print control 3618 * getting allocated would have taken care of initializing 3619 * default values. 3620 * 3621 * We need to only set in_use to 1 in such a case 3622 */ 3623 3624 if (pctrl_name) { 3625 qdf_str_lcopy(print_ctrl_obj[idx].name, pctrl_name, 3626 sizeof(print_ctrl_obj[idx].name)); 3627 } 3628 3629 if (custom_print_handler) 3630 print_ctrl_obj[idx].custom_print = custom_print_handler; 3631 3632 if (custom_ctx) 3633 print_ctrl_obj[idx].custom_ctxt = custom_ctx; 3634 3635 if (cinfo) { 3636 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) { 3637 if (cinfo[i].category_verbose_mask == 3638 QDF_TRACE_LEVEL_ALL) { 3639 print_ctrl_obj[idx].cat_info[i] 3640 .category_verbose_mask = 0xFFFF; 3641 } else if ((cinfo[i].category_verbose_mask == 3642 QDF_TRACE_LEVEL_NONE) || 3643 (cinfo[i].category_verbose_mask == 3644 QDF_TRACE_LEVEL_TO_MODULE_BITMASK( 3645 QDF_TRACE_LEVEL_NONE))) { 3646 print_ctrl_obj[idx].cat_info[i] 3647 .category_verbose_mask = 0; 3648 } else { 3649 print_ctrl_obj[idx].cat_info[i] 3650 .category_verbose_mask = 3651 cinfo[i].category_verbose_mask; 3652 } 3653 } 3654 } 3655 3656 return idx; 3657 } 3658 qdf_export_symbol(qdf_print_ctrl_register); 3659 3660 #ifdef QDF_TRACE_PRINT_ENABLE 3661 void qdf_shared_print_ctrl_cleanup(void) 3662 { 3663 qdf_print_ctrl_cleanup(qdf_pidx); 3664 } 3665 qdf_export_symbol(qdf_shared_print_ctrl_cleanup); 3666 3667 /* 3668 * Set this to invalid value to differentiate with user-provided 3669 * value. 3670 */ 3671 int qdf_dbg_mask = QDF_TRACE_LEVEL_MAX; 3672 qdf_export_symbol(qdf_dbg_mask); 3673 qdf_declare_param(qdf_dbg_mask, int); 3674 3675 /* 3676 * QDF can be passed parameters which indicate the 3677 * debug level for each module. 3678 * an array of string values are passed, each string hold the following form 3679 * 3680 * <module name string>=<integer debug level value> 3681 * 3682 * The array qdf_dbg_arr will hold these module-string=value strings 3683 * The variable qdf_dbg_arr_cnt will have the count of how many such 3684 * string values were passed. 3685 */ 3686 static char *qdf_dbg_arr[QDF_MODULE_ID_MAX]; 3687 static int qdf_dbg_arr_cnt; 3688 qdf_declare_param_array(qdf_dbg_arr, charp, &qdf_dbg_arr_cnt); 3689 3690 static uint16_t set_cumulative_verbose_mask(QDF_TRACE_LEVEL max_level) 3691 { 3692 uint16_t category_verbose_mask = 0; 3693 QDF_TRACE_LEVEL level; 3694 3695 for (level = QDF_TRACE_LEVEL_FATAL; level <= max_level; level++) { 3696 category_verbose_mask |= 3697 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level); 3698 } 3699 return category_verbose_mask; 3700 } 3701 3702 static QDF_MODULE_ID find_qdf_module_from_string(char *str) 3703 { 3704 QDF_MODULE_ID mod_id; 3705 3706 for (mod_id = 0; mod_id < QDF_MODULE_ID_MAX; mod_id++) { 3707 if (strcasecmp(str, 3708 g_qdf_category_name[mod_id].category_name_str) 3709 == 0) { 3710 break; 3711 } 3712 } 3713 return mod_id; 3714 } 3715 3716 static void process_qdf_dbg_arr_param(struct category_info *cinfo, 3717 int array_index) 3718 { 3719 char *mod_val_str, *mod_str, *val_str; 3720 unsigned long dbg_level; 3721 QDF_MODULE_ID mod_id; 3722 3723 mod_val_str = qdf_dbg_arr[array_index]; 3724 mod_str = strsep(&mod_val_str, "="); 3725 val_str = mod_val_str; 3726 if (!val_str) { 3727 pr_info("qdf_dbg_arr: %s not in the <mod>=<val> form\n", 3728 mod_str); 3729 return; 3730 } 3731 3732 mod_id = find_qdf_module_from_string(mod_str); 3733 if (mod_id >= QDF_MODULE_ID_MAX) { 3734 pr_info("ERROR!!Module name %s not in the list of modules\n", 3735 mod_str); 3736 return; 3737 } 3738 3739 if (kstrtol(val_str, 10, &dbg_level) < 0) { 3740 pr_info("ERROR!!Invalid debug level for module: %s\n", 3741 mod_str); 3742 return; 3743 } 3744 3745 if (dbg_level >= QDF_TRACE_LEVEL_MAX) { 3746 pr_info("ERROR!!Debug level for %s too high", mod_str); 3747 pr_info("max: %d given %lu\n", QDF_TRACE_LEVEL_MAX, 3748 dbg_level); 3749 return; 3750 } 3751 3752 pr_info("User passed setting module %s(%d) to level %lu\n", 3753 mod_str, 3754 mod_id, 3755 dbg_level); 3756 cinfo[mod_id].category_verbose_mask = 3757 set_cumulative_verbose_mask((QDF_TRACE_LEVEL)dbg_level); 3758 } 3759 3760 static void set_default_trace_levels(struct category_info *cinfo) 3761 { 3762 int i; 3763 static QDF_TRACE_LEVEL module_trace_default_level[QDF_MODULE_ID_MAX] = { 3764 [QDF_MODULE_ID_TDLS] = QDF_TRACE_LEVEL_NONE, 3765 [QDF_MODULE_ID_ACS] = QDF_TRACE_LEVEL_NONE, 3766 [QDF_MODULE_ID_SCAN_SM] = QDF_TRACE_LEVEL_NONE, 3767 [QDF_MODULE_ID_SCANENTRY] = QDF_TRACE_LEVEL_NONE, 3768 [QDF_MODULE_ID_WDS] = QDF_TRACE_LEVEL_NONE, 3769 [QDF_MODULE_ID_ACTION] = QDF_TRACE_LEVEL_NONE, 3770 [QDF_MODULE_ID_ROAM] = QDF_TRACE_LEVEL_NONE, 3771 [QDF_MODULE_ID_INACT] = QDF_TRACE_LEVEL_NONE, 3772 [QDF_MODULE_ID_DOTH] = QDF_TRACE_LEVEL_NONE, 3773 [QDF_MODULE_ID_IQUE] = QDF_TRACE_LEVEL_NONE, 3774 [QDF_MODULE_ID_WME] = QDF_TRACE_LEVEL_NONE, 3775 [QDF_MODULE_ID_ACL] = QDF_TRACE_LEVEL_NONE, 3776 [QDF_MODULE_ID_WPA] = QDF_TRACE_LEVEL_NONE, 3777 [QDF_MODULE_ID_RADKEYS] = QDF_TRACE_LEVEL_NONE, 3778 [QDF_MODULE_ID_RADDUMP] = QDF_TRACE_LEVEL_NONE, 3779 [QDF_MODULE_ID_RADIUS] = QDF_TRACE_LEVEL_NONE, 3780 [QDF_MODULE_ID_DOT1XSM] = QDF_TRACE_LEVEL_NONE, 3781 [QDF_MODULE_ID_DOT1X] = QDF_TRACE_LEVEL_NONE, 3782 [QDF_MODULE_ID_POWER] = QDF_TRACE_LEVEL_NONE, 3783 [QDF_MODULE_ID_STATE] = QDF_TRACE_LEVEL_NONE, 3784 [QDF_MODULE_ID_OUTPUT] = QDF_TRACE_LEVEL_NONE, 3785 [QDF_MODULE_ID_SCAN] = QDF_TRACE_LEVEL_ERROR, 3786 [QDF_MODULE_ID_AUTH] = QDF_TRACE_LEVEL_NONE, 3787 [QDF_MODULE_ID_ASSOC] = QDF_TRACE_LEVEL_NONE, 3788 [QDF_MODULE_ID_NODE] = QDF_TRACE_LEVEL_NONE, 3789 [QDF_MODULE_ID_ELEMID] = QDF_TRACE_LEVEL_NONE, 3790 [QDF_MODULE_ID_XRATE] = QDF_TRACE_LEVEL_NONE, 3791 [QDF_MODULE_ID_INPUT] = QDF_TRACE_LEVEL_NONE, 3792 [QDF_MODULE_ID_CRYPTO] = QDF_TRACE_LEVEL_NONE, 3793 [QDF_MODULE_ID_DUMPPKTS] = QDF_TRACE_LEVEL_NONE, 3794 [QDF_MODULE_ID_DEBUG] = QDF_TRACE_LEVEL_NONE, 3795 [QDF_MODULE_ID_MLME] = QDF_TRACE_LEVEL_ERROR, 3796 [QDF_MODULE_ID_RRM] = QDF_TRACE_LEVEL_NONE, 3797 [QDF_MODULE_ID_WNM] = QDF_TRACE_LEVEL_NONE, 3798 [QDF_MODULE_ID_P2P_PROT] = QDF_TRACE_LEVEL_NONE, 3799 [QDF_MODULE_ID_PROXYARP] = QDF_TRACE_LEVEL_NONE, 3800 [QDF_MODULE_ID_L2TIF] = QDF_TRACE_LEVEL_NONE, 3801 [QDF_MODULE_ID_WIFIPOS] = QDF_TRACE_LEVEL_NONE, 3802 [QDF_MODULE_ID_WRAP] = QDF_TRACE_LEVEL_NONE, 3803 [QDF_MODULE_ID_DFS] = QDF_TRACE_LEVEL_NONE, 3804 [QDF_MODULE_ID_ATF] = QDF_TRACE_LEVEL_ERROR, 3805 [QDF_MODULE_ID_SPLITMAC] = QDF_TRACE_LEVEL_NONE, 3806 [QDF_MODULE_ID_IOCTL] = QDF_TRACE_LEVEL_NONE, 3807 [QDF_MODULE_ID_NAC] = QDF_TRACE_LEVEL_NONE, 3808 [QDF_MODULE_ID_MESH] = QDF_TRACE_LEVEL_NONE, 3809 [QDF_MODULE_ID_MBO] = QDF_TRACE_LEVEL_NONE, 3810 [QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = QDF_TRACE_LEVEL_NONE, 3811 [QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = QDF_TRACE_LEVEL_NONE, 3812 [QDF_MODULE_ID_TLSHIM] = QDF_TRACE_LEVEL_NONE, 3813 [QDF_MODULE_ID_WMI] = QDF_TRACE_LEVEL_ERROR, 3814 [QDF_MODULE_ID_HTT] = QDF_TRACE_LEVEL_NONE, 3815 [QDF_MODULE_ID_HDD] = QDF_TRACE_LEVEL_NONE, 3816 [QDF_MODULE_ID_SME] = QDF_TRACE_LEVEL_NONE, 3817 [QDF_MODULE_ID_PE] = QDF_TRACE_LEVEL_NONE, 3818 [QDF_MODULE_ID_WMA] = QDF_TRACE_LEVEL_NONE, 3819 [QDF_MODULE_ID_SYS] = QDF_TRACE_LEVEL_NONE, 3820 [QDF_MODULE_ID_QDF] = QDF_TRACE_LEVEL_ERROR, 3821 [QDF_MODULE_ID_SAP] = QDF_TRACE_LEVEL_NONE, 3822 [QDF_MODULE_ID_HDD_SOFTAP] = QDF_TRACE_LEVEL_NONE, 3823 [QDF_MODULE_ID_HDD_DATA] = QDF_TRACE_LEVEL_NONE, 3824 [QDF_MODULE_ID_HDD_SAP_DATA] = QDF_TRACE_LEVEL_NONE, 3825 [QDF_MODULE_ID_HIF] = QDF_TRACE_LEVEL_ERROR, 3826 [QDF_MODULE_ID_HTC] = QDF_TRACE_LEVEL_NONE, 3827 [QDF_MODULE_ID_TXRX] = QDF_TRACE_LEVEL_NONE, 3828 [QDF_MODULE_ID_QDF_DEVICE] = QDF_TRACE_LEVEL_NONE, 3829 [QDF_MODULE_ID_CFG] = QDF_TRACE_LEVEL_NONE, 3830 [QDF_MODULE_ID_BMI] = QDF_TRACE_LEVEL_NONE, 3831 [QDF_MODULE_ID_EPPING] = QDF_TRACE_LEVEL_NONE, 3832 [QDF_MODULE_ID_QVIT] = QDF_TRACE_LEVEL_NONE, 3833 [QDF_MODULE_ID_DP] = QDF_TRACE_LEVEL_FATAL, 3834 [QDF_MODULE_ID_HAL] = QDF_TRACE_LEVEL_NONE, 3835 [QDF_MODULE_ID_SOC] = QDF_TRACE_LEVEL_NONE, 3836 [QDF_MODULE_ID_OS_IF] = QDF_TRACE_LEVEL_NONE, 3837 [QDF_MODULE_ID_TARGET_IF] = QDF_TRACE_LEVEL_INFO, 3838 [QDF_MODULE_ID_SCHEDULER] = QDF_TRACE_LEVEL_FATAL, 3839 [QDF_MODULE_ID_MGMT_TXRX] = QDF_TRACE_LEVEL_NONE, 3840 [QDF_MODULE_ID_SERIALIZATION] = QDF_TRACE_LEVEL_ERROR, 3841 [QDF_MODULE_ID_PMO] = QDF_TRACE_LEVEL_NONE, 3842 [QDF_MODULE_ID_P2P] = QDF_TRACE_LEVEL_NONE, 3843 [QDF_MODULE_ID_POLICY_MGR] = QDF_TRACE_LEVEL_NONE, 3844 [QDF_MODULE_ID_CONFIG] = QDF_TRACE_LEVEL_ERROR, 3845 [QDF_MODULE_ID_REGULATORY] = QDF_TRACE_LEVEL_NONE, 3846 [QDF_MODULE_ID_SA_API] = QDF_TRACE_LEVEL_NONE, 3847 [QDF_MODULE_ID_NAN] = QDF_TRACE_LEVEL_NONE, 3848 [QDF_MODULE_ID_OFFCHAN_TXRX] = QDF_TRACE_LEVEL_NONE, 3849 [QDF_MODULE_ID_SON] = QDF_TRACE_LEVEL_NONE, 3850 [QDF_MODULE_ID_SPECTRAL] = QDF_TRACE_LEVEL_ERROR, 3851 [QDF_MODULE_ID_OBJ_MGR] = QDF_TRACE_LEVEL_FATAL, 3852 [QDF_MODULE_ID_NSS] = QDF_TRACE_LEVEL_ERROR, 3853 [QDF_MODULE_ID_ROAM_DEBUG] = QDF_TRACE_LEVEL_ERROR, 3854 [QDF_MODULE_ID_CDP] = QDF_TRACE_LEVEL_NONE, 3855 [QDF_MODULE_ID_DIRECT_BUF_RX] = QDF_TRACE_LEVEL_ERROR, 3856 [QDF_MODULE_ID_DISA] = QDF_TRACE_LEVEL_NONE, 3857 [QDF_MODULE_ID_GREEN_AP] = QDF_TRACE_LEVEL_ERROR, 3858 [QDF_MODULE_ID_FTM] = QDF_TRACE_LEVEL_ERROR, 3859 [QDF_MODULE_ID_FD] = QDF_TRACE_LEVEL_ERROR, 3860 [QDF_MODULE_ID_OCB] = QDF_TRACE_LEVEL_ERROR, 3861 [QDF_MODULE_ID_IPA] = QDF_TRACE_LEVEL_NONE, 3862 [QDF_MODULE_ID_ACTION_OUI] = QDF_TRACE_LEVEL_NONE, 3863 [QDF_MODULE_ID_CP_STATS] = QDF_TRACE_LEVEL_ERROR, 3864 [QDF_MODULE_ID_DCS] = QDF_TRACE_LEVEL_ERROR, 3865 [QDF_MODULE_ID_MBSSIE] = QDF_TRACE_LEVEL_INFO, 3866 [QDF_MODULE_ID_FWOL] = QDF_TRACE_LEVEL_NONE, 3867 [QDF_MODULE_ID_SM_ENGINE] = QDF_TRACE_LEVEL_ERROR, 3868 [QDF_MODULE_ID_CMN_MLME] = QDF_TRACE_LEVEL_INFO, 3869 [QDF_MODULE_ID_BSSCOLOR] = QDF_TRACE_LEVEL_ERROR, 3870 [QDF_MODULE_ID_CFR] = QDF_TRACE_LEVEL_ERROR, 3871 [QDF_MODULE_ID_DP_TX_CAPTURE] = QDF_TRACE_LEVEL_FATAL, 3872 [QDF_MODULE_ID_INTEROP_ISSUES_AP] = QDF_TRACE_LEVEL_NONE, 3873 [QDF_MODULE_ID_DENYLIST_MGR] = QDF_TRACE_LEVEL_NONE, 3874 [QDF_MODULE_ID_QLD] = QDF_TRACE_LEVEL_ERROR, 3875 [QDF_MODULE_ID_DYNAMIC_MODE_CHG] = QDF_TRACE_LEVEL_INFO, 3876 [QDF_MODULE_ID_COEX] = QDF_TRACE_LEVEL_ERROR, 3877 [QDF_MODULE_ID_MON_FILTER] = QDF_TRACE_LEVEL_INFO, 3878 [QDF_MODULE_ID_PKT_CAPTURE] = QDF_TRACE_LEVEL_NONE, 3879 [QDF_MODULE_ID_RPTR] = QDF_TRACE_LEVEL_INFO, 3880 [QDF_MODULE_ID_6GHZ] = QDF_TRACE_LEVEL_ERROR, 3881 [QDF_MODULE_ID_IOT_SIM] = QDF_TRACE_LEVEL_ERROR, 3882 [QDF_MODULE_ID_MSCS] = QDF_TRACE_LEVEL_INFO, 3883 [QDF_MODULE_ID_GPIO] = QDF_TRACE_LEVEL_NONE, 3884 [QDF_MODULE_ID_IFMGR] = QDF_TRACE_LEVEL_ERROR, 3885 [QDF_MODULE_ID_DIAG] = QDF_TRACE_LEVEL_ERROR, 3886 [QDF_MODULE_ID_DP_INIT] = QDF_TRACE_LEVEL_FATAL, 3887 [QDF_MODULE_ID_DP_TX] = QDF_TRACE_LEVEL_FATAL, 3888 [QDF_MODULE_ID_DP_RX] = QDF_TRACE_LEVEL_FATAL, 3889 [QDF_MODULE_ID_DP_STATS] = QDF_TRACE_LEVEL_FATAL, 3890 [QDF_MODULE_ID_DP_HTT] = QDF_TRACE_LEVEL_FATAL, 3891 [QDF_MODULE_ID_DP_PEER] = QDF_TRACE_LEVEL_FATAL, 3892 [QDF_MODULE_ID_DP_RX_ERROR] = QDF_TRACE_LEVEL_FATAL, 3893 [QDF_MODULE_ID_DP_HTT_TX_STATS] = QDF_TRACE_LEVEL_FATAL, 3894 [QDF_MODULE_ID_DP_RX_MON_STATUS] = QDF_TRACE_LEVEL_FATAL, 3895 [QDF_MODULE_ID_DP_RX_MON_DEST] = QDF_TRACE_LEVEL_FATAL, 3896 [QDF_MODULE_ID_DP_REO] = QDF_TRACE_LEVEL_FATAL, 3897 [QDF_MODULE_ID_DP_TX_COMP] = QDF_TRACE_LEVEL_FATAL, 3898 [QDF_MODULE_ID_DP_VDEV] = QDF_TRACE_LEVEL_FATAL, 3899 [QDF_MODULE_ID_DP_CDP] = QDF_TRACE_LEVEL_FATAL, 3900 [QDF_MODULE_ID_TSO] = QDF_TRACE_LEVEL_FATAL, 3901 [QDF_MODULE_ID_ME] = QDF_TRACE_LEVEL_INFO, 3902 [QDF_MODULE_ID_QWRAP] = QDF_TRACE_LEVEL_FATAL, 3903 [QDF_MODULE_ID_DBDC_REP] = QDF_TRACE_LEVEL_FATAL, 3904 [QDF_MODULE_ID_EXT_AP] = QDF_TRACE_LEVEL_NONE, 3905 [QDF_MODULE_ID_MLO] = QDF_TRACE_LEVEL_INFO, 3906 [QDF_MODULE_ID_MLOIE] = QDF_TRACE_LEVEL_INFO, 3907 [QDF_MODULE_ID_MBSS] = QDF_TRACE_LEVEL_ERROR, 3908 [QDF_MODULE_ID_MON] = QDF_TRACE_LEVEL_ERROR, 3909 [QDF_MODULE_ID_MGMT_RX_REO] = QDF_TRACE_LEVEL_WARN, 3910 [QDF_MODULE_ID_TWT] = QDF_TRACE_LEVEL_ERROR, 3911 [QDF_MODULE_ID_WLAN_PRE_CAC] = QDF_TRACE_LEVEL_ERROR, 3912 [QDF_MODULE_ID_T2LM] = QDF_TRACE_LEVEL_ERROR, 3913 [QDF_MODULE_ID_DP_SAWF] = QDF_TRACE_LEVEL_ERROR, 3914 [QDF_MODULE_ID_SCS] = QDF_TRACE_LEVEL_ERROR, 3915 [QDF_MODULE_ID_DP_UMAC_RESET] = QDF_TRACE_LEVEL_ERROR, 3916 [QDF_MODULE_ID_COAP] = QDF_TRACE_LEVEL_ERROR, 3917 [QDF_MODULE_ID_FTM_TIME_SYNC] = QDF_TRACE_LEVEL_NONE, 3918 [QDF_MODULE_ID_AFC] = QDF_TRACE_LEVEL_NONE, 3919 [QDF_MODULE_ID_WIFI_RADAR] = QDF_TRACE_LEVEL_NONE, 3920 [QDF_MODULE_ID_TARGET] = QDF_TRACE_LEVEL_NONE, 3921 [QDF_MODULE_ID_QMI] = QDF_TRACE_LEVEL_ERROR, 3922 [QDF_MODULE_ID_SOUNDING] = QDF_TRACE_LEVEL_ERROR, 3923 [QDF_MODULE_ID_SAWF] = QDF_TRACE_LEVEL_INFO, 3924 [QDF_MODULE_ID_EPCS] = QDF_TRACE_LEVEL_INFO, 3925 [QDF_MODULE_ID_LL_SAP] = QDF_TRACE_LEVEL_NONE, 3926 [QDF_MODULE_ID_COHOSTED_BSS] = QDF_TRACE_LEVEL_INFO, 3927 [QDF_MODULE_ID_TELEMETRY_AGENT] = QDF_TRACE_LEVEL_ERROR, 3928 [QDF_MODULE_ID_RF_PATH_SWITCH] = QDF_TRACE_LEVEL_INFO, 3929 [QDF_MODULE_ID_ANY] = QDF_TRACE_LEVEL_INFO, 3930 }; 3931 3932 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) { 3933 cinfo[i].category_verbose_mask = set_cumulative_verbose_mask( 3934 module_trace_default_level[i]); 3935 } 3936 } 3937 3938 void qdf_shared_print_ctrl_init(void) 3939 { 3940 int i; 3941 struct category_info cinfo[MAX_SUPPORTED_CATEGORY]; 3942 3943 set_default_trace_levels(cinfo); 3944 3945 /* 3946 * User specified across-module single debug level 3947 */ 3948 if ((qdf_dbg_mask >= 0) && (qdf_dbg_mask < QDF_TRACE_LEVEL_MAX)) { 3949 pr_info("User specified module debug level of %d\n", 3950 qdf_dbg_mask); 3951 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) { 3952 cinfo[i].category_verbose_mask = 3953 set_cumulative_verbose_mask(qdf_dbg_mask); 3954 } 3955 } else if (qdf_dbg_mask != QDF_TRACE_LEVEL_MAX) { 3956 pr_info("qdf_dbg_mask value is invalid\n"); 3957 pr_info("Using the default module debug levels instead\n"); 3958 } 3959 3960 /* 3961 * Module ID-Level specified as array during module load 3962 */ 3963 for (i = 0; i < qdf_dbg_arr_cnt; i++) { 3964 process_qdf_dbg_arr_param(cinfo, i); 3965 } 3966 qdf_pidx = qdf_print_ctrl_register(cinfo, NULL, NULL, 3967 "LOG_SHARED_OBJ"); 3968 } 3969 qdf_export_symbol(qdf_shared_print_ctrl_init); 3970 #endif 3971 3972 #ifdef QCA_WIFI_MODULE_PARAMS_FROM_INI 3973 QDF_STATUS qdf_module_param_handler(void *context, const char *str_param, 3974 const char *str) 3975 { 3976 QDF_STATUS status = QDF_STATUS_E_FAILURE; 3977 uint16_t param = 0; 3978 uint32_t flush_tmr_prd; 3979 bool dump_flag; 3980 3981 while (param < QDF_PARAM_MAX) { 3982 if (qdf_str_eq(qdf_module_param[param], str_param)) { 3983 switch (param) { 3984 case MEM_DEBUG_DISABLED: 3985 status = qdf_mem_debug_disabled_config_set(str); 3986 break; 3987 case QDF_DBG_MASK: 3988 status = qdf_int32_parse(str, &qdf_dbg_mask); 3989 break; 3990 case PREALLOC_DISABLED: 3991 status = qdf_prealloc_disabled_config_set(str); 3992 break; 3993 case QDF_LOG_DUMP_AT_KERNEL_ENABLE: 3994 status = qdf_bool_parse(str, &dump_flag); 3995 qdf_log_dump_at_kernel_enable = dump_flag; 3996 break; 3997 case QDF_DBG_ARR: 3998 qdf_dbg_arr[0] = (char *)str; 3999 status = QDF_STATUS_SUCCESS; 4000 break; 4001 case QDF_LOG_FLUSH_TIMER_PERIOD: 4002 status = qdf_uint32_parse(str, &flush_tmr_prd); 4003 qdf_log_flush_timer_period = flush_tmr_prd; 4004 break; 4005 default: 4006 break; 4007 } 4008 return status; 4009 } 4010 param++; 4011 } 4012 4013 return QDF_STATUS_SUCCESS; 4014 } 4015 4016 void qdf_initialize_module_param_from_ini(void) 4017 { 4018 QDF_STATUS status; 4019 char *path = QDF_WIFI_MODULE_PARAMS_FILE; 4020 4021 status = qdf_ini_parse(path, NULL, qdf_module_param_handler, NULL); 4022 if (QDF_IS_STATUS_ERROR(status)) { 4023 QDF_TRACE_ERROR(QDF_MODULE_ID_QDF, 4024 "Failed to parse *.ini file @ %s; status:%d", 4025 path, status); 4026 return; 4027 } 4028 } 4029 #endif 4030 4031 QDF_STATUS qdf_print_set_category_verbose(unsigned int idx, 4032 QDF_MODULE_ID category, 4033 QDF_TRACE_LEVEL verbose, 4034 bool is_set) 4035 { 4036 /* Check if index passed is valid */ 4037 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 4038 pr_err("%s: Invalid index - %d\n", __func__, idx); 4039 return QDF_STATUS_E_FAILURE; 4040 } 4041 4042 /* Check if print control object is in use */ 4043 if (!print_ctrl_obj[idx].in_use) { 4044 pr_err("%s: Invalid print control object\n", __func__); 4045 return QDF_STATUS_E_FAILURE; 4046 } 4047 4048 /* Check if category passed is valid */ 4049 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) { 4050 pr_err("%s: Invalid category: %d\n", __func__, category); 4051 return QDF_STATUS_E_FAILURE; 4052 } 4053 4054 /* Check if verbose mask is valid */ 4055 if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) { 4056 pr_err("%s: Invalid verbose level %d\n", __func__, verbose); 4057 return QDF_STATUS_E_FAILURE; 4058 } 4059 4060 if (verbose == QDF_TRACE_LEVEL_ALL) { 4061 print_ctrl_obj[idx].cat_info[category].category_verbose_mask = 4062 0xFFFF; 4063 return QDF_STATUS_SUCCESS; 4064 } 4065 4066 if (verbose == QDF_TRACE_LEVEL_NONE) { 4067 print_ctrl_obj[idx].cat_info[category].category_verbose_mask = 4068 QDF_TRACE_LEVEL_NONE; 4069 return QDF_STATUS_SUCCESS; 4070 } 4071 4072 if (!is_set) { 4073 if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask 4074 & QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) { 4075 print_ctrl_obj[idx].cat_info[category] 4076 .category_verbose_mask &= 4077 ~QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose); 4078 } 4079 } else { 4080 print_ctrl_obj[idx].cat_info[category].category_verbose_mask |= 4081 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose); 4082 } 4083 4084 pr_debug("%s: Print control object %d, Category %d, Verbose level %d\n", 4085 __func__, 4086 idx, 4087 category, 4088 print_ctrl_obj[idx].cat_info[category].category_verbose_mask); 4089 4090 return QDF_STATUS_SUCCESS; 4091 } 4092 qdf_export_symbol(qdf_print_set_category_verbose); 4093 4094 void qdf_log_dump_at_kernel_level(bool enable) 4095 { 4096 if (qdf_log_dump_at_kernel_enable == enable) { 4097 QDF_TRACE_INFO(QDF_MODULE_ID_QDF, 4098 "qdf_log_dump_at_kernel_enable is already %d\n", 4099 enable); 4100 } 4101 qdf_log_dump_at_kernel_enable = enable; 4102 } 4103 4104 qdf_export_symbol(qdf_log_dump_at_kernel_level); 4105 4106 QDF_TRACE_LEVEL qdf_print_get_category_verbose(unsigned int idx, 4107 QDF_MODULE_ID category) 4108 { 4109 /* Check if index passed is valid */ 4110 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 4111 pr_info("%s: Invalid index - %d\n", __func__, idx); 4112 return false; 4113 } 4114 4115 /* Check if print control object is in use */ 4116 if (!print_ctrl_obj[idx].in_use) { 4117 pr_info("%s: Invalid print control object\n", __func__); 4118 return false; 4119 } 4120 4121 /* Check if category passed is valid */ 4122 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) { 4123 pr_info("%s: Invalid category: %d\n", __func__, category); 4124 return false; 4125 } 4126 4127 return print_ctrl_obj[idx].cat_info[category].category_verbose_mask; 4128 } 4129 4130 qdf_export_symbol(qdf_print_get_category_verbose); 4131 4132 bool qdf_print_is_category_enabled(unsigned int idx, QDF_MODULE_ID category) 4133 { 4134 QDF_TRACE_LEVEL verbose_mask; 4135 4136 verbose_mask = qdf_print_get_category_verbose(idx, category); 4137 4138 if (verbose_mask == QDF_TRACE_LEVEL_NONE) 4139 return false; 4140 else 4141 return true; 4142 } 4143 4144 qdf_export_symbol(qdf_print_is_category_enabled); 4145 4146 bool qdf_print_is_verbose_enabled(unsigned int idx, QDF_MODULE_ID category, 4147 QDF_TRACE_LEVEL verbose) 4148 { 4149 bool verbose_enabled = false; 4150 4151 /* Check if index passed is valid */ 4152 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 4153 pr_info("%s: Invalid index - %d\n", __func__, idx); 4154 return verbose_enabled; 4155 } 4156 4157 /* Check if print control object is in use */ 4158 if (!print_ctrl_obj[idx].in_use) { 4159 pr_info("%s: Invalid print control object\n", __func__); 4160 return verbose_enabled; 4161 } 4162 4163 /* Check if category passed is valid */ 4164 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) { 4165 pr_info("%s: Invalid category: %d\n", __func__, category); 4166 return verbose_enabled; 4167 } 4168 4169 if ((verbose == QDF_TRACE_LEVEL_NONE) || 4170 (verbose >= QDF_TRACE_LEVEL_MAX)) { 4171 verbose_enabled = false; 4172 } else if (verbose == QDF_TRACE_LEVEL_ALL) { 4173 if (print_ctrl_obj[idx].cat_info[category] 4174 .category_verbose_mask == 0xFFFF) 4175 verbose_enabled = true; 4176 } else { 4177 verbose_enabled = 4178 (print_ctrl_obj[idx].cat_info[category].category_verbose_mask & 4179 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) ? true : false; 4180 } 4181 4182 return verbose_enabled; 4183 } 4184 qdf_export_symbol(qdf_print_is_verbose_enabled); 4185 4186 #ifdef DBG_LVL_MAC_FILTERING 4187 4188 QDF_STATUS qdf_print_set_node_flag(unsigned int idx, uint8_t enable) 4189 { 4190 /* Check if index passed is valid */ 4191 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 4192 pr_info("%s: Invalid index - %d\n", __func__, idx); 4193 return QDF_STATUS_E_FAILURE; 4194 } 4195 4196 /* Check if print control object is in use */ 4197 if (!print_ctrl_obj[idx].in_use) { 4198 pr_info("%s: Invalid print control object\n", __func__); 4199 return QDF_STATUS_E_FAILURE; 4200 } 4201 4202 if (enable > 1) { 4203 pr_info("%s: Incorrect input: Use 1 or 0 to enable or disable\n", 4204 __func__); 4205 return QDF_STATUS_E_FAILURE; 4206 } 4207 4208 print_ctrl_obj[idx].dbglvlmac_on = enable; 4209 pr_info("%s: DbgLVLmac feature %s\n", 4210 __func__, 4211 ((enable) ? "enabled" : "disabled")); 4212 4213 return QDF_STATUS_SUCCESS; 4214 } 4215 qdf_export_symbol(qdf_print_set_node_flag); 4216 4217 bool qdf_print_get_node_flag(unsigned int idx) 4218 { 4219 bool node_flag = false; 4220 4221 /* Check if index passed is valid */ 4222 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 4223 pr_info("%s: Invalid index - %d\n", __func__, idx); 4224 return node_flag; 4225 } 4226 4227 /* Check if print control object is in use */ 4228 if (!print_ctrl_obj[idx].in_use) { 4229 pr_info("%s: Invalid print control object\n", __func__); 4230 return node_flag; 4231 } 4232 4233 if (print_ctrl_obj[idx].dbglvlmac_on) 4234 node_flag = true; 4235 4236 return node_flag; 4237 } 4238 qdf_export_symbol(qdf_print_get_node_flag); 4239 4240 void qdf_print_clean_node_flag(unsigned int idx) 4241 { 4242 /* Disable dbglvlmac_on during cleanup */ 4243 print_ctrl_obj[idx].dbglvlmac_on = 0; 4244 } 4245 4246 #else 4247 4248 void qdf_print_clean_node_flag(unsigned int idx) 4249 { 4250 /* No operation in case of no support for DBG_LVL_MAC_FILTERING */ 4251 return; 4252 } 4253 #endif 4254 4255 void QDF_PRINT_INFO(unsigned int idx, QDF_MODULE_ID module, 4256 QDF_TRACE_LEVEL level, 4257 char *str_format, ...) 4258 { 4259 va_list args; 4260 4261 /* Generic wrapper API will compile qdf_vprint in order to 4262 * log the message. Once QDF converged debug framework is in 4263 * place, this will be changed to adapt to the framework, compiling 4264 * call to converged tracing API 4265 */ 4266 va_start(args, str_format); 4267 qdf_vprint(str_format, args); 4268 va_end(args); 4269 } 4270 qdf_export_symbol(QDF_PRINT_INFO); 4271 4272 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE 4273 void qdf_logging_init(void) 4274 { 4275 wlan_logging_sock_init_svc(); 4276 nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY); 4277 wlan_logging_notifier_init(qdf_log_dump_at_kernel_enable); 4278 wlan_logging_set_flush_timer(qdf_log_flush_timer_period); 4279 } 4280 4281 void qdf_logging_exit(void) 4282 { 4283 wlan_logging_notifier_deinit(qdf_log_dump_at_kernel_enable); 4284 nl_srv_exit(); 4285 wlan_logging_sock_deinit_svc(); 4286 } 4287 4288 int qdf_logging_set_flush_timer(uint32_t milliseconds) 4289 { 4290 if (wlan_logging_set_flush_timer(milliseconds) == 0) 4291 return QDF_STATUS_SUCCESS; 4292 else 4293 return QDF_STATUS_E_FAILURE; 4294 } 4295 4296 void qdf_logging_flush_logs(void) 4297 { 4298 wlan_flush_host_logs_for_fatal(); 4299 } 4300 4301 #else 4302 void qdf_logging_init(void) 4303 { 4304 nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY); 4305 } 4306 4307 void qdf_logging_exit(void) 4308 { 4309 nl_srv_exit(); 4310 } 4311 4312 int qdf_logging_set_flush_timer(uint32_t milliseconds) 4313 { 4314 return QDF_STATUS_E_FAILURE; 4315 } 4316 4317 void qdf_logging_flush_logs(void) 4318 { 4319 } 4320 #endif 4321 4322 qdf_export_symbol(qdf_logging_set_flush_timer); 4323 qdf_export_symbol(qdf_logging_flush_logs); 4324 4325 #ifdef CONFIG_KALLSYMS 4326 inline int qdf_sprint_symbol(char *buffer, void *addr) 4327 { 4328 return sprint_symbol(buffer, (unsigned long)addr); 4329 } 4330 #else 4331 int qdf_sprint_symbol(char *buffer, void *addr) 4332 { 4333 if (!buffer) 4334 return 0; 4335 4336 buffer[0] = '\0'; 4337 return 1; 4338 } 4339 #endif 4340 qdf_export_symbol(qdf_sprint_symbol); 4341 4342 void qdf_set_pidx(int pidx) 4343 { 4344 qdf_pidx = pidx; 4345 } 4346 qdf_export_symbol(qdf_set_pidx); 4347 4348 int qdf_get_pidx(void) 4349 { 4350 return qdf_pidx; 4351 } 4352 qdf_export_symbol(qdf_get_pidx); 4353 4354 #ifdef PANIC_ON_BUG 4355 #ifdef CONFIG_SLUB_DEBUG 4356 void __qdf_bug(void) 4357 { 4358 BUG(); 4359 } 4360 qdf_export_symbol(__qdf_bug); 4361 #endif /* CONFIG_SLUB_DEBUG */ 4362 #endif /* PANIC_ON_BUG */ 4363 4364 #ifdef WLAN_QCOM_VA_MINIDUMP 4365 static bool qdf_va_md_initialized; 4366 static qdf_list_t qdf_va_md_list; 4367 static qdf_spinlock_t qdf_va_md_list_lock; 4368 #define QDF_MINIDUMP_LIST_SIZE 128 4369 4370 struct qdf_va_md_entry { 4371 qdf_list_node_t node; 4372 struct va_md_entry data; 4373 }; 4374 4375 static int qdf_va_md_notif_handler(struct notifier_block *this, 4376 unsigned long event, void *ptr) 4377 { 4378 struct qdf_va_md_entry *entry; 4379 struct qdf_va_md_entry *next; 4380 4381 qdf_spin_lock_irqsave(&qdf_va_md_list_lock); 4382 qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) { 4383 qcom_va_md_add_region(&entry->data); 4384 } 4385 4386 qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock); 4387 return NOTIFY_OK; 4388 } 4389 4390 static struct notifier_block qdf_va_md_notif_blk = { 4391 .notifier_call = qdf_va_md_notif_handler, 4392 .priority = INT_MAX, 4393 }; 4394 4395 void __qdf_minidump_init(void) 4396 { 4397 int ret; 4398 4399 if (qdf_va_md_initialized) 4400 return; 4401 4402 qdf_spinlock_create(&qdf_va_md_list_lock); 4403 qdf_list_create(&qdf_va_md_list, QDF_MINIDUMP_LIST_SIZE); 4404 ret = qcom_va_md_register(qdf_trace_wlan_modname(), 4405 &qdf_va_md_notif_blk); 4406 qdf_va_md_initialized = !ret; 4407 } 4408 4409 qdf_export_symbol(__qdf_minidump_init); 4410 4411 void __qdf_minidump_deinit(void) 4412 { 4413 struct qdf_va_md_entry *entry; 4414 struct qdf_va_md_entry *next; 4415 4416 if (!qdf_va_md_initialized) 4417 return; 4418 4419 qdf_va_md_initialized = false; 4420 qcom_va_md_unregister(qdf_trace_wlan_modname(), 4421 &qdf_va_md_notif_blk); 4422 qdf_spin_lock_irqsave(&qdf_va_md_list_lock); 4423 qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) { 4424 qdf_list_remove_node(&qdf_va_md_list, &entry->node); 4425 qdf_mem_free(entry); 4426 } 4427 4428 qdf_list_destroy(&qdf_va_md_list); 4429 qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock); 4430 qdf_spinlock_destroy(&qdf_va_md_list_lock); 4431 } 4432 4433 qdf_export_symbol(__qdf_minidump_deinit); 4434 4435 void __qdf_minidump_log(void *start_addr, size_t size, const char *name) 4436 { 4437 struct qdf_va_md_entry *entry; 4438 QDF_STATUS status; 4439 4440 if (!qdf_va_md_initialized) 4441 return; 4442 4443 entry = qdf_mem_malloc(sizeof(*entry)); 4444 if (!entry) { 4445 qdf_err("malloc failed for %s: %pK, %zu", 4446 name, start_addr, size); 4447 return; 4448 } 4449 4450 qdf_str_lcopy(entry->data.owner, name, sizeof(entry->data.owner)); 4451 entry->data.vaddr = (unsigned long)start_addr; 4452 entry->data.size = size; 4453 4454 qdf_spin_lock_irqsave(&qdf_va_md_list_lock); 4455 status = qdf_list_insert_front(&qdf_va_md_list, &entry->node); 4456 qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock); 4457 if (QDF_IS_STATUS_ERROR(status)) { 4458 qdf_err("Failed to insert qdf va md entry, status %d", status); 4459 qdf_mem_free(entry); 4460 } 4461 } 4462 4463 qdf_export_symbol(__qdf_minidump_log); 4464 4465 void __qdf_minidump_remove(void *addr, size_t size, const char *name) 4466 { 4467 struct qdf_va_md_entry *entry; 4468 struct qdf_va_md_entry *next; 4469 4470 if (!qdf_va_md_initialized) 4471 return; 4472 4473 qdf_spin_lock_irqsave(&qdf_va_md_list_lock); 4474 qdf_list_for_each_del(&qdf_va_md_list, entry, next, node) { 4475 if (entry->data.vaddr == (unsigned long)addr && 4476 entry->data.size == size && 4477 !qdf_str_cmp(entry->data.owner, name)) { 4478 qdf_list_remove_node(&qdf_va_md_list, &entry->node); 4479 qdf_mem_free(entry); 4480 break; 4481 } 4482 } 4483 4484 qdf_spin_unlock_irqrestore(&qdf_va_md_list_lock); 4485 } 4486 4487 qdf_export_symbol(__qdf_minidump_remove); 4488 #endif 4489