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