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