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