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