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