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