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