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