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