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