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