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, uint16_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 * @type: packet type 1442 * @subtype: packet subtype 1443 * 1444 * Return: String based on pkt type 1445 */ 1446 static 1447 uint8_t *qdf_get_pkt_type_string(uint8_t type, uint8_t subtype) 1448 { 1449 switch (subtype) { 1450 case QDF_PROTO_EAPOL_M1: 1451 return "EAPOL-1"; 1452 case QDF_PROTO_EAPOL_M2: 1453 return "EAPOL-2"; 1454 case QDF_PROTO_EAPOL_M3: 1455 return "EAPOL-3"; 1456 case QDF_PROTO_EAPOL_M4: 1457 return "EAPOL-4"; 1458 case QDF_PROTO_DHCP_DISCOVER: 1459 return "DHCP-D"; 1460 case QDF_PROTO_DHCP_REQUEST: 1461 return "DHCP-R"; 1462 case QDF_PROTO_DHCP_OFFER: 1463 return "DHCP-O"; 1464 case QDF_PROTO_DHCP_ACK: 1465 return "DHCP-A"; 1466 case QDF_PROTO_DHCP_NACK: 1467 return "DHCP-NA"; 1468 case QDF_PROTO_DHCP_RELEASE: 1469 return "DHCP-REL"; 1470 case QDF_PROTO_DHCP_INFORM: 1471 return "DHCP-IN"; 1472 case QDF_PROTO_DHCP_DECLINE: 1473 return "DHCP-DEC"; 1474 case QDF_PROTO_ARP_REQ: 1475 return "ARP-RQ"; 1476 case QDF_PROTO_ARP_RES: 1477 return "ARP-RS"; 1478 case QDF_PROTO_DNS_QUERY: 1479 return "DNS_Q"; 1480 case QDF_PROTO_DNS_RES: 1481 return "DNS_RS"; 1482 default: 1483 switch (type) { 1484 case QDF_PROTO_TYPE_EAPOL: 1485 return "EAP"; 1486 case QDF_PROTO_TYPE_DHCP: 1487 return "DHCP"; 1488 case QDF_PROTO_TYPE_ARP: 1489 return "ARP"; 1490 case QDF_PROTO_TYPE_DNS: 1491 return "DNS"; 1492 default: 1493 return "UNKNOWN"; 1494 } 1495 } 1496 } 1497 1498 /** 1499 * qdf_get_pkt_status_string() - Get the string based on pkt status 1500 * @status: packet status 1501 * 1502 * Return: String based on pkt status 1503 */ 1504 static 1505 uint8_t *qdf_get_pkt_status_string(uint8_t status) 1506 { 1507 switch (status) { 1508 case QDF_TX_RX_STATUS_INVALID: 1509 return "inv"; 1510 case QDF_TX_RX_STATUS_OK: 1511 return "succ"; 1512 case QDF_TX_RX_STATUS_FW_DISCARD: 1513 return "disc"; 1514 case QDF_TX_RX_STATUS_NO_ACK: 1515 return "nack"; 1516 case QDF_TX_RX_STATUS_DROP: 1517 return "drop"; 1518 default: 1519 return "unknown"; 1520 } 1521 } 1522 1523 /** 1524 * qdf_dp_log_proto_pkt_info() - Send diag log with pkt info 1525 * @sa: Source MAC address 1526 * @da: Destination MAC address 1527 * @type: packet type 1528 * @subtype: packet subtype 1529 * @dir: tx or rx 1530 * @msdu_id: MSDU id 1531 * @status: status code 1532 * 1533 * Return: none 1534 */ 1535 void qdf_dp_log_proto_pkt_info(uint8_t *sa, uint8_t *da, uint8_t type, 1536 uint8_t subtype, uint8_t dir, uint16_t msdu_id, 1537 uint8_t status) 1538 { 1539 uint8_t pkt_rate_limit; 1540 static ulong last_ticks_tx[QDF_PROTO_SUBTYPE_MAX] = {0}; 1541 static ulong last_ticks_rx[QDF_PROTO_SUBTYPE_MAX] = {0}; 1542 ulong curr_ticks = jiffies; 1543 1544 pkt_rate_limit = qdf_get_rate_limit_by_type(type); 1545 1546 if ((dir == QDF_TX && 1547 !time_after(curr_ticks, 1548 last_ticks_tx[subtype] + HZ / pkt_rate_limit)) || 1549 (dir == QDF_RX && 1550 !time_after(curr_ticks, 1551 last_ticks_rx[subtype] + HZ / pkt_rate_limit))) 1552 return; 1553 1554 if (dir == QDF_TX) 1555 last_ticks_tx[subtype] = curr_ticks; 1556 else 1557 last_ticks_rx[subtype] = curr_ticks; 1558 1559 if (status == QDF_TX_RX_STATUS_INVALID) 1560 qdf_nofl_info("%s %s: SA:%pM DA:%pM", 1561 qdf_get_pkt_type_string(type, subtype), 1562 dir ? "RX":"TX", sa, da); 1563 else 1564 qdf_nofl_info("%s %s: SA:%pM DA:%pM msdu_id:%d status: %s", 1565 qdf_get_pkt_type_string(type, subtype), 1566 dir ? "RX":"TX", sa, da, msdu_id, 1567 qdf_get_pkt_status_string(status)); 1568 } 1569 1570 qdf_export_symbol(qdf_dp_log_proto_pkt_info); 1571 1572 /** 1573 * qdf_log_icmpv6_pkt() - log ICMPv6 packet 1574 * @vdev_id: ID of the vdev 1575 * @skb: skb pointer 1576 * @dir: direction 1577 * @pdev_id: ID of the pdev 1578 * 1579 * Return: true/false 1580 */ 1581 static bool qdf_log_icmpv6_pkt(uint8_t vdev_id, struct sk_buff *skb, 1582 enum qdf_proto_dir dir, uint8_t pdev_id) 1583 { 1584 enum qdf_proto_subtype subtype; 1585 1586 if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMPv6) && 1587 ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ICMPv6 == 1588 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) || 1589 (dir == QDF_RX && qdf_nbuf_is_icmpv6_pkt(skb) == true))) { 1590 1591 subtype = qdf_nbuf_get_icmpv6_subtype(skb); 1592 1593 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false; 1594 if (dir == QDF_TX) 1595 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1; 1596 else if (dir == QDF_RX) 1597 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1; 1598 1599 DPTRACE(qdf_dp_trace_proto_pkt( 1600 QDF_DP_TRACE_ICMPv6_PACKET_RECORD, 1601 vdev_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET), 1602 (skb->data + QDF_NBUF_DEST_MAC_OFFSET), 1603 QDF_PROTO_TYPE_ICMPv6, subtype, dir, pdev_id, false)); 1604 1605 switch (subtype) { 1606 case QDF_PROTO_ICMPV6_REQ: 1607 g_qdf_dp_trace_data.icmpv6_req++; 1608 break; 1609 case QDF_PROTO_ICMPV6_RES: 1610 g_qdf_dp_trace_data.icmpv6_resp++; 1611 break; 1612 case QDF_PROTO_ICMPV6_RS: 1613 g_qdf_dp_trace_data.icmpv6_rs++; 1614 break; 1615 case QDF_PROTO_ICMPV6_RA: 1616 g_qdf_dp_trace_data.icmpv6_ra++; 1617 break; 1618 case QDF_PROTO_ICMPV6_NS: 1619 g_qdf_dp_trace_data.icmpv6_ns++; 1620 break; 1621 case QDF_PROTO_ICMPV6_NA: 1622 g_qdf_dp_trace_data.icmpv6_na++; 1623 break; 1624 default: 1625 break; 1626 } 1627 return true; 1628 } 1629 1630 return false; 1631 } 1632 1633 /** 1634 * qdf_log_icmp_pkt() - log ICMP packet 1635 * @vdev_id: ID of the vdev 1636 * @skb: skb pointer 1637 * @dir: direction 1638 * @pdev_id: ID of the pdev 1639 * 1640 * Return: true/false 1641 */ 1642 static bool qdf_log_icmp_pkt(uint8_t vdev_id, struct sk_buff *skb, 1643 enum qdf_proto_dir dir, uint8_t pdev_id) 1644 { 1645 enum qdf_proto_subtype proto_subtype; 1646 1647 if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ICMP) && 1648 (qdf_nbuf_is_icmp_pkt(skb) == true)) { 1649 1650 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = false; 1651 proto_subtype = qdf_nbuf_get_icmp_subtype(skb); 1652 1653 if (QDF_TX == dir) 1654 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1; 1655 else if (QDF_RX == dir) 1656 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1; 1657 1658 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ICMP_PACKET_RECORD, 1659 vdev_id, 1660 skb->data + 1661 QDF_NBUF_SRC_MAC_OFFSET, 1662 skb->data + 1663 QDF_NBUF_DEST_MAC_OFFSET, 1664 QDF_PROTO_TYPE_ICMP, 1665 proto_subtype, dir, pdev_id, 1666 false)); 1667 1668 if (proto_subtype == QDF_PROTO_ICMP_REQ) 1669 g_qdf_dp_trace_data.icmp_req++; 1670 else 1671 g_qdf_dp_trace_data.icmp_resp++; 1672 1673 return true; 1674 } 1675 return false; 1676 } 1677 1678 /** 1679 * qdf_log_eapol_pkt() - log EAPOL packet 1680 * @vdev_id: ID of the vdev 1681 * @skb: skb pointer 1682 * @dir: direction 1683 * @pdev_id: ID of the pdev 1684 * 1685 * Return: true/false 1686 */ 1687 static bool qdf_log_eapol_pkt(uint8_t vdev_id, struct sk_buff *skb, 1688 enum qdf_proto_dir dir, uint8_t pdev_id) 1689 { 1690 enum qdf_proto_subtype subtype; 1691 uint32_t dp_eap_trace; 1692 uint32_t dp_eap_event; 1693 1694 dp_eap_trace = qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_EAPOL; 1695 dp_eap_event = qdf_dp_get_proto_event_bitmap() & 1696 QDF_NBUF_PKT_TRAC_TYPE_EAPOL; 1697 1698 if (!dp_eap_trace && !dp_eap_event) 1699 return false; 1700 1701 if (!((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_EAPOL == 1702 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) || 1703 (dir == QDF_RX && qdf_nbuf_is_ipv4_eapol_pkt(skb) == true))) 1704 return false; 1705 1706 subtype = qdf_nbuf_get_eapol_subtype(skb); 1707 1708 if (dp_eap_event && dir == QDF_RX) 1709 qdf_dp_log_proto_pkt_info(skb->data + QDF_NBUF_SRC_MAC_OFFSET, 1710 skb->data + QDF_NBUF_DEST_MAC_OFFSET, 1711 QDF_PROTO_TYPE_EAPOL, subtype, dir, 1712 QDF_TRACE_DEFAULT_MSDU_ID, 1713 QDF_TX_RX_STATUS_INVALID); 1714 1715 if (dp_eap_trace) { 1716 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true; 1717 if (QDF_TX == dir) 1718 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1; 1719 else if (QDF_RX == dir) 1720 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1; 1721 1722 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_EAPOL_PACKET_RECORD, 1723 vdev_id, 1724 skb->data + 1725 QDF_NBUF_SRC_MAC_OFFSET, 1726 skb->data + 1727 QDF_NBUF_DEST_MAC_OFFSET, 1728 QDF_PROTO_TYPE_EAPOL, subtype, 1729 dir, pdev_id, true)); 1730 1731 switch (subtype) { 1732 case QDF_PROTO_EAPOL_M1: 1733 g_qdf_dp_trace_data.eapol_m1++; 1734 break; 1735 case QDF_PROTO_EAPOL_M2: 1736 g_qdf_dp_trace_data.eapol_m2++; 1737 break; 1738 case QDF_PROTO_EAPOL_M3: 1739 g_qdf_dp_trace_data.eapol_m3++; 1740 break; 1741 case QDF_PROTO_EAPOL_M4: 1742 g_qdf_dp_trace_data.eapol_m4++; 1743 break; 1744 default: 1745 g_qdf_dp_trace_data.eapol_others++; 1746 break; 1747 } 1748 } 1749 1750 return true; 1751 } 1752 1753 /** 1754 * qdf_log_dhcp_pkt() - log DHCP packet 1755 * @vdev_id: ID of the vdev 1756 * @skb: skb pointer 1757 * @dir: direction 1758 * @pdev_id: ID of the pdev 1759 * 1760 * Return: true/false 1761 */ 1762 static bool qdf_log_dhcp_pkt(uint8_t vdev_id, struct sk_buff *skb, 1763 enum qdf_proto_dir dir, uint8_t pdev_id) 1764 { 1765 enum qdf_proto_subtype subtype = QDF_PROTO_INVALID; 1766 uint32_t dp_dhcp_trace; 1767 uint32_t dp_dhcp_event; 1768 1769 dp_dhcp_trace = qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_DHCP; 1770 dp_dhcp_event = qdf_dp_get_proto_event_bitmap() & 1771 QDF_NBUF_PKT_TRAC_TYPE_DHCP; 1772 1773 if (!dp_dhcp_trace && !dp_dhcp_event) 1774 return false; 1775 1776 if (!((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_DHCP == 1777 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) || 1778 (dir == QDF_RX && qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true))) 1779 return false; 1780 1781 subtype = qdf_nbuf_get_dhcp_subtype(skb); 1782 1783 if (dp_dhcp_event && dir == QDF_RX) 1784 qdf_dp_log_proto_pkt_info(skb->data + QDF_NBUF_SRC_MAC_OFFSET, 1785 skb->data + QDF_NBUF_DEST_MAC_OFFSET, 1786 QDF_PROTO_TYPE_DHCP, subtype, dir, 1787 QDF_TRACE_DEFAULT_MSDU_ID, 1788 QDF_TX_RX_STATUS_INVALID); 1789 1790 if (dp_dhcp_trace) { 1791 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true; 1792 if (QDF_TX == dir) 1793 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1; 1794 else if (QDF_RX == dir) 1795 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1; 1796 1797 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_DHCP_PACKET_RECORD, 1798 vdev_id, 1799 skb->data + 1800 QDF_NBUF_SRC_MAC_OFFSET, 1801 skb->data + 1802 QDF_NBUF_DEST_MAC_OFFSET, 1803 QDF_PROTO_TYPE_DHCP, subtype, 1804 dir, pdev_id, true)); 1805 1806 switch (subtype) { 1807 case QDF_PROTO_DHCP_DISCOVER: 1808 g_qdf_dp_trace_data.dhcp_disc++; 1809 break; 1810 case QDF_PROTO_DHCP_OFFER: 1811 g_qdf_dp_trace_data.dhcp_off++; 1812 break; 1813 case QDF_PROTO_DHCP_REQUEST: 1814 g_qdf_dp_trace_data.dhcp_req++; 1815 break; 1816 case QDF_PROTO_DHCP_ACK: 1817 g_qdf_dp_trace_data.dhcp_ack++; 1818 break; 1819 case QDF_PROTO_DHCP_NACK: 1820 g_qdf_dp_trace_data.dhcp_nack++; 1821 break; 1822 default: 1823 g_qdf_dp_trace_data.eapol_others++; 1824 break; 1825 } 1826 } 1827 1828 return true; 1829 } 1830 1831 /** 1832 * qdf_log_arp_pkt() - log ARP packet 1833 * @vdev_id: ID of the vdev 1834 * @skb: skb pointer 1835 * @dir: direction 1836 * @pdev_id: ID of the pdev 1837 * 1838 * Return: true/false 1839 */ 1840 static bool qdf_log_arp_pkt(uint8_t vdev_id, struct sk_buff *skb, 1841 enum qdf_proto_dir dir, uint8_t pdev_id) 1842 { 1843 enum qdf_proto_subtype proto_subtype; 1844 1845 if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ARP) && 1846 ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ARP == 1847 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) || 1848 (dir == QDF_RX && qdf_nbuf_is_ipv4_arp_pkt(skb) == true))) { 1849 1850 proto_subtype = qdf_nbuf_get_arp_subtype(skb); 1851 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true; 1852 if (QDF_TX == dir) 1853 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1; 1854 else if (QDF_RX == dir) 1855 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1; 1856 1857 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ARP_PACKET_RECORD, 1858 vdev_id, 1859 skb->data + 1860 QDF_NBUF_SRC_MAC_OFFSET, 1861 skb->data + 1862 QDF_NBUF_DEST_MAC_OFFSET, 1863 QDF_PROTO_TYPE_ARP, 1864 proto_subtype, dir, pdev_id, 1865 true)); 1866 1867 if (QDF_PROTO_ARP_REQ == proto_subtype) 1868 g_qdf_dp_trace_data.arp_req++; 1869 else 1870 g_qdf_dp_trace_data.arp_resp++; 1871 1872 return true; 1873 } 1874 return false; 1875 } 1876 1877 1878 bool qdf_dp_trace_log_pkt(uint8_t vdev_id, struct sk_buff *skb, 1879 enum qdf_proto_dir dir, uint8_t pdev_id) 1880 { 1881 if (!qdf_dp_get_proto_bitmap() && !qdf_dp_get_proto_event_bitmap()) 1882 return false; 1883 if (qdf_log_arp_pkt(vdev_id, skb, dir, pdev_id)) 1884 return true; 1885 if (qdf_log_dhcp_pkt(vdev_id, skb, dir, pdev_id)) 1886 return true; 1887 if (qdf_log_eapol_pkt(vdev_id, skb, dir, pdev_id)) 1888 return true; 1889 if (qdf_log_icmp_pkt(vdev_id, skb, dir, pdev_id)) 1890 return true; 1891 if (qdf_log_icmpv6_pkt(vdev_id, skb, dir, pdev_id)) 1892 return true; 1893 return false; 1894 } 1895 qdf_export_symbol(qdf_dp_trace_log_pkt); 1896 1897 void qdf_dp_display_mgmt_pkt(struct qdf_dp_trace_record_s *record, 1898 uint16_t index, uint8_t pdev_id, uint8_t info) 1899 { 1900 int loc; 1901 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 1902 struct qdf_dp_trace_mgmt_buf *buf = 1903 (struct qdf_dp_trace_mgmt_buf *)record->data; 1904 1905 qdf_mem_zero(prepend_str, sizeof(prepend_str)); 1906 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 1907 index, info, record); 1908 1909 DPTRACE_PRINT("%s [%d] [%s %s]", 1910 prepend_str, 1911 buf->vdev_id, 1912 qdf_dp_type_to_str(buf->type), 1913 qdf_dp_subtype_to_str(buf->subtype)); 1914 } 1915 qdf_export_symbol(qdf_dp_display_mgmt_pkt); 1916 1917 1918 void qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id, 1919 uint8_t pdev_id, enum qdf_proto_type type, 1920 enum qdf_proto_subtype subtype) 1921 { 1922 struct qdf_dp_trace_mgmt_buf buf; 1923 int buf_size = sizeof(struct qdf_dp_trace_mgmt_buf); 1924 1925 if (qdf_dp_enable_check(NULL, code, QDF_NA) == false) 1926 return; 1927 1928 if (buf_size > QDF_DP_TRACE_RECORD_SIZE) 1929 QDF_BUG(0); 1930 1931 buf.type = type; 1932 buf.subtype = subtype; 1933 buf.vdev_id = vdev_id; 1934 qdf_dp_add_record(code, pdev_id, (uint8_t *)&buf, buf_size, 1935 NULL, 0, true); 1936 } 1937 qdf_export_symbol(qdf_dp_trace_mgmt_pkt); 1938 1939 static void 1940 qdf_dpt_display_credit_record_debugfs(qdf_debugfs_file_t file, 1941 struct qdf_dp_trace_record_s *record, 1942 uint32_t index) 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, 0, record); 1951 if (buf->operation == QDF_OP_NA) 1952 qdf_debugfs_printf(file, "%s [%s] [T: %d G0: %d G1: %d]\n", 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 qdf_debugfs_printf(file, 1959 "%s [%s] [T: %d G0: %d G1: %d] [%s %d]\n", 1960 prepend_str, 1961 qdf_dp_credit_source_to_str(buf->source), 1962 buf->total_credits, buf->g0_credit, 1963 buf->g1_credit, 1964 qdf_dp_operation_to_str(buf->operation), 1965 buf->delta); 1966 } 1967 1968 void qdf_dp_display_credit_record(struct qdf_dp_trace_record_s *record, 1969 uint16_t index, uint8_t pdev_id, uint8_t info) 1970 { 1971 int loc; 1972 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 1973 struct qdf_dp_trace_credit_record *buf = 1974 (struct qdf_dp_trace_credit_record *)record->data; 1975 1976 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 1977 index, info, record); 1978 if (buf->operation == QDF_OP_NA) 1979 DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d]", 1980 prepend_str, 1981 qdf_dp_credit_source_to_str(buf->source), 1982 buf->total_credits, buf->g0_credit, 1983 buf->g1_credit); 1984 else 1985 DPTRACE_PRINT("%s [%s] [T: %d G0: %d G1: %d] [%s %d]", 1986 prepend_str, 1987 qdf_dp_credit_source_to_str(buf->source), 1988 buf->total_credits, buf->g0_credit, 1989 buf->g1_credit, 1990 qdf_dp_operation_to_str(buf->operation), 1991 buf->delta); 1992 } 1993 1994 void qdf_dp_trace_credit_record(enum QDF_CREDIT_UPDATE_SOURCE source, 1995 enum QDF_CREDIT_OPERATION operation, 1996 int delta, int total_credits, 1997 int g0_credit, int g1_credit) 1998 { 1999 struct qdf_dp_trace_credit_record buf; 2000 int buf_size = sizeof(struct qdf_dp_trace_credit_record); 2001 enum QDF_DP_TRACE_ID code = QDF_DP_TRACE_TX_CREDIT_RECORD; 2002 2003 if (qdf_dp_enable_check(NULL, code, QDF_NA) == false) 2004 return; 2005 2006 if (!(qdf_dp_get_proto_bitmap() & QDF_HL_CREDIT_TRACKING)) 2007 return; 2008 2009 if (buf_size > QDF_DP_TRACE_RECORD_SIZE) 2010 QDF_BUG(0); 2011 2012 buf.source = source; 2013 buf.operation = operation; 2014 buf.delta = delta; 2015 buf.total_credits = total_credits; 2016 buf.g0_credit = g0_credit; 2017 buf.g1_credit = g1_credit; 2018 2019 qdf_dp_add_record(code, QDF_TRACE_DEFAULT_PDEV_ID, (uint8_t *)&buf, 2020 buf_size, NULL, 0, false); 2021 } 2022 qdf_export_symbol(qdf_dp_trace_credit_record); 2023 2024 void qdf_dp_display_event_record(struct qdf_dp_trace_record_s *record, 2025 uint16_t index, uint8_t pdev_id, uint8_t info) 2026 { 2027 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2028 struct qdf_dp_trace_event_buf *buf = 2029 (struct qdf_dp_trace_event_buf *)record->data; 2030 2031 qdf_mem_zero(prepend_str, sizeof(prepend_str)); 2032 qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2033 index, info, record); 2034 2035 DPTRACE_PRINT("%s [%d] [%s %s]", 2036 prepend_str, 2037 buf->vdev_id, 2038 qdf_dp_type_to_str(buf->type), 2039 qdf_dp_subtype_to_str(buf->subtype)); 2040 } 2041 qdf_export_symbol(qdf_dp_display_event_record); 2042 2043 /** 2044 * qdf_dp_trace_record_event() - record events 2045 * @code: dptrace code 2046 * @vdev_id: vdev id 2047 * @pdev_id: pdev_id 2048 * @type: proto type 2049 * @subtype: proto subtype 2050 * 2051 * Return: none 2052 */ 2053 void qdf_dp_trace_record_event(enum QDF_DP_TRACE_ID code, uint8_t vdev_id, 2054 uint8_t pdev_id, enum qdf_proto_type type, 2055 enum qdf_proto_subtype subtype) 2056 { 2057 struct qdf_dp_trace_event_buf buf; 2058 int buf_size = sizeof(struct qdf_dp_trace_event_buf); 2059 2060 if (qdf_dp_enable_check(NULL, code, QDF_NA) == false) 2061 return; 2062 2063 if (buf_size > QDF_DP_TRACE_RECORD_SIZE) 2064 QDF_BUG(0); 2065 2066 buf.type = type; 2067 buf.subtype = subtype; 2068 buf.vdev_id = vdev_id; 2069 qdf_dp_add_record(code, pdev_id, 2070 (uint8_t *)&buf, buf_size, NULL, 0, true); 2071 } 2072 qdf_export_symbol(qdf_dp_trace_record_event); 2073 2074 2075 void qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s *record, 2076 uint16_t index, uint8_t pdev_id, uint8_t info) 2077 { 2078 int loc; 2079 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2080 struct qdf_dp_trace_proto_buf *buf = 2081 (struct qdf_dp_trace_proto_buf *)record->data; 2082 2083 qdf_mem_zero(prepend_str, sizeof(prepend_str)); 2084 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2085 index, info, record); 2086 DPTRACE_PRINT("%s [%d] [%s] SA: " 2087 QDF_MAC_ADDR_STR " %s DA: " 2088 QDF_MAC_ADDR_STR, 2089 prepend_str, 2090 buf->vdev_id, 2091 qdf_dp_subtype_to_str(buf->subtype), 2092 QDF_MAC_ADDR_ARRAY(buf->sa.bytes), 2093 qdf_dp_dir_to_str(buf->dir), 2094 QDF_MAC_ADDR_ARRAY(buf->da.bytes)); 2095 } 2096 qdf_export_symbol(qdf_dp_display_proto_pkt); 2097 2098 void qdf_dp_trace_proto_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id, 2099 uint8_t *sa, uint8_t *da, enum qdf_proto_type type, 2100 enum qdf_proto_subtype subtype, enum qdf_proto_dir dir, 2101 uint8_t pdev_id, bool print) 2102 { 2103 struct qdf_dp_trace_proto_buf buf; 2104 int buf_size = sizeof(struct qdf_dp_trace_ptr_buf); 2105 2106 if (qdf_dp_enable_check(NULL, code, dir) == false) 2107 return; 2108 2109 if (buf_size > QDF_DP_TRACE_RECORD_SIZE) 2110 QDF_BUG(0); 2111 2112 memcpy(&buf.sa, sa, QDF_NET_ETH_LEN); 2113 memcpy(&buf.da, da, QDF_NET_ETH_LEN); 2114 buf.dir = dir; 2115 buf.type = type; 2116 buf.subtype = subtype; 2117 buf.vdev_id = vdev_id; 2118 qdf_dp_add_record(code, pdev_id, 2119 (uint8_t *)&buf, buf_size, NULL, 0, print); 2120 } 2121 qdf_export_symbol(qdf_dp_trace_proto_pkt); 2122 2123 void qdf_dp_display_ptr_record(struct qdf_dp_trace_record_s *record, 2124 uint16_t index, uint8_t pdev_id, uint8_t info) 2125 { 2126 int loc; 2127 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2128 struct qdf_dp_trace_ptr_buf *buf = 2129 (struct qdf_dp_trace_ptr_buf *)record->data; 2130 bool is_free_pkt_ptr_record = false; 2131 2132 if ((record->code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) || 2133 (record->code == QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD)) 2134 is_free_pkt_ptr_record = true; 2135 2136 qdf_mem_zero(prepend_str, sizeof(prepend_str)); 2137 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2138 index, info, record); 2139 2140 if (loc < sizeof(prepend_str)) 2141 scnprintf(&prepend_str[loc], sizeof(prepend_str) - loc, 2142 "[msdu id %d %s %d]", 2143 buf->msdu_id, 2144 is_free_pkt_ptr_record ? "status" : "vdev_id", 2145 buf->status); 2146 2147 if (info & QDF_DP_TRACE_RECORD_INFO_LIVE) { 2148 /* In live mode donot dump the contents of the cookie */ 2149 DPTRACE_PRINT("%s", prepend_str); 2150 } else { 2151 dump_dp_hex_trace(prepend_str, (uint8_t *)&buf->cookie, 2152 sizeof(buf->cookie)); 2153 } 2154 } 2155 qdf_export_symbol(qdf_dp_display_ptr_record); 2156 2157 static 2158 enum qdf_proto_type qdf_dp_get_pkt_proto_type(qdf_nbuf_t nbuf) 2159 { 2160 uint8_t pkt_type; 2161 2162 if (!nbuf) 2163 return QDF_PROTO_TYPE_MAX; 2164 2165 if (qdf_nbuf_data_is_dns_query(nbuf) || 2166 qdf_nbuf_data_is_dns_response(nbuf)) 2167 return QDF_PROTO_TYPE_DNS; 2168 2169 pkt_type = QDF_NBUF_CB_GET_PACKET_TYPE(nbuf); 2170 2171 switch (pkt_type) { 2172 case QDF_NBUF_CB_PACKET_TYPE_EAPOL: 2173 return QDF_PROTO_TYPE_EAPOL; 2174 case QDF_NBUF_CB_PACKET_TYPE_ARP: 2175 return QDF_PROTO_TYPE_ARP; 2176 case QDF_NBUF_CB_PACKET_TYPE_DHCP: 2177 return QDF_PROTO_TYPE_DHCP; 2178 default: 2179 return QDF_PROTO_TYPE_MAX; 2180 } 2181 } 2182 2183 static 2184 enum qdf_proto_subtype qdf_dp_get_pkt_subtype(qdf_nbuf_t nbuf, 2185 enum qdf_proto_type pkt_type) 2186 { 2187 switch (pkt_type) { 2188 case QDF_PROTO_TYPE_EAPOL: 2189 return qdf_nbuf_get_eapol_subtype(nbuf); 2190 case QDF_PROTO_TYPE_ARP: 2191 return qdf_nbuf_get_arp_subtype(nbuf); 2192 case QDF_PROTO_TYPE_DHCP: 2193 return qdf_nbuf_get_dhcp_subtype(nbuf); 2194 case QDF_PROTO_TYPE_DNS: 2195 return (qdf_nbuf_data_is_dns_query(nbuf)) ? 2196 QDF_PROTO_DNS_QUERY : QDF_PROTO_DNS_RES; 2197 default: 2198 return QDF_PROTO_INVALID; 2199 } 2200 } 2201 2202 static 2203 bool qdf_dp_proto_log_enable_check(enum qdf_proto_type pkt_type, 2204 uint16_t status) 2205 { 2206 if (pkt_type == QDF_PROTO_TYPE_MAX) 2207 return false; 2208 2209 switch (pkt_type) { 2210 case QDF_PROTO_TYPE_EAPOL: 2211 return qdf_dp_get_proto_event_bitmap() & 2212 QDF_NBUF_PKT_TRAC_TYPE_EAPOL; 2213 case QDF_PROTO_TYPE_DHCP: 2214 return qdf_dp_get_proto_event_bitmap() & 2215 QDF_NBUF_PKT_TRAC_TYPE_DHCP; 2216 case QDF_PROTO_TYPE_ARP: 2217 if (status == QDF_TX_RX_STATUS_OK) 2218 return false; 2219 else 2220 return qdf_dp_get_proto_event_bitmap() & 2221 QDF_NBUF_PKT_TRAC_TYPE_ARP; 2222 case QDF_PROTO_TYPE_DNS: 2223 if (status == QDF_TX_RX_STATUS_OK) 2224 return false; 2225 else 2226 return qdf_dp_get_proto_event_bitmap() & 2227 QDF_NBUF_PKT_TRAC_TYPE_DNS; 2228 default: 2229 return false; 2230 } 2231 } 2232 2233 void qdf_dp_track_noack_check(qdf_nbuf_t nbuf, enum qdf_proto_subtype *subtype) 2234 { 2235 enum qdf_proto_type pkt_type = qdf_dp_get_pkt_proto_type(nbuf); 2236 uint16_t dp_track = 0; 2237 2238 switch (pkt_type) { 2239 case QDF_PROTO_TYPE_EAPOL: 2240 dp_track = qdf_dp_get_proto_bitmap() & 2241 QDF_NBUF_PKT_TRAC_TYPE_EAPOL; 2242 break; 2243 case QDF_PROTO_TYPE_DHCP: 2244 dp_track = qdf_dp_get_proto_bitmap() & 2245 QDF_NBUF_PKT_TRAC_TYPE_DHCP; 2246 break; 2247 case QDF_PROTO_TYPE_ARP: 2248 dp_track = qdf_dp_get_proto_bitmap() & 2249 QDF_NBUF_PKT_TRAC_TYPE_ARP; 2250 break; 2251 case QDF_PROTO_TYPE_DNS: 2252 dp_track = qdf_dp_get_proto_bitmap() & 2253 QDF_NBUF_PKT_TRAC_TYPE_DNS; 2254 break; 2255 default: 2256 break; 2257 } 2258 2259 if (!dp_track) { 2260 *subtype = QDF_PROTO_INVALID; 2261 return; 2262 } 2263 2264 *subtype = qdf_dp_get_pkt_subtype(nbuf, pkt_type); 2265 } 2266 qdf_export_symbol(qdf_dp_track_noack_check); 2267 2268 enum qdf_dp_tx_rx_status qdf_dp_get_status_from_htt(uint8_t status) 2269 { 2270 switch (status) { 2271 case QDF_TX_COMP_STATUS_OK: 2272 return QDF_TX_RX_STATUS_OK; 2273 case QDF_TX_COMP_STATUS_STAT_DISCARD: 2274 case QDF_TX_COMP_STATUS_STAT_DROP: 2275 return QDF_TX_RX_STATUS_FW_DISCARD; 2276 case QDF_TX_COMP_STATUS_STAT_NO_ACK: 2277 return QDF_TX_RX_STATUS_NO_ACK; 2278 default: 2279 return QDF_TX_RX_STATUS_MAX; 2280 } 2281 } 2282 2283 qdf_export_symbol(qdf_dp_get_status_from_htt); 2284 2285 enum qdf_dp_tx_rx_status qdf_dp_get_status_from_a_status(uint8_t status) 2286 { 2287 if (status == QDF_A_STATUS_ERROR) 2288 return QDF_TX_RX_STATUS_INVALID; 2289 else if (status == QDF_A_STATUS_OK) 2290 return QDF_TX_RX_STATUS_OK; 2291 else 2292 return QDF_TX_RX_STATUS_MAX; 2293 } 2294 2295 qdf_export_symbol(qdf_dp_get_status_from_a_status); 2296 2297 /** 2298 * qdf_dp_trace_ptr() - record dptrace 2299 * @code: dptrace code 2300 * @pdev_id: pdev_id 2301 * @data: data 2302 * @size: size of data 2303 * @msdu_id: msdu_id 2304 * @status: return status 2305 * 2306 * Return: none 2307 */ 2308 void qdf_dp_trace_ptr(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code, 2309 uint8_t pdev_id, uint8_t *data, uint8_t size, 2310 uint16_t msdu_id, uint16_t status) 2311 { 2312 struct qdf_dp_trace_ptr_buf buf; 2313 int buf_size = sizeof(struct qdf_dp_trace_ptr_buf); 2314 enum qdf_proto_type pkt_type; 2315 2316 pkt_type = qdf_dp_get_pkt_proto_type(nbuf); 2317 if ((code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD || 2318 code == QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD) && 2319 qdf_dp_proto_log_enable_check(pkt_type, status)) 2320 qdf_dp_log_proto_pkt_info(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET, 2321 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET, 2322 pkt_type, 2323 qdf_dp_get_pkt_subtype(nbuf, pkt_type), 2324 QDF_TX, msdu_id, status); 2325 2326 if (qdf_dp_enable_check(nbuf, code, QDF_TX) == false) 2327 return; 2328 2329 if (buf_size > QDF_DP_TRACE_RECORD_SIZE) 2330 QDF_BUG(0); 2331 2332 qdf_mem_copy(&buf.cookie, data, size); 2333 buf.msdu_id = msdu_id; 2334 buf.status = status; 2335 qdf_dp_add_record(code, pdev_id, (uint8_t *)&buf, buf_size, NULL, 0, 2336 QDF_NBUF_CB_DP_TRACE_PRINT(nbuf)); 2337 } 2338 qdf_export_symbol(qdf_dp_trace_ptr); 2339 2340 void qdf_dp_trace_data_pkt(qdf_nbuf_t nbuf, uint8_t pdev_id, 2341 enum QDF_DP_TRACE_ID code, uint16_t msdu_id, 2342 enum qdf_proto_dir dir) 2343 { 2344 struct qdf_dp_trace_data_buf buf; 2345 enum qdf_proto_type pkt_type; 2346 2347 pkt_type = qdf_dp_get_pkt_proto_type(nbuf); 2348 if (code == QDF_DP_TRACE_DROP_PACKET_RECORD && 2349 qdf_dp_proto_log_enable_check(pkt_type, QDF_TX_RX_STATUS_DROP)) 2350 qdf_dp_log_proto_pkt_info(nbuf->data + QDF_NBUF_SRC_MAC_OFFSET, 2351 nbuf->data + QDF_NBUF_DEST_MAC_OFFSET, 2352 pkt_type, 2353 qdf_dp_get_pkt_subtype(nbuf, pkt_type), 2354 QDF_TX, msdu_id, 2355 QDF_TX_RX_STATUS_DROP); 2356 2357 buf.msdu_id = msdu_id; 2358 if (!qdf_dp_enable_check(nbuf, code, dir)) 2359 return; 2360 2361 qdf_dp_add_record(code, pdev_id, 2362 nbuf ? qdf_nbuf_data(nbuf) : NULL, 2363 nbuf ? nbuf->len - nbuf->data_len : 0, 2364 (uint8_t *)&buf, sizeof(struct qdf_dp_trace_data_buf), 2365 (nbuf) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false); 2366 } 2367 2368 qdf_export_symbol(qdf_dp_trace_data_pkt); 2369 2370 void qdf_dp_display_record(struct qdf_dp_trace_record_s *record, 2371 uint16_t index, uint8_t pdev_id, uint8_t info) 2372 { 2373 int loc; 2374 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2375 2376 if (!(pdev_id == QDF_TRACE_DEFAULT_PDEV_ID || 2377 pdev_id == record->pdev_id)) 2378 return; 2379 2380 qdf_mem_zero(prepend_str, sizeof(prepend_str)); 2381 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2382 index, info, record); 2383 2384 switch (record->code) { 2385 case QDF_DP_TRACE_HDD_TX_TIMEOUT: 2386 DPTRACE_PRINT(" %s: HDD TX Timeout", prepend_str); 2387 break; 2388 case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT: 2389 DPTRACE_PRINT(" %s: HDD SoftAP TX Timeout", prepend_str); 2390 break; 2391 case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD: 2392 DPTRACE_PRINT(" %s: CE Fast Packet Error", prepend_str); 2393 break; 2394 case QDF_DP_TRACE_LI_DP_NULL_RX_PACKET_RECORD: 2395 default: 2396 dump_dp_hex_trace(prepend_str, record->data, record->size); 2397 break; 2398 }; 2399 } 2400 qdf_export_symbol(qdf_dp_display_record); 2401 2402 void 2403 qdf_dp_display_data_pkt_record(struct qdf_dp_trace_record_s *record, 2404 uint16_t rec_index, uint8_t pdev_id, 2405 uint8_t info) 2406 { 2407 int loc; 2408 char prepend_str[DP_TRACE_META_DATA_STRLEN + 10]; 2409 struct qdf_dp_trace_data_buf *buf = 2410 (struct qdf_dp_trace_data_buf *)record->data; 2411 2412 qdf_mem_zero(prepend_str, sizeof(prepend_str)); 2413 2414 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2415 rec_index, info, record); 2416 if (loc < sizeof(prepend_str)) 2417 loc += snprintf(&prepend_str[loc], sizeof(prepend_str) - loc, 2418 "[%d]", buf->msdu_id); 2419 dump_dp_hex_trace(prepend_str, 2420 &record->data[sizeof(struct qdf_dp_trace_data_buf)], 2421 record->size); 2422 } 2423 2424 /** 2425 * qdf_dp_trace() - Stores the data in buffer 2426 * @nbuf : defines the netbuf 2427 * @code : defines the event 2428 * @pdev_id: pdev_id 2429 * @data : defines the data to be stored 2430 * @size : defines the size of the data record 2431 * 2432 * Return: None 2433 */ 2434 void qdf_dp_trace(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code, uint8_t pdev_id, 2435 uint8_t *data, uint8_t size, enum qdf_proto_dir dir) 2436 { 2437 2438 if (qdf_dp_enable_check(nbuf, code, dir) == false) 2439 return; 2440 2441 qdf_dp_add_record(code, pdev_id, nbuf ? qdf_nbuf_data(nbuf) : NULL, 2442 size, NULL, 0, 2443 (nbuf) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false); 2444 } 2445 qdf_export_symbol(qdf_dp_trace); 2446 2447 /** 2448 * qdf_dp_trace_spin_lock_init() - initializes the lock variable before use 2449 * This function will be called from cds_alloc_global_context, we will have lock 2450 * available to use ASAP 2451 * 2452 * Return: None 2453 */ 2454 void qdf_dp_trace_spin_lock_init(void) 2455 { 2456 spin_lock_init(&l_dp_trace_lock); 2457 } 2458 qdf_export_symbol(qdf_dp_trace_spin_lock_init); 2459 2460 /** 2461 * qdf_dp_trace_disable_live_mode - disable live mode for dptrace 2462 * 2463 * Return: none 2464 */ 2465 void qdf_dp_trace_disable_live_mode(void) 2466 { 2467 g_qdf_dp_trace_data.force_live_mode = 0; 2468 } 2469 qdf_export_symbol(qdf_dp_trace_disable_live_mode); 2470 2471 /** 2472 * qdf_dp_trace_enable_live_mode() - enable live mode for dptrace 2473 * 2474 * Return: none 2475 */ 2476 void qdf_dp_trace_enable_live_mode(void) 2477 { 2478 g_qdf_dp_trace_data.force_live_mode = 1; 2479 } 2480 qdf_export_symbol(qdf_dp_trace_enable_live_mode); 2481 2482 /** 2483 * qdf_dp_trace_clear_buffer() - clear dp trace buffer 2484 * 2485 * Return: none 2486 */ 2487 void qdf_dp_trace_clear_buffer(void) 2488 { 2489 g_qdf_dp_trace_data.head = INVALID_QDF_DP_TRACE_ADDR; 2490 g_qdf_dp_trace_data.tail = INVALID_QDF_DP_TRACE_ADDR; 2491 g_qdf_dp_trace_data.num = 0; 2492 g_qdf_dp_trace_data.dump_counter = 0; 2493 g_qdf_dp_trace_data.num_records_to_dump = MAX_QDF_DP_TRACE_RECORDS; 2494 if (g_qdf_dp_trace_data.enable) 2495 memset(g_qdf_dp_trace_tbl, 0, 2496 MAX_QDF_DP_TRACE_RECORDS * 2497 sizeof(struct qdf_dp_trace_record_s)); 2498 } 2499 qdf_export_symbol(qdf_dp_trace_clear_buffer); 2500 2501 void qdf_dp_trace_dump_stats(void) 2502 { 2503 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)", 2504 g_qdf_dp_trace_data.tx_count, 2505 g_qdf_dp_trace_data.rx_count, 2506 g_qdf_dp_trace_data.icmp_req, 2507 g_qdf_dp_trace_data.icmp_resp, 2508 g_qdf_dp_trace_data.arp_req, 2509 g_qdf_dp_trace_data.arp_resp, 2510 g_qdf_dp_trace_data.icmpv6_req, 2511 g_qdf_dp_trace_data.icmpv6_resp, 2512 g_qdf_dp_trace_data.icmpv6_ns, 2513 g_qdf_dp_trace_data.icmpv6_na, 2514 g_qdf_dp_trace_data.icmpv6_rs, 2515 g_qdf_dp_trace_data.icmpv6_ra, 2516 g_qdf_dp_trace_data.dhcp_disc, 2517 g_qdf_dp_trace_data.dhcp_off, 2518 g_qdf_dp_trace_data.dhcp_req, 2519 g_qdf_dp_trace_data.dhcp_ack, 2520 g_qdf_dp_trace_data.dhcp_nack, 2521 g_qdf_dp_trace_data.dhcp_others, 2522 g_qdf_dp_trace_data.eapol_m1, 2523 g_qdf_dp_trace_data.eapol_m2, 2524 g_qdf_dp_trace_data.eapol_m3, 2525 g_qdf_dp_trace_data.eapol_m4, 2526 g_qdf_dp_trace_data.eapol_others); 2527 } 2528 qdf_export_symbol(qdf_dp_trace_dump_stats); 2529 2530 /** 2531 * qdf_dpt_dump_hex_trace_debugfs() - read data in file 2532 * @file: file to read 2533 * @str: string to prepend the hexdump with. 2534 * @buf: buffer which contains data to be written 2535 * @buf_len: defines the size of the data to be written 2536 * 2537 * Return: None 2538 */ 2539 static void qdf_dpt_dump_hex_trace_debugfs(qdf_debugfs_file_t file, 2540 char *str, uint8_t *buf, uint8_t buf_len) 2541 { 2542 unsigned char linebuf[BUFFER_SIZE]; 2543 const u8 *ptr = buf; 2544 int i, linelen, remaining = buf_len; 2545 2546 /* Dump the bytes in the last line */ 2547 for (i = 0; i < buf_len; i += ROW_SIZE) { 2548 linelen = min(remaining, ROW_SIZE); 2549 remaining -= ROW_SIZE; 2550 2551 hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1, 2552 linebuf, sizeof(linebuf), false); 2553 2554 qdf_debugfs_printf(file, "%s %s\n", str, linebuf); 2555 } 2556 } 2557 2558 /** 2559 * qdf_dpt_display_proto_pkt_debugfs() - display proto packet 2560 * @file: file to read 2561 * @record: dptrace record 2562 * @index: index 2563 * 2564 * Return: none 2565 */ 2566 static void qdf_dpt_display_proto_pkt_debugfs(qdf_debugfs_file_t file, 2567 struct qdf_dp_trace_record_s *record, 2568 uint32_t index) 2569 { 2570 int loc; 2571 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2572 struct qdf_dp_trace_proto_buf *buf = 2573 (struct qdf_dp_trace_proto_buf *)record->data; 2574 2575 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2576 index, 0, record); 2577 qdf_debugfs_printf(file, "%s [%d] [%s] SA: " 2578 QDF_MAC_ADDR_STR " %s DA: " 2579 QDF_MAC_ADDR_STR, 2580 prepend_str, 2581 buf->vdev_id, 2582 qdf_dp_subtype_to_str(buf->subtype), 2583 QDF_MAC_ADDR_ARRAY(buf->sa.bytes), 2584 qdf_dp_dir_to_str(buf->dir), 2585 QDF_MAC_ADDR_ARRAY(buf->da.bytes)); 2586 qdf_debugfs_printf(file, "\n"); 2587 } 2588 2589 /** 2590 * qdf_dpt_display_mgmt_pkt_debugfs() - display mgmt packet 2591 * @file: file to read 2592 * @record: dptrace record 2593 * @index: index 2594 * 2595 * Return: none 2596 */ 2597 static void qdf_dpt_display_mgmt_pkt_debugfs(qdf_debugfs_file_t file, 2598 struct qdf_dp_trace_record_s *record, 2599 uint32_t index) 2600 { 2601 2602 int loc; 2603 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2604 struct qdf_dp_trace_mgmt_buf *buf = 2605 (struct qdf_dp_trace_mgmt_buf *)record->data; 2606 2607 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2608 index, 0, record); 2609 2610 qdf_debugfs_printf(file, "%s [%d] [%s %s]\n", 2611 prepend_str, 2612 buf->vdev_id, 2613 qdf_dp_type_to_str(buf->type), 2614 qdf_dp_subtype_to_str(buf->subtype)); 2615 } 2616 2617 /** 2618 * qdf_dpt_display_event_record_debugfs() - display event records 2619 * @file: file to read 2620 * @record: dptrace record 2621 * @index: index 2622 * 2623 * Return: none 2624 */ 2625 static void qdf_dpt_display_event_record_debugfs(qdf_debugfs_file_t file, 2626 struct qdf_dp_trace_record_s *record, 2627 uint32_t index) 2628 { 2629 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2630 struct qdf_dp_trace_event_buf *buf = 2631 (struct qdf_dp_trace_event_buf *)record->data; 2632 2633 qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2634 index, 0, record); 2635 qdf_debugfs_printf(file, "%s [%d] [%s %s]\n", 2636 prepend_str, 2637 buf->vdev_id, 2638 qdf_dp_type_to_str(buf->type), 2639 qdf_dp_subtype_to_str(buf->subtype)); 2640 } 2641 2642 /** 2643 * qdf_dpt_display_ptr_record_debugfs() - display record ptr 2644 * @file: file to read 2645 * @record: dptrace record 2646 * @index: index 2647 * 2648 * Return: none 2649 */ 2650 static void qdf_dpt_display_ptr_record_debugfs(qdf_debugfs_file_t file, 2651 struct qdf_dp_trace_record_s *record, 2652 uint32_t index) 2653 { 2654 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2655 int loc; 2656 struct qdf_dp_trace_ptr_buf *buf = 2657 (struct qdf_dp_trace_ptr_buf *)record->data; 2658 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2659 index, 0, record); 2660 2661 if (loc < sizeof(prepend_str)) 2662 scnprintf(&prepend_str[loc], sizeof(prepend_str) - loc, 2663 "[msdu id %d %s %d]", 2664 buf->msdu_id, 2665 (record->code == 2666 QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) ? 2667 "status" : "vdev_id", 2668 buf->status); 2669 2670 qdf_dpt_dump_hex_trace_debugfs(file, prepend_str, 2671 (uint8_t *)&buf->cookie, 2672 sizeof(buf->cookie)); 2673 } 2674 2675 /** 2676 * qdf_dpt_display_ptr_record_debugfs() - display record 2677 * @file: file to read 2678 * @record: dptrace record 2679 * @index: index 2680 * 2681 * Return: none 2682 */ 2683 static void qdf_dpt_display_record_debugfs(qdf_debugfs_file_t file, 2684 struct qdf_dp_trace_record_s *record, 2685 uint32_t index) 2686 { 2687 int loc; 2688 char prepend_str[QDF_DP_TRACE_PREPEND_STR_SIZE]; 2689 struct qdf_dp_trace_data_buf *buf = 2690 (struct qdf_dp_trace_data_buf *)record->data; 2691 2692 loc = qdf_dp_trace_fill_meta_str(prepend_str, sizeof(prepend_str), 2693 index, 0, record); 2694 if (loc < sizeof(prepend_str)) 2695 loc += snprintf(&prepend_str[loc], sizeof(prepend_str) - loc, 2696 "[%d]", buf->msdu_id); 2697 qdf_dpt_dump_hex_trace_debugfs(file, prepend_str, 2698 record->data, record->size); 2699 } 2700 2701 uint32_t qdf_dpt_get_curr_pos_debugfs(qdf_debugfs_file_t file, 2702 enum qdf_dpt_debugfs_state state) 2703 { 2704 uint32_t i = 0; 2705 uint32_t tail; 2706 uint32_t count = g_qdf_dp_trace_data.num; 2707 2708 if (!g_qdf_dp_trace_data.enable) { 2709 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, 2710 "%s: Tracing Disabled", __func__); 2711 return QDF_STATUS_E_EMPTY; 2712 } 2713 2714 if (!count) { 2715 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_DEBUG, 2716 "%s: no packets", __func__); 2717 return QDF_STATUS_E_EMPTY; 2718 } 2719 2720 if (state == QDF_DPT_DEBUGFS_STATE_SHOW_IN_PROGRESS) 2721 return g_qdf_dp_trace_data.curr_pos; 2722 2723 qdf_debugfs_printf(file, 2724 "DPT: config - bitmap 0x%x verb %u #rec %u rec_requested %u live_config %u thresh %u time_limit %u\n", 2725 g_qdf_dp_trace_data.proto_bitmap, 2726 g_qdf_dp_trace_data.verbosity, 2727 g_qdf_dp_trace_data.no_of_record, 2728 g_qdf_dp_trace_data.num_records_to_dump, 2729 g_qdf_dp_trace_data.live_mode_config, 2730 g_qdf_dp_trace_data.high_tput_thresh, 2731 g_qdf_dp_trace_data.thresh_time_limit); 2732 2733 qdf_debugfs_printf(file, 2734 "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", 2735 g_qdf_dp_trace_data.icmp_req, 2736 g_qdf_dp_trace_data.icmp_resp, 2737 g_qdf_dp_trace_data.arp_req, 2738 g_qdf_dp_trace_data.arp_resp, 2739 g_qdf_dp_trace_data.icmpv6_req, 2740 g_qdf_dp_trace_data.icmpv6_resp, 2741 g_qdf_dp_trace_data.icmpv6_ns, 2742 g_qdf_dp_trace_data.icmpv6_na, 2743 g_qdf_dp_trace_data.icmpv6_rs, 2744 g_qdf_dp_trace_data.icmpv6_ra, 2745 g_qdf_dp_trace_data.dhcp_disc, 2746 g_qdf_dp_trace_data.dhcp_off, 2747 g_qdf_dp_trace_data.dhcp_req, 2748 g_qdf_dp_trace_data.dhcp_ack, 2749 g_qdf_dp_trace_data.dhcp_nack, 2750 g_qdf_dp_trace_data.dhcp_others, 2751 g_qdf_dp_trace_data.eapol_m1, 2752 g_qdf_dp_trace_data.eapol_m2, 2753 g_qdf_dp_trace_data.eapol_m3, 2754 g_qdf_dp_trace_data.eapol_m4, 2755 g_qdf_dp_trace_data.eapol_others); 2756 2757 qdf_debugfs_printf(file, 2758 "DPT: Total Records: %d, Head: %d, Tail: %d\n", 2759 g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head, 2760 g_qdf_dp_trace_data.tail); 2761 2762 spin_lock_bh(&l_dp_trace_lock); 2763 if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) { 2764 i = g_qdf_dp_trace_data.head; 2765 tail = g_qdf_dp_trace_data.tail; 2766 2767 if (count > g_qdf_dp_trace_data.num) 2768 count = g_qdf_dp_trace_data.num; 2769 2770 if (tail >= (count - 1)) 2771 i = tail - count + 1; 2772 else if (count != MAX_QDF_DP_TRACE_RECORDS) 2773 i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) - 2774 tail); 2775 g_qdf_dp_trace_data.curr_pos = 0; 2776 g_qdf_dp_trace_data.saved_tail = tail; 2777 } 2778 spin_unlock_bh(&l_dp_trace_lock); 2779 2780 return g_qdf_dp_trace_data.saved_tail; 2781 } 2782 qdf_export_symbol(qdf_dpt_get_curr_pos_debugfs); 2783 2784 QDF_STATUS qdf_dpt_dump_stats_debugfs(qdf_debugfs_file_t file, 2785 uint32_t curr_pos) 2786 { 2787 struct qdf_dp_trace_record_s p_record; 2788 uint32_t i = curr_pos; 2789 uint16_t num_records_to_dump = g_qdf_dp_trace_data.num_records_to_dump; 2790 2791 if (!g_qdf_dp_trace_data.enable) { 2792 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, 2793 "%s: Tracing Disabled", __func__); 2794 return QDF_STATUS_E_FAILURE; 2795 } 2796 2797 if (num_records_to_dump > g_qdf_dp_trace_data.num) 2798 num_records_to_dump = g_qdf_dp_trace_data.num; 2799 2800 /* 2801 * Max dp trace record size should always be less than 2802 * QDF_DP_TRACE_PREPEND_STR_SIZE(100) + BUFFER_SIZE(121). 2803 */ 2804 if (WARN_ON(QDF_DP_TRACE_MAX_RECORD_SIZE < 2805 QDF_DP_TRACE_PREPEND_STR_SIZE + BUFFER_SIZE)) 2806 return QDF_STATUS_E_FAILURE; 2807 2808 spin_lock_bh(&l_dp_trace_lock); 2809 p_record = g_qdf_dp_trace_tbl[i]; 2810 spin_unlock_bh(&l_dp_trace_lock); 2811 2812 for (;; ) { 2813 /* 2814 * Initially we get file as 1 page size, and 2815 * if remaining size in file is less than one record max size, 2816 * then return so that it gets an extra page. 2817 */ 2818 if ((file->size - file->count) < QDF_DP_TRACE_MAX_RECORD_SIZE) { 2819 spin_lock_bh(&l_dp_trace_lock); 2820 g_qdf_dp_trace_data.curr_pos = i; 2821 spin_unlock_bh(&l_dp_trace_lock); 2822 return QDF_STATUS_E_FAILURE; 2823 } 2824 2825 switch (p_record.code) { 2826 case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD: 2827 case QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD: 2828 case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD: 2829 qdf_dpt_display_ptr_record_debugfs(file, &p_record, i); 2830 break; 2831 2832 case QDF_DP_TRACE_EAPOL_PACKET_RECORD: 2833 case QDF_DP_TRACE_DHCP_PACKET_RECORD: 2834 case QDF_DP_TRACE_ARP_PACKET_RECORD: 2835 case QDF_DP_TRACE_ICMP_PACKET_RECORD: 2836 case QDF_DP_TRACE_ICMPv6_PACKET_RECORD: 2837 qdf_dpt_display_proto_pkt_debugfs(file, &p_record, i); 2838 break; 2839 2840 case QDF_DP_TRACE_TX_CREDIT_RECORD: 2841 qdf_dpt_display_credit_record_debugfs(file, &p_record, 2842 i); 2843 break; 2844 2845 case QDF_DP_TRACE_MGMT_PACKET_RECORD: 2846 qdf_dpt_display_mgmt_pkt_debugfs(file, &p_record, i); 2847 break; 2848 2849 case QDF_DP_TRACE_EVENT_RECORD: 2850 qdf_dpt_display_event_record_debugfs(file, &p_record, 2851 i); 2852 break; 2853 2854 case QDF_DP_TRACE_HDD_TX_TIMEOUT: 2855 qdf_debugfs_printf( 2856 file, "DPT: %04d: %llu %s\n", 2857 i, p_record.time, 2858 qdf_dp_code_to_string(p_record.code)); 2859 qdf_debugfs_printf(file, "HDD TX Timeout\n"); 2860 break; 2861 2862 case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT: 2863 qdf_debugfs_printf( 2864 file, "DPT: %04d: %llu %s\n", 2865 i, p_record.time, 2866 qdf_dp_code_to_string(p_record.code)); 2867 qdf_debugfs_printf(file, "HDD SoftAP TX Timeout\n"); 2868 break; 2869 2870 case QDF_DP_TRACE_CE_FAST_PACKET_ERR_RECORD: 2871 qdf_debugfs_printf( 2872 file, "DPT: %04d: %llu %s\n", 2873 i, p_record.time, 2874 qdf_dp_code_to_string(p_record.code)); 2875 qdf_debugfs_printf(file, "CE Fast Packet Error\n"); 2876 break; 2877 2878 case QDF_DP_TRACE_MAX: 2879 qdf_debugfs_printf(file, 2880 "%s: QDF_DP_TRACE_MAX event should not be generated\n", 2881 __func__); 2882 break; 2883 2884 case QDF_DP_TRACE_HDD_TX_PACKET_RECORD: 2885 case QDF_DP_TRACE_HDD_RX_PACKET_RECORD: 2886 case QDF_DP_TRACE_TX_PACKET_RECORD: 2887 case QDF_DP_TRACE_RX_PACKET_RECORD: 2888 case QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD: 2889 case QDF_DP_TRACE_LI_DP_RX_PACKET_RECORD: 2890 2891 default: 2892 qdf_dpt_display_record_debugfs(file, &p_record, i); 2893 break; 2894 } 2895 2896 if (++g_qdf_dp_trace_data.dump_counter == num_records_to_dump) 2897 break; 2898 2899 spin_lock_bh(&l_dp_trace_lock); 2900 if (i == 0) 2901 i = MAX_QDF_DP_TRACE_RECORDS; 2902 2903 i -= 1; 2904 p_record = g_qdf_dp_trace_tbl[i]; 2905 spin_unlock_bh(&l_dp_trace_lock); 2906 } 2907 2908 g_qdf_dp_trace_data.dump_counter = 0; 2909 2910 return QDF_STATUS_SUCCESS; 2911 } 2912 qdf_export_symbol(qdf_dpt_dump_stats_debugfs); 2913 2914 /** 2915 * qdf_dpt_set_value_debugfs() - Configure the value to control DP trace 2916 * @proto_bitmap: defines the protocol to be tracked 2917 * @no_of_records: defines the nth packet which is traced 2918 * @verbosity: defines the verbosity level 2919 * 2920 * Return: None 2921 */ 2922 void qdf_dpt_set_value_debugfs(uint8_t proto_bitmap, uint8_t no_of_record, 2923 uint8_t verbosity, uint16_t num_records_to_dump) 2924 { 2925 if (g_qdf_dp_trace_data.enable) { 2926 g_qdf_dp_trace_data.proto_bitmap = proto_bitmap; 2927 g_qdf_dp_trace_data.no_of_record = no_of_record; 2928 g_qdf_dp_trace_data.verbosity = verbosity; 2929 g_qdf_dp_trace_data.num_records_to_dump = num_records_to_dump; 2930 } 2931 } 2932 qdf_export_symbol(qdf_dpt_set_value_debugfs); 2933 2934 2935 /** 2936 * qdf_dp_trace_dump_all() - Dump data from ring buffer via call back functions 2937 * registered with QDF 2938 * @count: Number of lines to dump starting from tail to head 2939 * @pdev_id: pdev_id 2940 * 2941 * Return: None 2942 */ 2943 void qdf_dp_trace_dump_all(uint32_t count, uint8_t pdev_id) 2944 { 2945 struct qdf_dp_trace_record_s p_record; 2946 int32_t i, tail; 2947 2948 if (!g_qdf_dp_trace_data.enable) { 2949 DPTRACE_PRINT("Tracing Disabled"); 2950 return; 2951 } 2952 2953 DPTRACE_PRINT( 2954 "DPT: config - bitmap 0x%x verb %u #rec %u live_config %u thresh %u time_limit %u", 2955 g_qdf_dp_trace_data.proto_bitmap, 2956 g_qdf_dp_trace_data.verbosity, 2957 g_qdf_dp_trace_data.no_of_record, 2958 g_qdf_dp_trace_data.live_mode_config, 2959 g_qdf_dp_trace_data.high_tput_thresh, 2960 g_qdf_dp_trace_data.thresh_time_limit); 2961 2962 qdf_dp_trace_dump_stats(); 2963 2964 DPTRACE_PRINT("DPT: Total Records: %d, Head: %d, Tail: %d", 2965 g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head, 2966 g_qdf_dp_trace_data.tail); 2967 2968 /* aquire the lock so that only one thread at a time can read 2969 * the ring buffer 2970 */ 2971 spin_lock_bh(&l_dp_trace_lock); 2972 2973 if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) { 2974 i = g_qdf_dp_trace_data.head; 2975 tail = g_qdf_dp_trace_data.tail; 2976 2977 if (count) { 2978 if (count > g_qdf_dp_trace_data.num) 2979 count = g_qdf_dp_trace_data.num; 2980 if (tail >= (count - 1)) 2981 i = tail - count + 1; 2982 else if (count != MAX_QDF_DP_TRACE_RECORDS) 2983 i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) - 2984 tail); 2985 } 2986 2987 p_record = g_qdf_dp_trace_tbl[i]; 2988 spin_unlock_bh(&l_dp_trace_lock); 2989 for (;; ) { 2990 qdf_dp_trace_cb_table[p_record.code](&p_record, 2991 (uint16_t)i, pdev_id, false); 2992 if (i == tail) 2993 break; 2994 i += 1; 2995 2996 spin_lock_bh(&l_dp_trace_lock); 2997 if (MAX_QDF_DP_TRACE_RECORDS == i) 2998 i = 0; 2999 3000 p_record = g_qdf_dp_trace_tbl[i]; 3001 spin_unlock_bh(&l_dp_trace_lock); 3002 } 3003 } else { 3004 spin_unlock_bh(&l_dp_trace_lock); 3005 } 3006 } 3007 qdf_export_symbol(qdf_dp_trace_dump_all); 3008 3009 /** 3010 * qdf_dp_trace_throttle_live_mode() - Throttle DP Trace live mode 3011 * @high_bw_request: whether this is a high BW req or not 3012 * 3013 * The function tries to prevent excessive logging into the live buffer by 3014 * having an upper limit on number of packets that can be logged per second. 3015 * 3016 * The intention is to allow occasional pings and data packets and really low 3017 * throughput levels while suppressing bursts and higher throughput levels so 3018 * that we donot hog the live buffer. 3019 * 3020 * If the number of packets printed in a particular second exceeds the thresh, 3021 * disable printing in the next second. 3022 * 3023 * Return: None 3024 */ 3025 void qdf_dp_trace_throttle_live_mode(bool high_bw_request) 3026 { 3027 static int bw_interval_counter; 3028 3029 if (g_qdf_dp_trace_data.enable == false || 3030 g_qdf_dp_trace_data.live_mode_config == false) 3031 return; 3032 3033 if (high_bw_request) { 3034 g_qdf_dp_trace_data.live_mode = 0; 3035 bw_interval_counter = 0; 3036 return; 3037 } 3038 3039 bw_interval_counter++; 3040 3041 if (0 == (bw_interval_counter % 3042 g_qdf_dp_trace_data.thresh_time_limit)) { 3043 3044 spin_lock_bh(&l_dp_trace_lock); 3045 if (g_qdf_dp_trace_data.print_pkt_cnt <= 3046 g_qdf_dp_trace_data.high_tput_thresh) 3047 g_qdf_dp_trace_data.live_mode = 1; 3048 3049 g_qdf_dp_trace_data.print_pkt_cnt = 0; 3050 spin_unlock_bh(&l_dp_trace_lock); 3051 } 3052 } 3053 qdf_export_symbol(qdf_dp_trace_throttle_live_mode); 3054 3055 void qdf_dp_trace_apply_tput_policy(bool is_data_traffic) 3056 { 3057 if (g_qdf_dp_trace_data.dynamic_verbosity_modify) { 3058 goto check_live_mode; 3059 return; 3060 } 3061 3062 if (is_data_traffic) { 3063 g_qdf_dp_trace_data.verbosity = 3064 QDF_DP_TRACE_VERBOSITY_ULTRA_LOW; 3065 } else { 3066 g_qdf_dp_trace_data.verbosity = 3067 g_qdf_dp_trace_data.ini_conf_verbosity; 3068 } 3069 check_live_mode: 3070 qdf_dp_trace_throttle_live_mode(is_data_traffic); 3071 } 3072 #endif 3073 3074 struct qdf_print_ctrl print_ctrl_obj[MAX_PRINT_CONFIG_SUPPORTED]; 3075 3076 struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = { 3077 [QDF_MODULE_ID_TDLS] = {"tdls"}, 3078 [QDF_MODULE_ID_ACS] = {"ACS"}, 3079 [QDF_MODULE_ID_SCAN_SM] = {"scan state machine"}, 3080 [QDF_MODULE_ID_SCANENTRY] = {"scan entry"}, 3081 [QDF_MODULE_ID_WDS] = {"WDS"}, 3082 [QDF_MODULE_ID_ACTION] = {"action"}, 3083 [QDF_MODULE_ID_ROAM] = {"STA roaming"}, 3084 [QDF_MODULE_ID_INACT] = {"inactivity"}, 3085 [QDF_MODULE_ID_DOTH] = {"11h"}, 3086 [QDF_MODULE_ID_IQUE] = {"IQUE"}, 3087 [QDF_MODULE_ID_WME] = {"WME"}, 3088 [QDF_MODULE_ID_ACL] = {"ACL"}, 3089 [QDF_MODULE_ID_WPA] = {"WPA/RSN"}, 3090 [QDF_MODULE_ID_RADKEYS] = {"dump 802.1x keys"}, 3091 [QDF_MODULE_ID_RADDUMP] = {"dump radius packet"}, 3092 [QDF_MODULE_ID_RADIUS] = {"802.1x radius client"}, 3093 [QDF_MODULE_ID_DOT1XSM] = {"802.1x state machine"}, 3094 [QDF_MODULE_ID_DOT1X] = {"802.1x authenticator"}, 3095 [QDF_MODULE_ID_POWER] = {"power save"}, 3096 [QDF_MODULE_ID_STATE] = {"state"}, 3097 [QDF_MODULE_ID_OUTPUT] = {"output"}, 3098 [QDF_MODULE_ID_SCAN] = {"scan"}, 3099 [QDF_MODULE_ID_AUTH] = {"authentication"}, 3100 [QDF_MODULE_ID_ASSOC] = {"association"}, 3101 [QDF_MODULE_ID_NODE] = {"node"}, 3102 [QDF_MODULE_ID_ELEMID] = {"element ID"}, 3103 [QDF_MODULE_ID_XRATE] = {"rate"}, 3104 [QDF_MODULE_ID_INPUT] = {"input"}, 3105 [QDF_MODULE_ID_CRYPTO] = {"crypto"}, 3106 [QDF_MODULE_ID_DUMPPKTS] = {"dump packet"}, 3107 [QDF_MODULE_ID_DEBUG] = {"debug"}, 3108 [QDF_MODULE_ID_MLME] = {"mlme"}, 3109 [QDF_MODULE_ID_RRM] = {"rrm"}, 3110 [QDF_MODULE_ID_WNM] = {"wnm"}, 3111 [QDF_MODULE_ID_P2P_PROT] = {"p2p_prot"}, 3112 [QDF_MODULE_ID_PROXYARP] = {"proxyarp"}, 3113 [QDF_MODULE_ID_L2TIF] = {"l2tif"}, 3114 [QDF_MODULE_ID_WIFIPOS] = {"wifipos"}, 3115 [QDF_MODULE_ID_WRAP] = {"wrap"}, 3116 [QDF_MODULE_ID_DFS] = {"dfs"}, 3117 [QDF_MODULE_ID_ATF] = {"atf"}, 3118 [QDF_MODULE_ID_SPLITMAC] = {"splitmac"}, 3119 [QDF_MODULE_ID_IOCTL] = {"ioctl"}, 3120 [QDF_MODULE_ID_NAC] = {"nac"}, 3121 [QDF_MODULE_ID_MESH] = {"mesh"}, 3122 [QDF_MODULE_ID_MBO] = {"mbo"}, 3123 [QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = {"extchanswitch"}, 3124 [QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = {"extchanscan"}, 3125 [QDF_MODULE_ID_TLSHIM] = {"tlshim"}, 3126 [QDF_MODULE_ID_WMI] = {"WMI"}, 3127 [QDF_MODULE_ID_HTT] = {"HTT"}, 3128 [QDF_MODULE_ID_HDD] = {"HDD"}, 3129 [QDF_MODULE_ID_SME] = {"SME"}, 3130 [QDF_MODULE_ID_PE] = {"PE"}, 3131 [QDF_MODULE_ID_WMA] = {"WMA"}, 3132 [QDF_MODULE_ID_SYS] = {"SYS"}, 3133 [QDF_MODULE_ID_QDF] = {"QDF"}, 3134 [QDF_MODULE_ID_SAP] = {"SAP"}, 3135 [QDF_MODULE_ID_HDD_SOFTAP] = {"HDD_SAP"}, 3136 [QDF_MODULE_ID_HDD_DATA] = {"DATA"}, 3137 [QDF_MODULE_ID_HDD_SAP_DATA] = {"SAP_DATA"}, 3138 [QDF_MODULE_ID_HIF] = {"HIF"}, 3139 [QDF_MODULE_ID_HTC] = {"HTC"}, 3140 [QDF_MODULE_ID_TXRX] = {"TXRX"}, 3141 [QDF_MODULE_ID_QDF_DEVICE] = {"QDF_DEV"}, 3142 [QDF_MODULE_ID_CFG] = {"CFG"}, 3143 [QDF_MODULE_ID_BMI] = {"BMI"}, 3144 [QDF_MODULE_ID_EPPING] = {"EPPING"}, 3145 [QDF_MODULE_ID_QVIT] = {"QVIT"}, 3146 [QDF_MODULE_ID_DP] = {"DP"}, 3147 [QDF_MODULE_ID_HAL] = {"HAL"}, 3148 [QDF_MODULE_ID_SOC] = {"SOC"}, 3149 [QDF_MODULE_ID_OS_IF] = {"OSIF"}, 3150 [QDF_MODULE_ID_TARGET_IF] = {"TIF"}, 3151 [QDF_MODULE_ID_SCHEDULER] = {"SCH"}, 3152 [QDF_MODULE_ID_MGMT_TXRX] = {"MGMT_TXRX"}, 3153 [QDF_MODULE_ID_PMO] = {"PMO"}, 3154 [QDF_MODULE_ID_POLICY_MGR] = {"POLICY_MGR"}, 3155 [QDF_MODULE_ID_SA_API] = {"SA_API"}, 3156 [QDF_MODULE_ID_NAN] = {"NAN"}, 3157 [QDF_MODULE_ID_SPECTRAL] = {"SPECTRAL"}, 3158 [QDF_MODULE_ID_P2P] = {"P2P"}, 3159 [QDF_MODULE_ID_OFFCHAN_TXRX] = {"OFFCHAN"}, 3160 [QDF_MODULE_ID_REGULATORY] = {"REGULATORY"}, 3161 [QDF_MODULE_ID_OBJ_MGR] = {"OBJMGR"}, 3162 [QDF_MODULE_ID_SERIALIZATION] = {"SER"}, 3163 [QDF_MODULE_ID_NSS] = {"NSS"}, 3164 [QDF_MODULE_ID_ROAM_DEBUG] = {"roam debug"}, 3165 [QDF_MODULE_ID_DIRECT_BUF_RX] = {"DIRECT_BUF_RX"}, 3166 [QDF_MODULE_ID_DISA] = {"disa"}, 3167 [QDF_MODULE_ID_GREEN_AP] = {"GREEN_AP"}, 3168 [QDF_MODULE_ID_EXTAP] = {"EXTAP"}, 3169 [QDF_MODULE_ID_FD] = {"FILS discovery"}, 3170 [QDF_MODULE_ID_FTM] = {"FTM"}, 3171 [QDF_MODULE_ID_OCB] = {"OCB"}, 3172 [QDF_MODULE_ID_CONFIG] = {"CONFIG"}, 3173 [QDF_MODULE_ID_IPA] = {"IPA"}, 3174 [QDF_MODULE_ID_CP_STATS] = {"CP_STATS"}, 3175 [QDF_MODULE_ID_DCS] = {"DCS"}, 3176 [QDF_MODULE_ID_ACTION_OUI] = {"action_oui"}, 3177 [QDF_MODULE_ID_TARGET] = {"TARGET"}, 3178 [QDF_MODULE_ID_MBSSIE] = {"MBSSIE"}, 3179 [QDF_MODULE_ID_FWOL] = {"fwol"}, 3180 [QDF_MODULE_ID_SM_ENGINE] = {"SM_ENG"}, 3181 [QDF_MODULE_ID_CMN_MLME] = {"CMN_MLME"}, 3182 [QDF_MODULE_ID_BSSCOLOR] = {"BSSCOLOR"}, 3183 [QDF_MODULE_ID_CFR] = {"CFR"}, 3184 [QDF_MODULE_ID_TX_CAPTURE] = {"TX_CAPTURE_ENHANCE"}, 3185 [QDF_MODULE_ID_INTEROP_ISSUES_AP] = {"INTEROP_ISSUES_AP"}, 3186 [QDF_MODULE_ID_BLACKLIST_MGR] = {"blm"}, 3187 [QDF_MODULE_ID_QLD] = {"QLD"}, 3188 [QDF_MODULE_ID_DYNAMIC_MODE_CHG] = {"Dynamic Mode Change"}, 3189 [QDF_MODULE_ID_COEX] = {"COEX"}, 3190 [QDF_MODULE_ID_MON_FILTER] = {"Monitor Filter"}, 3191 [QDF_MODULE_ID_ANY] = {"ANY"}, 3192 [QDF_MODULE_ID_PKT_CAPTURE] = {"pkt_capture"}, 3193 [QDF_MODULE_ID_RPTR] = {"RPTR"}, 3194 [QDF_MODULE_ID_6GHZ] = {"6GHZ"}, 3195 [QDF_MODULE_ID_IOT_SIM] = {"IOT_SIM"}, 3196 }; 3197 qdf_export_symbol(g_qdf_category_name); 3198 3199 /** 3200 * qdf_trace_display() - Display trace 3201 * 3202 * Return: None 3203 */ 3204 void qdf_trace_display(void) 3205 { 3206 QDF_MODULE_ID module_id; 3207 3208 pr_err(" 1)FATAL 2)ERROR 3)WARN 4)INFO 5)INFO_H 6)INFO_M 7)INFO_L 8)DEBUG\n"); 3209 for (module_id = 0; module_id < QDF_MODULE_ID_MAX; ++module_id) { 3210 pr_err("%2d)%s %s %s %s %s %s %s %s %s\n", 3211 (int)module_id, 3212 g_qdf_category_name[module_id].category_name_str, 3213 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3214 QDF_TRACE_LEVEL_FATAL) ? "X" : " ", 3215 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3216 QDF_TRACE_LEVEL_ERROR) ? "X" : " ", 3217 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3218 QDF_TRACE_LEVEL_WARN) ? "X" : " ", 3219 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3220 QDF_TRACE_LEVEL_INFO) ? "X" : " ", 3221 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3222 QDF_TRACE_LEVEL_INFO_HIGH) ? "X" : " ", 3223 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3224 QDF_TRACE_LEVEL_INFO_MED) ? "X" : " ", 3225 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3226 QDF_TRACE_LEVEL_INFO_LOW) ? "X" : " ", 3227 qdf_print_is_verbose_enabled(qdf_pidx, module_id, 3228 QDF_TRACE_LEVEL_DEBUG) ? "X" : " "); 3229 } 3230 } 3231 qdf_export_symbol(qdf_trace_display); 3232 3233 #ifdef QDF_TRACE_PRINT_ENABLE 3234 static inline void print_to_console(char *str_buffer) 3235 { 3236 pr_err("%s\n", str_buffer); 3237 } 3238 #else 3239 3240 #define print_to_console(str) 3241 #endif 3242 3243 #ifdef MULTI_IF_NAME 3244 static const char *qdf_trace_wlan_modname(void) 3245 { 3246 return MULTI_IF_NAME; 3247 } 3248 #else 3249 static const char *qdf_trace_wlan_modname(void) 3250 { 3251 return "wlan"; 3252 } 3253 #endif 3254 3255 void qdf_trace_msg_cmn(unsigned int idx, 3256 QDF_MODULE_ID category, 3257 QDF_TRACE_LEVEL verbose, 3258 const char *str_format, va_list val) 3259 { 3260 char str_buffer[QDF_TRACE_BUFFER_SIZE]; 3261 int n; 3262 3263 /* Check if index passed is valid */ 3264 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 3265 pr_info("%s: Invalid index - %d\n", __func__, idx); 3266 return; 3267 } 3268 3269 /* Check if print control object is in use */ 3270 if (!print_ctrl_obj[idx].in_use) { 3271 pr_info("%s: Invalid print control object\n", __func__); 3272 return; 3273 } 3274 3275 /* Check if category passed is valid */ 3276 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) { 3277 vscnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, str_format, val); 3278 pr_info("%s: Invalid category: %d, log: %s\n", 3279 __func__, category, str_buffer); 3280 return; 3281 } 3282 3283 /* Check if verbose mask is valid */ 3284 if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) { 3285 vscnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, str_format, val); 3286 pr_info("%s: Invalid verbose level %d, log: %s\n", 3287 __func__, verbose, str_buffer); 3288 return; 3289 } 3290 3291 /* 3292 * Print the trace message when the desired verbose level is set in 3293 * the desired category for the print control object 3294 */ 3295 if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask & 3296 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) { 3297 static const char * const VERBOSE_STR[] = { 3298 [QDF_TRACE_LEVEL_NONE] = "", 3299 [QDF_TRACE_LEVEL_FATAL] = "F", 3300 [QDF_TRACE_LEVEL_ERROR] = "E", 3301 [QDF_TRACE_LEVEL_WARN] = "W", 3302 [QDF_TRACE_LEVEL_INFO] = "I", 3303 [QDF_TRACE_LEVEL_INFO_HIGH] = "IH", 3304 [QDF_TRACE_LEVEL_INFO_MED] = "IM", 3305 [QDF_TRACE_LEVEL_INFO_LOW] = "IL", 3306 [QDF_TRACE_LEVEL_DEBUG] = "D", 3307 [QDF_TRACE_LEVEL_TRACE] = "T", 3308 [QDF_TRACE_LEVEL_ALL] = "" }; 3309 3310 /* print the prefix string into the string buffer... */ 3311 n = scnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, 3312 "%s: [%d:%s:%s] ", qdf_trace_wlan_modname(), 3313 in_interrupt() ? 0 : current->pid, 3314 VERBOSE_STR[verbose], 3315 g_qdf_category_name[category].category_name_str); 3316 3317 /* print the formatted log message after the prefix string */ 3318 vscnprintf(str_buffer + n, QDF_TRACE_BUFFER_SIZE - n, 3319 str_format, val); 3320 #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE) 3321 wlan_log_to_user(verbose, (char *)str_buffer, 3322 strlen(str_buffer)); 3323 if (qdf_unlikely(qdf_log_dump_at_kernel_enable)) 3324 print_to_console(str_buffer); 3325 #else 3326 pr_err("%s\n", str_buffer); 3327 #endif 3328 } 3329 } 3330 qdf_export_symbol(qdf_trace_msg_cmn); 3331 3332 QDF_STATUS qdf_print_setup(void) 3333 { 3334 int i; 3335 3336 /* Loop through all print ctrl objects */ 3337 for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) { 3338 if (qdf_print_ctrl_cleanup(i)) 3339 return QDF_STATUS_E_FAILURE; 3340 } 3341 return QDF_STATUS_SUCCESS; 3342 } 3343 qdf_export_symbol(qdf_print_setup); 3344 3345 QDF_STATUS qdf_print_ctrl_cleanup(unsigned int idx) 3346 { 3347 int i = 0; 3348 3349 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 3350 pr_info("%s: Invalid index - %d\n", __func__, idx); 3351 return QDF_STATUS_E_FAILURE; 3352 } 3353 3354 /* Clean up the print control object corresponding to that index 3355 * If success, callee to change print control index to -1 3356 */ 3357 3358 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) { 3359 print_ctrl_obj[idx].cat_info[i].category_verbose_mask = 3360 QDF_TRACE_LEVEL_NONE; 3361 } 3362 print_ctrl_obj[idx].custom_print = NULL; 3363 print_ctrl_obj[idx].custom_ctxt = NULL; 3364 qdf_print_clean_node_flag(idx); 3365 print_ctrl_obj[idx].in_use = false; 3366 3367 return QDF_STATUS_SUCCESS; 3368 } 3369 qdf_export_symbol(qdf_print_ctrl_cleanup); 3370 3371 int qdf_print_ctrl_register(const struct category_info *cinfo, 3372 void *custom_print_handler, 3373 void *custom_ctx, 3374 const char *pctrl_name) 3375 { 3376 int idx = -1; 3377 int i = 0; 3378 3379 for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) { 3380 if (!print_ctrl_obj[i].in_use) { 3381 idx = i; 3382 break; 3383 } 3384 } 3385 3386 /* Callee to handle idx -1 appropriately */ 3387 if (idx == -1) { 3388 pr_info("%s: Allocation failed! No print control object free\n", 3389 __func__); 3390 return idx; 3391 } 3392 3393 print_ctrl_obj[idx].in_use = true; 3394 3395 /* 3396 * In case callee does not pass category info, 3397 * custom print handler, custom context and print control name, 3398 * we do not set any value here. Clean up for the print control 3399 * getting allocated would have taken care of initializing 3400 * default values. 3401 * 3402 * We need to only set in_use to 1 in such a case 3403 */ 3404 3405 if (pctrl_name) { 3406 qdf_str_lcopy(print_ctrl_obj[idx].name, pctrl_name, 3407 sizeof(print_ctrl_obj[idx].name)); 3408 } 3409 3410 if (custom_print_handler) 3411 print_ctrl_obj[idx].custom_print = custom_print_handler; 3412 3413 if (custom_ctx) 3414 print_ctrl_obj[idx].custom_ctxt = custom_ctx; 3415 3416 if (cinfo) { 3417 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) { 3418 if (cinfo[i].category_verbose_mask == 3419 QDF_TRACE_LEVEL_ALL) { 3420 print_ctrl_obj[idx].cat_info[i] 3421 .category_verbose_mask = 0xFFFF; 3422 } else if ((cinfo[i].category_verbose_mask == 3423 QDF_TRACE_LEVEL_NONE) || 3424 (cinfo[i].category_verbose_mask == 3425 QDF_TRACE_LEVEL_TO_MODULE_BITMASK( 3426 QDF_TRACE_LEVEL_NONE))) { 3427 print_ctrl_obj[idx].cat_info[i] 3428 .category_verbose_mask = 0; 3429 } else { 3430 print_ctrl_obj[idx].cat_info[i] 3431 .category_verbose_mask = 3432 cinfo[i].category_verbose_mask; 3433 } 3434 } 3435 } 3436 3437 return idx; 3438 } 3439 qdf_export_symbol(qdf_print_ctrl_register); 3440 3441 #ifdef QDF_TRACE_PRINT_ENABLE 3442 void qdf_shared_print_ctrl_cleanup(void) 3443 { 3444 qdf_print_ctrl_cleanup(qdf_pidx); 3445 } 3446 qdf_export_symbol(qdf_shared_print_ctrl_cleanup); 3447 3448 /* 3449 * Set this to invalid value to differentiate with user-provided 3450 * value. 3451 */ 3452 int qdf_dbg_mask = QDF_TRACE_LEVEL_MAX; 3453 qdf_export_symbol(qdf_dbg_mask); 3454 qdf_declare_param(qdf_dbg_mask, int); 3455 3456 /* 3457 * QDF can be passed parameters which indicate the 3458 * debug level for each module. 3459 * an array of string values are passed, each string hold the following form 3460 * 3461 * <module name string>=<integer debug level value> 3462 * 3463 * The array qdf_dbg_arr will hold these module-string=value strings 3464 * The variable qdf_dbg_arr_cnt will have the count of how many such 3465 * string values were passed. 3466 */ 3467 static char *qdf_dbg_arr[QDF_MODULE_ID_MAX]; 3468 static int qdf_dbg_arr_cnt; 3469 qdf_declare_param_array(qdf_dbg_arr, charp, &qdf_dbg_arr_cnt); 3470 3471 static uint16_t set_cumulative_verbose_mask(QDF_TRACE_LEVEL max_level) 3472 { 3473 uint16_t category_verbose_mask = 0; 3474 QDF_TRACE_LEVEL level; 3475 3476 for (level = QDF_TRACE_LEVEL_FATAL; level <= max_level; level++) { 3477 category_verbose_mask |= 3478 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level); 3479 } 3480 return category_verbose_mask; 3481 } 3482 3483 static QDF_MODULE_ID find_qdf_module_from_string(char *str) 3484 { 3485 QDF_MODULE_ID mod_id; 3486 3487 for (mod_id = 0; mod_id < QDF_MODULE_ID_MAX; mod_id++) { 3488 if (strcasecmp(str, 3489 g_qdf_category_name[mod_id].category_name_str) 3490 == 0) { 3491 break; 3492 } 3493 } 3494 return mod_id; 3495 } 3496 3497 static void process_qdf_dbg_arr_param(struct category_info *cinfo, 3498 int array_index) 3499 { 3500 char *mod_val_str, *mod_str, *val_str; 3501 unsigned long dbg_level; 3502 QDF_MODULE_ID mod_id; 3503 3504 mod_val_str = qdf_dbg_arr[array_index]; 3505 mod_str = strsep(&mod_val_str, "="); 3506 val_str = mod_val_str; 3507 if (!val_str) { 3508 pr_info("qdf_dbg_arr: %s not in the <mod>=<val> form\n", 3509 mod_str); 3510 return; 3511 } 3512 3513 mod_id = find_qdf_module_from_string(mod_str); 3514 if (mod_id >= QDF_MODULE_ID_MAX) { 3515 pr_info("ERROR!!Module name %s not in the list of modules\n", 3516 mod_str); 3517 return; 3518 } 3519 3520 if (kstrtol(val_str, 10, &dbg_level) < 0) { 3521 pr_info("ERROR!!Invalid debug level for module: %s\n", 3522 mod_str); 3523 return; 3524 } 3525 3526 if (dbg_level >= QDF_TRACE_LEVEL_MAX) { 3527 pr_info("ERROR!!Debug level for %s too high", mod_str); 3528 pr_info("max: %d given %lu\n", QDF_TRACE_LEVEL_MAX, 3529 dbg_level); 3530 return; 3531 } 3532 3533 pr_info("User passed setting module %s(%d) to level %lu\n", 3534 mod_str, 3535 mod_id, 3536 dbg_level); 3537 cinfo[mod_id].category_verbose_mask = 3538 set_cumulative_verbose_mask((QDF_TRACE_LEVEL)dbg_level); 3539 } 3540 3541 static void set_default_trace_levels(struct category_info *cinfo) 3542 { 3543 int i; 3544 static QDF_TRACE_LEVEL module_trace_default_level[QDF_MODULE_ID_MAX] = { 3545 [QDF_MODULE_ID_TDLS] = QDF_TRACE_LEVEL_NONE, 3546 [QDF_MODULE_ID_ACS] = QDF_TRACE_LEVEL_NONE, 3547 [QDF_MODULE_ID_SCAN_SM] = QDF_TRACE_LEVEL_NONE, 3548 [QDF_MODULE_ID_SCANENTRY] = QDF_TRACE_LEVEL_NONE, 3549 [QDF_MODULE_ID_WDS] = QDF_TRACE_LEVEL_NONE, 3550 [QDF_MODULE_ID_ACTION] = QDF_TRACE_LEVEL_NONE, 3551 [QDF_MODULE_ID_ROAM] = QDF_TRACE_LEVEL_NONE, 3552 [QDF_MODULE_ID_INACT] = QDF_TRACE_LEVEL_NONE, 3553 [QDF_MODULE_ID_DOTH] = QDF_TRACE_LEVEL_NONE, 3554 [QDF_MODULE_ID_IQUE] = QDF_TRACE_LEVEL_NONE, 3555 [QDF_MODULE_ID_WME] = QDF_TRACE_LEVEL_NONE, 3556 [QDF_MODULE_ID_ACL] = QDF_TRACE_LEVEL_NONE, 3557 [QDF_MODULE_ID_WPA] = QDF_TRACE_LEVEL_NONE, 3558 [QDF_MODULE_ID_RADKEYS] = QDF_TRACE_LEVEL_NONE, 3559 [QDF_MODULE_ID_RADDUMP] = QDF_TRACE_LEVEL_NONE, 3560 [QDF_MODULE_ID_RADIUS] = QDF_TRACE_LEVEL_NONE, 3561 [QDF_MODULE_ID_DOT1XSM] = QDF_TRACE_LEVEL_NONE, 3562 [QDF_MODULE_ID_DOT1X] = QDF_TRACE_LEVEL_NONE, 3563 [QDF_MODULE_ID_POWER] = QDF_TRACE_LEVEL_NONE, 3564 [QDF_MODULE_ID_STATE] = QDF_TRACE_LEVEL_NONE, 3565 [QDF_MODULE_ID_OUTPUT] = QDF_TRACE_LEVEL_NONE, 3566 [QDF_MODULE_ID_SCAN] = QDF_TRACE_LEVEL_ERROR, 3567 [QDF_MODULE_ID_AUTH] = QDF_TRACE_LEVEL_NONE, 3568 [QDF_MODULE_ID_ASSOC] = QDF_TRACE_LEVEL_NONE, 3569 [QDF_MODULE_ID_NODE] = QDF_TRACE_LEVEL_NONE, 3570 [QDF_MODULE_ID_ELEMID] = QDF_TRACE_LEVEL_NONE, 3571 [QDF_MODULE_ID_XRATE] = QDF_TRACE_LEVEL_NONE, 3572 [QDF_MODULE_ID_INPUT] = QDF_TRACE_LEVEL_NONE, 3573 [QDF_MODULE_ID_CRYPTO] = QDF_TRACE_LEVEL_NONE, 3574 [QDF_MODULE_ID_DUMPPKTS] = QDF_TRACE_LEVEL_NONE, 3575 [QDF_MODULE_ID_DEBUG] = QDF_TRACE_LEVEL_NONE, 3576 [QDF_MODULE_ID_MLME] = QDF_TRACE_LEVEL_ERROR, 3577 [QDF_MODULE_ID_RRM] = QDF_TRACE_LEVEL_NONE, 3578 [QDF_MODULE_ID_WNM] = QDF_TRACE_LEVEL_NONE, 3579 [QDF_MODULE_ID_P2P_PROT] = QDF_TRACE_LEVEL_NONE, 3580 [QDF_MODULE_ID_PROXYARP] = QDF_TRACE_LEVEL_NONE, 3581 [QDF_MODULE_ID_L2TIF] = QDF_TRACE_LEVEL_NONE, 3582 [QDF_MODULE_ID_WIFIPOS] = QDF_TRACE_LEVEL_NONE, 3583 [QDF_MODULE_ID_WRAP] = QDF_TRACE_LEVEL_NONE, 3584 [QDF_MODULE_ID_DFS] = QDF_TRACE_LEVEL_NONE, 3585 [QDF_MODULE_ID_ATF] = QDF_TRACE_LEVEL_ERROR, 3586 [QDF_MODULE_ID_SPLITMAC] = QDF_TRACE_LEVEL_NONE, 3587 [QDF_MODULE_ID_IOCTL] = QDF_TRACE_LEVEL_NONE, 3588 [QDF_MODULE_ID_NAC] = QDF_TRACE_LEVEL_NONE, 3589 [QDF_MODULE_ID_MESH] = QDF_TRACE_LEVEL_NONE, 3590 [QDF_MODULE_ID_MBO] = QDF_TRACE_LEVEL_NONE, 3591 [QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = QDF_TRACE_LEVEL_NONE, 3592 [QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = QDF_TRACE_LEVEL_NONE, 3593 [QDF_MODULE_ID_TLSHIM] = QDF_TRACE_LEVEL_NONE, 3594 [QDF_MODULE_ID_WMI] = QDF_TRACE_LEVEL_ERROR, 3595 [QDF_MODULE_ID_HTT] = QDF_TRACE_LEVEL_NONE, 3596 [QDF_MODULE_ID_HDD] = QDF_TRACE_LEVEL_NONE, 3597 [QDF_MODULE_ID_SME] = QDF_TRACE_LEVEL_NONE, 3598 [QDF_MODULE_ID_PE] = QDF_TRACE_LEVEL_NONE, 3599 [QDF_MODULE_ID_WMA] = QDF_TRACE_LEVEL_NONE, 3600 [QDF_MODULE_ID_SYS] = QDF_TRACE_LEVEL_NONE, 3601 [QDF_MODULE_ID_QDF] = QDF_TRACE_LEVEL_ERROR, 3602 [QDF_MODULE_ID_SAP] = QDF_TRACE_LEVEL_NONE, 3603 [QDF_MODULE_ID_HDD_SOFTAP] = QDF_TRACE_LEVEL_NONE, 3604 [QDF_MODULE_ID_HDD_DATA] = QDF_TRACE_LEVEL_NONE, 3605 [QDF_MODULE_ID_HDD_SAP_DATA] = QDF_TRACE_LEVEL_NONE, 3606 [QDF_MODULE_ID_HIF] = QDF_TRACE_LEVEL_ERROR, 3607 [QDF_MODULE_ID_HTC] = QDF_TRACE_LEVEL_NONE, 3608 [QDF_MODULE_ID_TXRX] = QDF_TRACE_LEVEL_NONE, 3609 [QDF_MODULE_ID_QDF_DEVICE] = QDF_TRACE_LEVEL_NONE, 3610 [QDF_MODULE_ID_CFG] = QDF_TRACE_LEVEL_NONE, 3611 [QDF_MODULE_ID_BMI] = QDF_TRACE_LEVEL_NONE, 3612 [QDF_MODULE_ID_EPPING] = QDF_TRACE_LEVEL_NONE, 3613 [QDF_MODULE_ID_QVIT] = QDF_TRACE_LEVEL_NONE, 3614 [QDF_MODULE_ID_DP] = QDF_TRACE_LEVEL_FATAL, 3615 [QDF_MODULE_ID_HAL] = QDF_TRACE_LEVEL_NONE, 3616 [QDF_MODULE_ID_SOC] = QDF_TRACE_LEVEL_NONE, 3617 [QDF_MODULE_ID_OS_IF] = QDF_TRACE_LEVEL_NONE, 3618 [QDF_MODULE_ID_TARGET_IF] = QDF_TRACE_LEVEL_INFO, 3619 [QDF_MODULE_ID_SCHEDULER] = QDF_TRACE_LEVEL_FATAL, 3620 [QDF_MODULE_ID_MGMT_TXRX] = QDF_TRACE_LEVEL_NONE, 3621 [QDF_MODULE_ID_SERIALIZATION] = QDF_TRACE_LEVEL_ERROR, 3622 [QDF_MODULE_ID_PMO] = QDF_TRACE_LEVEL_NONE, 3623 [QDF_MODULE_ID_P2P] = QDF_TRACE_LEVEL_NONE, 3624 [QDF_MODULE_ID_POLICY_MGR] = QDF_TRACE_LEVEL_NONE, 3625 [QDF_MODULE_ID_CONFIG] = QDF_TRACE_LEVEL_ERROR, 3626 [QDF_MODULE_ID_REGULATORY] = QDF_TRACE_LEVEL_NONE, 3627 [QDF_MODULE_ID_SA_API] = QDF_TRACE_LEVEL_NONE, 3628 [QDF_MODULE_ID_NAN] = QDF_TRACE_LEVEL_NONE, 3629 [QDF_MODULE_ID_OFFCHAN_TXRX] = QDF_TRACE_LEVEL_NONE, 3630 [QDF_MODULE_ID_SON] = QDF_TRACE_LEVEL_NONE, 3631 [QDF_MODULE_ID_SPECTRAL] = QDF_TRACE_LEVEL_ERROR, 3632 [QDF_MODULE_ID_OBJ_MGR] = QDF_TRACE_LEVEL_FATAL, 3633 [QDF_MODULE_ID_NSS] = QDF_TRACE_LEVEL_ERROR, 3634 [QDF_MODULE_ID_ROAM_DEBUG] = QDF_TRACE_LEVEL_ERROR, 3635 [QDF_MODULE_ID_CDP] = QDF_TRACE_LEVEL_NONE, 3636 [QDF_MODULE_ID_DIRECT_BUF_RX] = QDF_TRACE_LEVEL_ERROR, 3637 [QDF_MODULE_ID_DISA] = QDF_TRACE_LEVEL_NONE, 3638 [QDF_MODULE_ID_GREEN_AP] = QDF_TRACE_LEVEL_ERROR, 3639 [QDF_MODULE_ID_FTM] = QDF_TRACE_LEVEL_ERROR, 3640 [QDF_MODULE_ID_EXTAP] = QDF_TRACE_LEVEL_NONE, 3641 [QDF_MODULE_ID_FD] = QDF_TRACE_LEVEL_ERROR, 3642 [QDF_MODULE_ID_OCB] = QDF_TRACE_LEVEL_ERROR, 3643 [QDF_MODULE_ID_IPA] = QDF_TRACE_LEVEL_NONE, 3644 [QDF_MODULE_ID_ACTION_OUI] = QDF_TRACE_LEVEL_NONE, 3645 [QDF_MODULE_ID_CP_STATS] = QDF_TRACE_LEVEL_ERROR, 3646 [QDF_MODULE_ID_DCS] = QDF_TRACE_LEVEL_ERROR, 3647 [QDF_MODULE_ID_MBSSIE] = QDF_TRACE_LEVEL_INFO, 3648 [QDF_MODULE_ID_FWOL] = QDF_TRACE_LEVEL_NONE, 3649 [QDF_MODULE_ID_SM_ENGINE] = QDF_TRACE_LEVEL_ERROR, 3650 [QDF_MODULE_ID_CMN_MLME] = QDF_TRACE_LEVEL_INFO, 3651 [QDF_MODULE_ID_BSSCOLOR] = QDF_TRACE_LEVEL_ERROR, 3652 [QDF_MODULE_ID_CFR] = QDF_TRACE_LEVEL_ERROR, 3653 [QDF_MODULE_ID_TX_CAPTURE] = QDF_TRACE_LEVEL_FATAL, 3654 [QDF_MODULE_ID_INTEROP_ISSUES_AP] = QDF_TRACE_LEVEL_NONE, 3655 [QDF_MODULE_ID_BLACKLIST_MGR] = QDF_TRACE_LEVEL_NONE, 3656 [QDF_MODULE_ID_QLD] = QDF_TRACE_LEVEL_ERROR, 3657 [QDF_MODULE_ID_DYNAMIC_MODE_CHG] = QDF_TRACE_LEVEL_INFO, 3658 [QDF_MODULE_ID_COEX] = QDF_TRACE_LEVEL_ERROR, 3659 [QDF_MODULE_ID_MON_FILTER] = QDF_TRACE_LEVEL_INFO, 3660 [QDF_MODULE_ID_ANY] = QDF_TRACE_LEVEL_INFO, 3661 [QDF_MODULE_ID_PKT_CAPTURE] = QDF_TRACE_LEVEL_NONE, 3662 [QDF_MODULE_ID_RPTR] = QDF_TRACE_LEVEL_INFO, 3663 [QDF_MODULE_ID_6GHZ] = QDF_TRACE_LEVEL_ERROR, 3664 [QDF_MODULE_ID_IOT_SIM] = QDF_TRACE_LEVEL_ERROR, 3665 }; 3666 3667 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) { 3668 cinfo[i].category_verbose_mask = set_cumulative_verbose_mask( 3669 module_trace_default_level[i]); 3670 } 3671 } 3672 3673 void qdf_shared_print_ctrl_init(void) 3674 { 3675 int i; 3676 struct category_info cinfo[MAX_SUPPORTED_CATEGORY]; 3677 3678 set_default_trace_levels(cinfo); 3679 3680 /* 3681 * User specified across-module single debug level 3682 */ 3683 if ((qdf_dbg_mask >= 0) && (qdf_dbg_mask < QDF_TRACE_LEVEL_MAX)) { 3684 pr_info("User specified module debug level of %d\n", 3685 qdf_dbg_mask); 3686 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) { 3687 cinfo[i].category_verbose_mask = 3688 set_cumulative_verbose_mask(qdf_dbg_mask); 3689 } 3690 } else if (qdf_dbg_mask != QDF_TRACE_LEVEL_MAX) { 3691 pr_info("qdf_dbg_mask value is invalid\n"); 3692 pr_info("Using the default module debug levels instead\n"); 3693 } 3694 3695 /* 3696 * Module ID-Level specified as array during module load 3697 */ 3698 for (i = 0; i < qdf_dbg_arr_cnt; i++) { 3699 process_qdf_dbg_arr_param(cinfo, i); 3700 } 3701 qdf_pidx = qdf_print_ctrl_register(cinfo, NULL, NULL, 3702 "LOG_SHARED_OBJ"); 3703 } 3704 qdf_export_symbol(qdf_shared_print_ctrl_init); 3705 #endif 3706 3707 QDF_STATUS qdf_print_set_category_verbose(unsigned int idx, 3708 QDF_MODULE_ID category, 3709 QDF_TRACE_LEVEL verbose, 3710 bool is_set) 3711 { 3712 /* Check if index passed is valid */ 3713 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 3714 pr_err("%s: Invalid index - %d\n", __func__, idx); 3715 return QDF_STATUS_E_FAILURE; 3716 } 3717 3718 /* Check if print control object is in use */ 3719 if (!print_ctrl_obj[idx].in_use) { 3720 pr_err("%s: Invalid print control object\n", __func__); 3721 return QDF_STATUS_E_FAILURE; 3722 } 3723 3724 /* Check if category passed is valid */ 3725 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) { 3726 pr_err("%s: Invalid category: %d\n", __func__, category); 3727 return QDF_STATUS_E_FAILURE; 3728 } 3729 3730 /* Check if verbose mask is valid */ 3731 if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) { 3732 pr_err("%s: Invalid verbose level %d\n", __func__, verbose); 3733 return QDF_STATUS_E_FAILURE; 3734 } 3735 3736 if (verbose == QDF_TRACE_LEVEL_ALL) { 3737 print_ctrl_obj[idx].cat_info[category].category_verbose_mask = 3738 0xFFFF; 3739 return QDF_STATUS_SUCCESS; 3740 } 3741 3742 if (verbose == QDF_TRACE_LEVEL_NONE) { 3743 print_ctrl_obj[idx].cat_info[category].category_verbose_mask = 3744 QDF_TRACE_LEVEL_NONE; 3745 return QDF_STATUS_SUCCESS; 3746 } 3747 3748 if (!is_set) { 3749 if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask 3750 & QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) { 3751 print_ctrl_obj[idx].cat_info[category] 3752 .category_verbose_mask &= 3753 ~QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose); 3754 } 3755 } else { 3756 print_ctrl_obj[idx].cat_info[category].category_verbose_mask |= 3757 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose); 3758 } 3759 3760 pr_debug("%s: Print control object %d, Category %d, Verbose level %d\n", 3761 __func__, 3762 idx, 3763 category, 3764 print_ctrl_obj[idx].cat_info[category].category_verbose_mask); 3765 3766 return QDF_STATUS_SUCCESS; 3767 } 3768 qdf_export_symbol(qdf_print_set_category_verbose); 3769 3770 void qdf_log_dump_at_kernel_level(bool enable) 3771 { 3772 if (qdf_log_dump_at_kernel_enable == enable) { 3773 QDF_TRACE_INFO(QDF_MODULE_ID_QDF, 3774 "qdf_log_dump_at_kernel_enable is already %d\n", 3775 enable); 3776 } 3777 qdf_log_dump_at_kernel_enable = enable; 3778 } 3779 3780 qdf_export_symbol(qdf_log_dump_at_kernel_level); 3781 3782 bool qdf_print_is_category_enabled(unsigned int idx, QDF_MODULE_ID category) 3783 { 3784 QDF_TRACE_LEVEL verbose_mask; 3785 3786 /* Check if index passed is valid */ 3787 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 3788 pr_info("%s: Invalid index - %d\n", __func__, idx); 3789 return false; 3790 } 3791 3792 /* Check if print control object is in use */ 3793 if (!print_ctrl_obj[idx].in_use) { 3794 pr_info("%s: Invalid print control object\n", __func__); 3795 return false; 3796 } 3797 3798 /* Check if category passed is valid */ 3799 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) { 3800 pr_info("%s: Invalid category: %d\n", __func__, category); 3801 return false; 3802 } 3803 3804 verbose_mask = 3805 print_ctrl_obj[idx].cat_info[category].category_verbose_mask; 3806 3807 if (verbose_mask == QDF_TRACE_LEVEL_NONE) 3808 return false; 3809 else 3810 return true; 3811 } 3812 qdf_export_symbol(qdf_print_is_category_enabled); 3813 3814 bool qdf_print_is_verbose_enabled(unsigned int idx, QDF_MODULE_ID category, 3815 QDF_TRACE_LEVEL verbose) 3816 { 3817 bool verbose_enabled = false; 3818 3819 /* Check if index passed is valid */ 3820 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 3821 pr_info("%s: Invalid index - %d\n", __func__, idx); 3822 return verbose_enabled; 3823 } 3824 3825 /* Check if print control object is in use */ 3826 if (!print_ctrl_obj[idx].in_use) { 3827 pr_info("%s: Invalid print control object\n", __func__); 3828 return verbose_enabled; 3829 } 3830 3831 /* Check if category passed is valid */ 3832 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) { 3833 pr_info("%s: Invalid category: %d\n", __func__, category); 3834 return verbose_enabled; 3835 } 3836 3837 if ((verbose == QDF_TRACE_LEVEL_NONE) || 3838 (verbose >= QDF_TRACE_LEVEL_MAX)) { 3839 verbose_enabled = false; 3840 } else if (verbose == QDF_TRACE_LEVEL_ALL) { 3841 if (print_ctrl_obj[idx].cat_info[category] 3842 .category_verbose_mask == 0xFFFF) 3843 verbose_enabled = true; 3844 } else { 3845 verbose_enabled = 3846 (print_ctrl_obj[idx].cat_info[category].category_verbose_mask & 3847 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) ? true : false; 3848 } 3849 3850 return verbose_enabled; 3851 } 3852 qdf_export_symbol(qdf_print_is_verbose_enabled); 3853 3854 #ifdef DBG_LVL_MAC_FILTERING 3855 3856 QDF_STATUS qdf_print_set_node_flag(unsigned int idx, uint8_t enable) 3857 { 3858 /* Check if index passed is valid */ 3859 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 3860 pr_info("%s: Invalid index - %d\n", __func__, idx); 3861 return QDF_STATUS_E_FAILURE; 3862 } 3863 3864 /* Check if print control object is in use */ 3865 if (!print_ctrl_obj[idx].in_use) { 3866 pr_info("%s: Invalid print control object\n", __func__); 3867 return QDF_STATUS_E_FAILURE; 3868 } 3869 3870 if (enable > 1) { 3871 pr_info("%s: Incorrect input: Use 1 or 0 to enable or disable\n", 3872 __func__); 3873 return QDF_STATUS_E_FAILURE; 3874 } 3875 3876 print_ctrl_obj[idx].dbglvlmac_on = enable; 3877 pr_info("%s: DbgLVLmac feature %s\n", 3878 __func__, 3879 ((enable) ? "enabled" : "disabled")); 3880 3881 return QDF_STATUS_SUCCESS; 3882 } 3883 qdf_export_symbol(qdf_print_set_node_flag); 3884 3885 bool qdf_print_get_node_flag(unsigned int idx) 3886 { 3887 bool node_flag = false; 3888 3889 /* Check if index passed is valid */ 3890 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 3891 pr_info("%s: Invalid index - %d\n", __func__, idx); 3892 return node_flag; 3893 } 3894 3895 /* Check if print control object is in use */ 3896 if (!print_ctrl_obj[idx].in_use) { 3897 pr_info("%s: Invalid print control object\n", __func__); 3898 return node_flag; 3899 } 3900 3901 if (print_ctrl_obj[idx].dbglvlmac_on) 3902 node_flag = true; 3903 3904 return node_flag; 3905 } 3906 qdf_export_symbol(qdf_print_get_node_flag); 3907 3908 void qdf_print_clean_node_flag(unsigned int idx) 3909 { 3910 /* Disable dbglvlmac_on during cleanup */ 3911 print_ctrl_obj[idx].dbglvlmac_on = 0; 3912 } 3913 3914 #else 3915 3916 void qdf_print_clean_node_flag(unsigned int idx) 3917 { 3918 /* No operation in case of no support for DBG_LVL_MAC_FILTERING */ 3919 return; 3920 } 3921 #endif 3922 3923 void QDF_PRINT_INFO(unsigned int idx, QDF_MODULE_ID module, 3924 QDF_TRACE_LEVEL level, 3925 char *str_format, ...) 3926 { 3927 va_list args; 3928 3929 /* Generic wrapper API will compile qdf_vprint in order to 3930 * log the message. Once QDF converged debug framework is in 3931 * place, this will be changed to adapt to the framework, compiling 3932 * call to converged tracing API 3933 */ 3934 va_start(args, str_format); 3935 qdf_vprint(str_format, args); 3936 va_end(args); 3937 } 3938 qdf_export_symbol(QDF_PRINT_INFO); 3939 3940 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE 3941 void qdf_logging_init(void) 3942 { 3943 wlan_logging_sock_init_svc(); 3944 nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY); 3945 wlan_logging_notifier_init(qdf_log_dump_at_kernel_enable); 3946 wlan_logging_set_flush_timer(qdf_log_flush_timer_period); 3947 } 3948 3949 void qdf_logging_exit(void) 3950 { 3951 wlan_logging_notifier_deinit(qdf_log_dump_at_kernel_enable); 3952 nl_srv_exit(); 3953 wlan_logging_sock_deinit_svc(); 3954 } 3955 3956 int qdf_logging_set_flush_timer(uint32_t milliseconds) 3957 { 3958 if (wlan_logging_set_flush_timer(milliseconds) == 0) 3959 return QDF_STATUS_SUCCESS; 3960 else 3961 return QDF_STATUS_E_FAILURE; 3962 } 3963 3964 void qdf_logging_flush_logs(void) 3965 { 3966 wlan_flush_host_logs_for_fatal(); 3967 } 3968 3969 #else 3970 void qdf_logging_init(void) 3971 { 3972 nl_srv_init(NULL, WLAN_NLINK_PROTO_FAMILY); 3973 } 3974 3975 void qdf_logging_exit(void) 3976 { 3977 nl_srv_exit(); 3978 } 3979 3980 int qdf_logging_set_flush_timer(uint32_t milliseconds) 3981 { 3982 return QDF_STATUS_E_FAILURE; 3983 } 3984 3985 void qdf_logging_flush_logs(void) 3986 { 3987 } 3988 #endif 3989 3990 qdf_export_symbol(qdf_logging_set_flush_timer); 3991 qdf_export_symbol(qdf_logging_flush_logs); 3992 3993 #ifdef CONFIG_KALLSYMS 3994 inline int qdf_sprint_symbol(char *buffer, void *addr) 3995 { 3996 return sprint_symbol(buffer, (unsigned long)addr); 3997 } 3998 #else 3999 int qdf_sprint_symbol(char *buffer, void *addr) 4000 { 4001 if (!buffer) 4002 return 0; 4003 4004 buffer[0] = '\0'; 4005 return 1; 4006 } 4007 #endif 4008 qdf_export_symbol(qdf_sprint_symbol); 4009 4010 void qdf_set_pidx(int pidx) 4011 { 4012 qdf_pidx = pidx; 4013 } 4014 qdf_export_symbol(qdf_set_pidx); 4015 4016 int qdf_get_pidx(void) 4017 { 4018 return qdf_pidx; 4019 } 4020 qdf_export_symbol(qdf_get_pidx); 4021 4022 #ifdef PANIC_ON_BUG 4023 #ifdef CONFIG_SLUB_DEBUG 4024 void __qdf_bug(void) 4025 { 4026 BUG(); 4027 } 4028 qdf_export_symbol(__qdf_bug); 4029 #endif /* CONFIG_SLUB_DEBUG */ 4030 #endif /* PANIC_ON_BUG */ 4031 4032