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