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