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