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