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