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