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