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