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