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 static int qdf_pidx = -1; 43 #ifdef CONFIG_MCL 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 FEATURE_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 void qdf_set_pidx(int pidx) 132 { 133 qdf_pidx = pidx; 134 } 135 EXPORT_SYMBOL(qdf_set_pidx); 136 137 int qdf_get_pidx(void) 138 { 139 return qdf_pidx; 140 } 141 EXPORT_SYMBOL(qdf_get_pidx); 142 143 /** 144 * qdf_trace_set_level() - Set the trace level for a particular module 145 * @module: Module id 146 * @level : trace level 147 * 148 * Trace level is a member of the QDF_TRACE_LEVEL enumeration indicating 149 * the severity of the condition causing the trace message to be issued. 150 * More severe conditions are more likely to be logged. 151 * 152 * This is an external API that allows trace levels to be set for each module. 153 * 154 * Return: None 155 */ 156 void qdf_trace_set_level(QDF_MODULE_ID module, QDF_TRACE_LEVEL level) 157 { 158 /* make sure the caller is passing in a valid LEVEL */ 159 if (level >= QDF_TRACE_LEVEL_MAX) { 160 pr_err("%s: Invalid trace level %d passed in!\n", __func__, 161 level); 162 return; 163 } 164 165 /* Treat 'none' differently. NONE means we have to run off all 166 * the bits in the bit mask so none of the traces appear. Anything 167 * other than 'none' means we need to turn ON a bit in the bitmask 168 */ 169 if (QDF_TRACE_LEVEL_NONE == level) 170 g_qdf_trace_info[module].module_trace_level = 171 QDF_TRACE_LEVEL_NONE; 172 else 173 /* set the desired bit in the bit mask for the module trace 174 * level */ 175 g_qdf_trace_info[module].module_trace_level |= 176 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level); 177 } 178 EXPORT_SYMBOL(qdf_trace_set_level); 179 180 /** 181 * qdf_trace_set_module_trace_level() - Set module trace level 182 * @module: Module id 183 * @level: Trace level for a module, as a bitmask as per 'module_trace_info' 184 * 185 * Sets the module trace level where the trace level is given as a bit mask 186 * 187 * Return: None 188 */ 189 void qdf_trace_set_module_trace_level(QDF_MODULE_ID module, uint32_t level) 190 { 191 if (module < 0 || module >= QDF_MODULE_ID_MAX) { 192 pr_err("%s: Invalid module id %d passed\n", __func__, module); 193 return; 194 } 195 g_qdf_trace_info[module].module_trace_level = level; 196 } 197 EXPORT_SYMBOL(qdf_trace_set_module_trace_level); 198 199 /** 200 * qdf_trace_set_value() - Set module trace value 201 * @module: Module id 202 * @level: Trace level for a module, as a bitmask as per 'module_trace_info' 203 * @on: set/clear the desired bit in the bit mask 204 * 205 * Return: None 206 */ 207 void qdf_trace_set_value(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, 208 uint8_t on) 209 { 210 /* make sure the caller is passing in a valid LEVEL */ 211 if (level < 0 || level >= QDF_TRACE_LEVEL_MAX) { 212 pr_err("%s: Invalid trace level %d passed in!\n", __func__, 213 level); 214 return; 215 } 216 217 /* make sure the caller is passing in a valid module */ 218 if (module < 0 || module >= QDF_MODULE_ID_MAX) { 219 pr_err("%s: Invalid module id %d passed in!\n", __func__, 220 module); 221 return; 222 } 223 224 /* Treat 'none' differently. NONE means we have to turn off all 225 the bits in the bit mask so none of the traces appear */ 226 if (QDF_TRACE_LEVEL_NONE == level) { 227 g_qdf_trace_info[module].module_trace_level = 228 QDF_TRACE_LEVEL_NONE; 229 } 230 /* Treat 'All' differently. All means we have to turn on all 231 the bits in the bit mask so all of the traces appear */ 232 else if (QDF_TRACE_LEVEL_ALL == level) { 233 g_qdf_trace_info[module].module_trace_level = 0xFFFF; 234 } else { 235 if (on) 236 /* set the desired bit in the bit mask for the module 237 trace level */ 238 g_qdf_trace_info[module].module_trace_level |= 239 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level); 240 else 241 /* clear the desired bit in the bit mask for the module 242 trace level */ 243 g_qdf_trace_info[module].module_trace_level &= 244 ~(QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level)); 245 } 246 } 247 EXPORT_SYMBOL(qdf_trace_set_value); 248 249 /** 250 * qdf_trace_get_level() - get the trace level 251 * @module: module Id 252 * @level: trace level 253 * 254 * This is an external API that returns a bool value to signify if a 255 * particular trace level is set for the specified module. 256 * A member of the QDF_TRACE_LEVEL enumeration indicating the severity 257 * of the condition causing the trace message to be issued. 258 * 259 * Note that individual trace levels are the only valid values 260 * for this API. QDF_TRACE_LEVEL_NONE and QDF_TRACE_LEVEL_ALL 261 * are not valid input and will return false 262 * 263 * Return: 264 * false - the specified trace level for the specified module is OFF 265 * true - the specified trace level for the specified module is ON 266 */ 267 bool qdf_trace_get_level(QDF_MODULE_ID module, QDF_TRACE_LEVEL level) 268 { 269 bool trace_on = false; 270 271 if ((QDF_TRACE_LEVEL_NONE == level) || 272 (QDF_TRACE_LEVEL_ALL == level) || (level >= QDF_TRACE_LEVEL_MAX)) { 273 trace_on = false; 274 } else { 275 trace_on = (level & g_qdf_trace_info[module].module_trace_level) 276 ? true : false; 277 } 278 279 return trace_on; 280 } 281 EXPORT_SYMBOL(qdf_trace_get_level); 282 283 /** 284 * qdf_snprintf() - wrapper function to snprintf 285 * @str_buffer: string Buffer 286 * @size: defines the size of the data record 287 * @str_format: Format string in which the message to be logged. This format 288 * string contains printf-like replacement parameters, which follow 289 * this parameter in the variable argument list. 290 * 291 * Return: None 292 */ 293 void qdf_snprintf(char *str_buffer, unsigned int size, char *str_format, ...) 294 { 295 va_list val; 296 297 va_start(val, str_format); 298 snprintf(str_buffer, size, str_format, val); 299 va_end(val); 300 } 301 EXPORT_SYMBOL(qdf_snprintf); 302 303 #ifdef QDF_ENABLE_TRACING 304 305 /** 306 * qdf_trace_msg() - externally called trace function 307 * @module: Module identifier a member of the QDF_MODULE_ID 308 * enumeration that identifies the module issuing the trace message. 309 * @level: Trace level a member of the QDF_TRACE_LEVEL enumeration 310 * indicating the severity of the condition causing the trace message 311 * to be issued. More severe conditions are more likely to be logged. 312 * @str_format: Format string in which the message to be logged. This format 313 * string contains printf-like replacement parameters, which follow 314 * this parameter in the variable argument list. 315 * 316 * Checks the level of severity and accordingly prints the trace messages 317 * 318 * Return: None 319 */ 320 void qdf_trace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, 321 char *str_format, ...) 322 { 323 va_list val; 324 325 va_start(val, str_format); 326 qdf_trace_msg_cmn(qdf_pidx, module, level, str_format, val); 327 va_end(val); 328 } 329 EXPORT_SYMBOL(qdf_trace_msg); 330 331 /** 332 * qdf_trace_display() - Display trace 333 * 334 * Return: None 335 */ 336 void qdf_trace_display(void) 337 { 338 QDF_MODULE_ID module_id; 339 340 pr_err 341 (" 1)FATAL 2)ERROR 3)WARN 4)INFO 5)INFO_H 6)INFO_M 7)INFO_L 8)DEBUG\n"); 342 for (module_id = 0; module_id < QDF_MODULE_ID_MAX; ++module_id) { 343 pr_err 344 ("%2d)%s %s %s %s %s %s %s %s %s\n", 345 (int)module_id, g_qdf_trace_info[module_id].module_name_str, 346 (g_qdf_trace_info[module_id]. 347 module_trace_level & (1 << QDF_TRACE_LEVEL_FATAL)) ? "X" : 348 " ", 349 (g_qdf_trace_info[module_id]. 350 module_trace_level & (1 << QDF_TRACE_LEVEL_ERROR)) ? "X" : 351 " ", 352 (g_qdf_trace_info[module_id]. 353 module_trace_level & (1 << QDF_TRACE_LEVEL_WARN)) ? "X" : 354 " ", 355 (g_qdf_trace_info[module_id]. 356 module_trace_level & (1 << QDF_TRACE_LEVEL_INFO)) ? "X" : 357 " ", 358 (g_qdf_trace_info[module_id]. 359 module_trace_level & (1 << QDF_TRACE_LEVEL_INFO_HIGH)) ? "X" 360 : " ", 361 (g_qdf_trace_info[module_id]. 362 module_trace_level & (1 << QDF_TRACE_LEVEL_INFO_MED)) ? "X" 363 : " ", 364 (g_qdf_trace_info[module_id]. 365 module_trace_level & (1 << QDF_TRACE_LEVEL_INFO_LOW)) ? "X" 366 : " ", 367 (g_qdf_trace_info[module_id]. 368 module_trace_level & (1 << QDF_TRACE_LEVEL_DEBUG)) ? "X" : 369 " "); 370 } 371 } 372 EXPORT_SYMBOL(qdf_trace_display); 373 374 #define ROW_SIZE 16 375 /* Buffer size = data bytes(2 hex chars plus space) + NULL */ 376 #define BUFFER_SIZE ((ROW_SIZE * 3) + 1) 377 378 /** 379 * qdf_trace_hex_dump() - externally called hex dump function 380 * @module: Module identifier a member of the QDF_MODULE_ID enumeration that 381 * identifies the module issuing the trace message. 382 * @level: Trace level a member of the QDF_TRACE_LEVEL enumeration indicating 383 * the severity of the condition causing the trace message to be 384 * issued. More severe conditions are more likely to be logged. 385 * @data: The base address of the buffer to be logged. 386 * @buf_len: The size of the buffer to be logged. 387 * 388 * Checks the level of severity and accordingly prints the trace messages 389 * 390 * Return: None 391 */ 392 void qdf_trace_hex_dump(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, 393 void *data, int buf_len) 394 { 395 const u8 *ptr = data; 396 int i, linelen, remaining = buf_len; 397 unsigned char linebuf[BUFFER_SIZE]; 398 399 if (!(g_qdf_trace_info[module].module_trace_level & 400 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level))) 401 return; 402 403 for (i = 0; i < buf_len; i += ROW_SIZE) { 404 linelen = min(remaining, ROW_SIZE); 405 remaining -= ROW_SIZE; 406 407 hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1, 408 linebuf, sizeof(linebuf), false); 409 410 qdf_trace_msg(module, level, "%.8x: %s", i, linebuf); 411 } 412 } 413 EXPORT_SYMBOL(qdf_trace_hex_dump); 414 415 #endif 416 417 /** 418 * qdf_trace_enable() - Enable MTRACE for specific modules 419 * @bitmask_of_module_id: Bitmask according to enum of the modules. 420 * 32[dec] = 0010 0000 [bin] <enum of HDD is 5> 421 * 64[dec] = 0100 0000 [bin] <enum of SME is 6> 422 * 128[dec] = 1000 0000 [bin] <enum of PE is 7> 423 * @enable: can be true or false true implies enabling MTRACE false implies 424 * disabling MTRACE. 425 * 426 * Enable MTRACE for specific modules whose bits are set in bitmask and enable 427 * is true. if enable is false it disables MTRACE for that module. set the 428 * bitmask according to enum value of the modules. 429 * This functions will be called when you issue ioctl as mentioned following 430 * [iwpriv wlan0 setdumplog <value> <enable>]. 431 * <value> - Decimal number, i.e. 64 decimal value shows only SME module, 432 * 128 decimal value shows only PE module, 192 decimal value shows PE and SME. 433 * 434 * Return: None 435 */ 436 void qdf_trace_enable(uint32_t bitmask_of_module_id, uint8_t enable) 437 { 438 int i; 439 if (bitmask_of_module_id) { 440 for (i = 0; i < QDF_MODULE_ID_MAX; i++) { 441 if (((bitmask_of_module_id >> i) & 1)) { 442 if (enable) { 443 if (NULL != 444 qdf_trace_restore_cb_table[i]) { 445 qdf_trace_cb_table[i] = 446 qdf_trace_restore_cb_table[i]; 447 } 448 } else { 449 qdf_trace_restore_cb_table[i] = 450 qdf_trace_cb_table[i]; 451 qdf_trace_cb_table[i] = NULL; 452 } 453 } 454 } 455 } else { 456 if (enable) { 457 for (i = 0; i < QDF_MODULE_ID_MAX; i++) { 458 if (NULL != qdf_trace_restore_cb_table[i]) { 459 qdf_trace_cb_table[i] = 460 qdf_trace_restore_cb_table[i]; 461 } 462 } 463 } else { 464 for (i = 0; i < QDF_MODULE_ID_MAX; i++) { 465 qdf_trace_restore_cb_table[i] = 466 qdf_trace_cb_table[i]; 467 qdf_trace_cb_table[i] = NULL; 468 } 469 } 470 } 471 } 472 EXPORT_SYMBOL(qdf_trace_enable); 473 474 /** 475 * qdf_trace_init() - initializes qdf trace structures and variables 476 * 477 * Called immediately after cds_preopen, so that we can start recording HDD 478 * events ASAP. 479 * 480 * Return: None 481 */ 482 void qdf_trace_init(void) 483 { 484 uint8_t i; 485 g_qdf_trace_data.head = INVALID_QDF_TRACE_ADDR; 486 g_qdf_trace_data.tail = INVALID_QDF_TRACE_ADDR; 487 g_qdf_trace_data.num = 0; 488 g_qdf_trace_data.enable = true; 489 g_qdf_trace_data.dump_count = DEFAULT_QDF_TRACE_DUMP_COUNT; 490 g_qdf_trace_data.num_since_last_dump = 0; 491 492 for (i = 0; i < QDF_MODULE_ID_MAX; i++) { 493 qdf_trace_cb_table[i] = NULL; 494 qdf_trace_restore_cb_table[i] = NULL; 495 } 496 } 497 EXPORT_SYMBOL(qdf_trace_init); 498 499 /** 500 * qdf_trace() - puts the messages in to ring-buffer 501 * @module: Enum of module, basically module id. 502 * @param: Code to be recorded 503 * @session: Session ID of the log 504 * @data: Actual message contents 505 * 506 * This function will be called from each module who wants record the messages 507 * in circular queue. Before calling this functions make sure you have 508 * registered your module with qdf through qdf_trace_register function. 509 * 510 * Return: None 511 */ 512 void qdf_trace(uint8_t module, uint8_t code, uint16_t session, uint32_t data) 513 { 514 tp_qdf_trace_record rec = NULL; 515 unsigned long flags; 516 char time[18]; 517 518 if (!g_qdf_trace_data.enable) 519 return; 520 521 /* if module is not registered, don't record for that module */ 522 if (NULL == qdf_trace_cb_table[module]) 523 return; 524 525 qdf_get_time_of_the_day_in_hr_min_sec_usec(time, sizeof(time)); 526 /* Aquire the lock so that only one thread at a time can fill the ring 527 * buffer 528 */ 529 spin_lock_irqsave(<race_lock, flags); 530 531 g_qdf_trace_data.num++; 532 533 if (g_qdf_trace_data.num > MAX_QDF_TRACE_RECORDS) 534 g_qdf_trace_data.num = MAX_QDF_TRACE_RECORDS; 535 536 if (INVALID_QDF_TRACE_ADDR == g_qdf_trace_data.head) { 537 /* first record */ 538 g_qdf_trace_data.head = 0; 539 g_qdf_trace_data.tail = 0; 540 } else { 541 /* queue is not empty */ 542 uint32_t tail = g_qdf_trace_data.tail + 1; 543 544 if (MAX_QDF_TRACE_RECORDS == tail) 545 tail = 0; 546 547 if (g_qdf_trace_data.head == tail) { 548 /* full */ 549 if (MAX_QDF_TRACE_RECORDS == ++g_qdf_trace_data.head) 550 g_qdf_trace_data.head = 0; 551 } 552 g_qdf_trace_data.tail = tail; 553 } 554 555 rec = &g_qdf_trace_tbl[g_qdf_trace_data.tail]; 556 rec->code = code; 557 rec->session = session; 558 rec->data = data; 559 rec->qtime = qdf_get_log_timestamp(); 560 scnprintf(rec->time, sizeof(rec->time), "%s", time); 561 rec->module = module; 562 rec->pid = (in_interrupt() ? 0 : current->pid); 563 g_qdf_trace_data.num_since_last_dump++; 564 spin_unlock_irqrestore(<race_lock, flags); 565 } 566 EXPORT_SYMBOL(qdf_trace); 567 568 /** 569 * qdf_trace_spin_lock_init() - initializes the lock variable before use 570 * 571 * This function will be called from cds_alloc_global_context, we will have lock 572 * available to use ASAP 573 * 574 * Return: None 575 */ 576 QDF_STATUS qdf_trace_spin_lock_init(void) 577 { 578 spin_lock_init(<race_lock); 579 580 return QDF_STATUS_SUCCESS; 581 } 582 EXPORT_SYMBOL(qdf_trace_spin_lock_init); 583 584 /** 585 * qdf_trace_register() - registers the call back functions 586 * @module_iD: enum value of module 587 * @qdf_trace_callback: call back functions to display the messages in 588 * particular format. 589 * 590 * Registers the call back functions to display the messages in particular 591 * format mentioned in these call back functions. This functions should be 592 * called by interested module in their init part as we will be ready to 593 * register as soon as modules are up. 594 * 595 * Return: None 596 */ 597 void qdf_trace_register(QDF_MODULE_ID module_iD, 598 tp_qdf_trace_cb qdf_trace_callback) 599 { 600 qdf_trace_cb_table[module_iD] = qdf_trace_callback; 601 } 602 EXPORT_SYMBOL(qdf_trace_register); 603 604 /** 605 * qdf_trace_dump_all() - Dump data from ring buffer via call back functions 606 * registered with QDF 607 * @p_mac: Context of particular module 608 * @code: Reason code 609 * @session: Session id of log 610 * @count: Number of lines to dump starting from tail to head 611 * 612 * This function will be called up on issueing ioctl call as mentioned following 613 * [iwpriv wlan0 dumplog 0 0 <n> <bitmask_of_module>] 614 * 615 * <n> - number lines to dump starting from tail to head. 616 * 617 * <bitmask_of_module> - if anybody wants to know how many messages were 618 * recorded for particular module/s mentioned by setbit in bitmask from last 619 * <n> messages. It is optional, if you don't provide then it will dump 620 * everything from buffer. 621 * 622 * Return: None 623 */ 624 void qdf_trace_dump_all(void *p_mac, uint8_t code, uint8_t session, 625 uint32_t count, uint32_t bitmask_of_module) 626 { 627 qdf_trace_record_t p_record; 628 int32_t i, tail; 629 630 if (!g_qdf_trace_data.enable) { 631 QDF_TRACE(QDF_MODULE_ID_SYS, 632 QDF_TRACE_LEVEL_ERROR, "Tracing Disabled"); 633 return; 634 } 635 636 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_INFO, 637 "Total Records: %d, Head: %d, Tail: %d", 638 g_qdf_trace_data.num, g_qdf_trace_data.head, 639 g_qdf_trace_data.tail); 640 641 /* aquire the lock so that only one thread at a time can read 642 * the ring buffer 643 */ 644 spin_lock(<race_lock); 645 646 if (g_qdf_trace_data.head != INVALID_QDF_TRACE_ADDR) { 647 i = g_qdf_trace_data.head; 648 tail = g_qdf_trace_data.tail; 649 650 if (count) { 651 if (count > g_qdf_trace_data.num) 652 count = g_qdf_trace_data.num; 653 if (tail >= (count - 1)) 654 i = tail - count + 1; 655 else if (count != MAX_QDF_TRACE_RECORDS) 656 i = MAX_QDF_TRACE_RECORDS - ((count - 1) - 657 tail); 658 } 659 660 p_record = g_qdf_trace_tbl[i]; 661 /* right now we are not using num_since_last_dump member but 662 * in future we might re-visit and use this member to track 663 * how many latest messages got added while we were dumping 664 * from ring buffer 665 */ 666 g_qdf_trace_data.num_since_last_dump = 0; 667 spin_unlock(<race_lock); 668 for (;; ) { 669 if ((code == 0 || (code == p_record.code)) && 670 (qdf_trace_cb_table[p_record.module] != NULL)) { 671 if (0 == bitmask_of_module) { 672 qdf_trace_cb_table[p_record. 673 module] (p_mac, 674 &p_record, 675 (uint16_t) 676 i); 677 } else { 678 if (bitmask_of_module & 679 (1 << p_record.module)) { 680 qdf_trace_cb_table[p_record. 681 module] 682 (p_mac, &p_record, 683 (uint16_t) i); 684 } 685 } 686 } 687 688 if (i == tail) 689 break; 690 i += 1; 691 692 spin_lock(<race_lock); 693 if (MAX_QDF_TRACE_RECORDS == i) { 694 i = 0; 695 p_record = g_qdf_trace_tbl[0]; 696 } else { 697 p_record = g_qdf_trace_tbl[i]; 698 } 699 spin_unlock(<race_lock); 700 } 701 } else { 702 spin_unlock(<race_lock); 703 } 704 } 705 EXPORT_SYMBOL(qdf_trace_dump_all); 706 707 /** 708 * qdf_register_debugcb_init() - initializes debug callbacks 709 * to NULL 710 * 711 * Return: None 712 */ 713 void qdf_register_debugcb_init(void) 714 { 715 uint8_t i; 716 717 for (i = 0; i < QDF_MODULE_ID_MAX; i++) 718 qdf_state_info_table[i] = NULL; 719 } 720 EXPORT_SYMBOL(qdf_register_debugcb_init); 721 722 /** 723 * qdf_register_debug_callback() - stores callback handlers to print 724 * state information 725 * @module_id: module id of layer 726 * @qdf_state_infocb: callback to be registered 727 * 728 * This function is used to store callback handlers to print 729 * state information 730 * 731 * Return: None 732 */ 733 void qdf_register_debug_callback(QDF_MODULE_ID module_id, 734 tp_qdf_state_info_cb qdf_state_infocb) 735 { 736 qdf_state_info_table[module_id] = qdf_state_infocb; 737 } 738 EXPORT_SYMBOL(qdf_register_debug_callback); 739 740 /** 741 * qdf_state_info_dump_all() - it invokes callback of layer which registered 742 * its callback to print its state information. 743 * @buf: buffer pointer to be passed 744 * @size: size of buffer to be filled 745 * @driver_dump_size: actual size of buffer used 746 * 747 * Return: QDF_STATUS_SUCCESS on success 748 */ 749 QDF_STATUS qdf_state_info_dump_all(char *buf, uint16_t size, 750 uint16_t *driver_dump_size) 751 { 752 uint8_t module, ret = QDF_STATUS_SUCCESS; 753 uint16_t buf_len = size; 754 char *buf_ptr = buf; 755 756 for (module = 0; module < QDF_MODULE_ID_MAX; module++) { 757 if (NULL != qdf_state_info_table[module]) { 758 qdf_state_info_table[module](&buf_ptr, &buf_len); 759 if (!buf_len) { 760 ret = QDF_STATUS_E_NOMEM; 761 break; 762 } 763 } 764 } 765 766 *driver_dump_size = size - buf_len; 767 return ret; 768 } 769 EXPORT_SYMBOL(qdf_state_info_dump_all); 770 771 #ifdef FEATURE_DP_TRACE 772 static void qdf_dp_unused(struct qdf_dp_trace_record_s *record, 773 uint16_t index) 774 { 775 qdf_print("%s: QDF_DP_TRACE_MAX event should not be generated", 776 __func__); 777 } 778 779 /** 780 * qdf_dp_trace_init() - enables the DP trace 781 * Called during driver load and it enables DP trace 782 * 783 * Return: None 784 */ 785 void qdf_dp_trace_init(void) 786 { 787 uint8_t i; 788 789 qdf_dp_trace_spin_lock_init(); 790 g_qdf_dp_trace_data.head = INVALID_QDF_DP_TRACE_ADDR; 791 g_qdf_dp_trace_data.tail = INVALID_QDF_DP_TRACE_ADDR; 792 g_qdf_dp_trace_data.num = 0; 793 g_qdf_dp_trace_data.proto_bitmap = QDF_NBUF_PKT_TRAC_TYPE_EAPOL | 794 QDF_NBUF_PKT_TRAC_TYPE_DHCP | 795 QDF_NBUF_PKT_TRAC_TYPE_MGMT_ACTION | 796 QDF_NBUF_PKT_TRAC_TYPE_ARP; 797 g_qdf_dp_trace_data.no_of_record = 0; 798 g_qdf_dp_trace_data.verbosity = QDF_DP_TRACE_VERBOSITY_HIGH; 799 g_qdf_dp_trace_data.enable = true; 800 g_qdf_dp_trace_data.tx_count = 0; 801 g_qdf_dp_trace_data.rx_count = 0; 802 g_qdf_dp_trace_data.live_mode = 0; 803 804 for (i = 0; i < ARRAY_SIZE(qdf_dp_trace_cb_table); i++) 805 qdf_dp_trace_cb_table[i] = qdf_dp_display_record; 806 807 qdf_dp_trace_cb_table[QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD] = 808 qdf_dp_trace_cb_table[QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD] = 809 qdf_dp_trace_cb_table[QDF_DP_TRACE_FREE_PACKET_PTR_RECORD] = 810 qdf_dp_display_ptr_record; 811 qdf_dp_trace_cb_table[QDF_DP_TRACE_EAPOL_PACKET_RECORD] = 812 qdf_dp_trace_cb_table[QDF_DP_TRACE_DHCP_PACKET_RECORD] = 813 qdf_dp_trace_cb_table[QDF_DP_TRACE_ARP_PACKET_RECORD] = 814 qdf_dp_display_proto_pkt; 815 qdf_dp_trace_cb_table[QDF_DP_TRACE_MGMT_PACKET_RECORD] = 816 qdf_dp_display_mgmt_pkt; 817 qdf_dp_trace_cb_table[QDF_DP_TRACE_EVENT_RECORD] = 818 qdf_dp_display_event_record; 819 820 qdf_dp_trace_cb_table[QDF_DP_TRACE_MAX] = qdf_dp_unused; 821 } 822 EXPORT_SYMBOL(qdf_dp_trace_init); 823 824 /** 825 * qdf_dp_trace_set_value() - Configure the value to control DP trace 826 * @proto_bitmap: defines the protocol to be tracked 827 * @no_of_records: defines the nth packet which is traced 828 * @verbosity: defines the verbosity level 829 * 830 * Return: None 831 */ 832 void qdf_dp_trace_set_value(uint8_t proto_bitmap, uint8_t no_of_record, 833 uint8_t verbosity) 834 { 835 g_qdf_dp_trace_data.proto_bitmap = proto_bitmap; 836 g_qdf_dp_trace_data.no_of_record = no_of_record; 837 g_qdf_dp_trace_data.verbosity = verbosity; 838 return; 839 } 840 EXPORT_SYMBOL(qdf_dp_trace_set_value); 841 842 /** 843 * qdf_dp_trace_enable_track() - enable the tracing for netbuf 844 * @code: defines the event 845 * 846 * In High verbosity all codes are logged. 847 * For Med/Low and Default case code which has 848 * less value than corresponding verbosity codes 849 * are logged. 850 * 851 * Return: true or false depends on whether tracing enabled 852 */ 853 static bool qdf_dp_trace_enable_track(enum QDF_DP_TRACE_ID code) 854 { 855 switch (g_qdf_dp_trace_data.verbosity) { 856 case QDF_DP_TRACE_VERBOSITY_HIGH: 857 return true; 858 case QDF_DP_TRACE_VERBOSITY_MEDIUM: 859 if (code <= QDF_DP_TRACE_MED_VERBOSITY) 860 return true; 861 return false; 862 case QDF_DP_TRACE_VERBOSITY_LOW: 863 if (code <= QDF_DP_TRACE_LOW_VERBOSITY) 864 return true; 865 return false; 866 case QDF_DP_TRACE_VERBOSITY_DEFAULT: 867 if (code <= QDF_DP_TRACE_DEFAULT_VERBOSITY) 868 return true; 869 return false; 870 default: 871 return false; 872 } 873 } 874 EXPORT_SYMBOL(qdf_dp_trace_enable_track); 875 876 /** 877 * qdf_dp_get_proto_bitmap() - get dp trace proto bitmap 878 * 879 * Return: proto bitmap 880 */ 881 uint8_t qdf_dp_get_proto_bitmap(void) 882 { 883 if (g_qdf_dp_trace_data.enable) 884 return g_qdf_dp_trace_data.proto_bitmap; 885 else 886 return 0; 887 } 888 889 /** 890 * qdf_dp_trace_set_track() - Marks whether the packet needs to be traced 891 * @nbuf: defines the netbuf 892 * @dir: direction 893 * 894 * Return: None 895 */ 896 void qdf_dp_trace_set_track(qdf_nbuf_t nbuf, enum qdf_proto_dir dir) 897 { 898 uint32_t count = 0; 899 900 spin_lock_bh(&l_dp_trace_lock); 901 if (QDF_TX == dir) 902 count = ++g_qdf_dp_trace_data.tx_count; 903 else if (QDF_RX == dir) 904 count = ++g_qdf_dp_trace_data.rx_count; 905 906 if ((g_qdf_dp_trace_data.no_of_record != 0) && 907 (count % g_qdf_dp_trace_data.no_of_record == 0)) { 908 if (QDF_TX == dir) 909 QDF_NBUF_CB_TX_DP_TRACE(nbuf) = 1; 910 else if (QDF_RX == dir) 911 QDF_NBUF_CB_RX_DP_TRACE(nbuf) = 1; 912 } 913 spin_unlock_bh(&l_dp_trace_lock); 914 return; 915 } 916 EXPORT_SYMBOL(qdf_dp_trace_set_track); 917 918 #define DPTRACE_PRINT(args...) \ 919 QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, ## args) 920 921 /** 922 * dump_hex_trace() - Display the data in buffer 923 * @str: string to prepend the hexdump with. 924 * @buf: buffer which contains data to be displayed 925 * @buf_len: defines the size of the data to be displayed 926 * 927 * Return: None 928 */ 929 static void dump_hex_trace(char *str, uint8_t *buf, uint8_t buf_len) 930 { 931 unsigned char linebuf[BUFFER_SIZE]; 932 const u8 *ptr = buf; 933 int i, linelen, remaining = buf_len; 934 935 /* Dump the bytes in the last line */ 936 for (i = 0; i < buf_len; i += ROW_SIZE) { 937 linelen = min(remaining, ROW_SIZE); 938 remaining -= ROW_SIZE; 939 940 hex_dump_to_buffer(ptr + i, linelen, ROW_SIZE, 1, 941 linebuf, sizeof(linebuf), false); 942 943 DPTRACE_PRINT("DPT: %s: %s", str, linebuf); 944 } 945 } 946 947 /** 948 * qdf_dp_code_to_string() - convert dptrace code to string 949 * @code: dptrace code 950 * 951 * Return: string version of code 952 */ 953 static 954 const char *qdf_dp_code_to_string(enum QDF_DP_TRACE_ID code) 955 { 956 switch (code) { 957 case QDF_DP_TRACE_DROP_PACKET_RECORD: 958 return "DROP:"; 959 case QDF_DP_TRACE_EAPOL_PACKET_RECORD: 960 return "EAPOL:"; 961 case QDF_DP_TRACE_DHCP_PACKET_RECORD: 962 return "DHCP:"; 963 case QDF_DP_TRACE_ARP_PACKET_RECORD: 964 return "ARP:"; 965 case QDF_DP_TRACE_MGMT_PACKET_RECORD: 966 return "MGMT:"; 967 case QDF_DP_TRACE_EVENT_RECORD: 968 return "EVENT:"; 969 case QDF_DP_TRACE_HDD_TX_PACKET_PTR_RECORD: 970 return "HDD: TX: PTR:"; 971 case QDF_DP_TRACE_HDD_TX_PACKET_RECORD: 972 return "HDD: TX: DATA:"; 973 case QDF_DP_TRACE_CE_PACKET_PTR_RECORD: 974 return "CE: TX: PTR:"; 975 case QDF_DP_TRACE_CE_FAST_PACKET_PTR_RECORD: 976 return "CE: TX: FAST: PTR:"; 977 case QDF_DP_TRACE_FREE_PACKET_PTR_RECORD: 978 return "FREE: TX: PTR:"; 979 case QDF_DP_TRACE_RX_HTT_PACKET_PTR_RECORD: 980 return "HTT: RX: PTR:"; 981 case QDF_DP_TRACE_RX_OFFLOAD_HTT_PACKET_PTR_RECORD: 982 return "HTT: RX: OF: PTR:"; 983 case QDF_DP_TRACE_RX_HDD_PACKET_PTR_RECORD: 984 return "HDD: RX: PTR:"; 985 case QDF_DP_TRACE_HDD_RX_PACKET_RECORD: 986 return "HDD: RX: DATA:"; 987 case QDF_DP_TRACE_TXRX_QUEUE_PACKET_PTR_RECORD: 988 return "TXRX: TX: Q: PTR:"; 989 case QDF_DP_TRACE_TXRX_PACKET_PTR_RECORD: 990 return "TXRX: TX: PTR:"; 991 case QDF_DP_TRACE_TXRX_FAST_PACKET_PTR_RECORD: 992 return "TXRX: TX: FAST: PTR:"; 993 case QDF_DP_TRACE_HTT_PACKET_PTR_RECORD: 994 return "HTT: TX: PTR:"; 995 case QDF_DP_TRACE_HTC_PACKET_PTR_RECORD: 996 return "HTC: TX: PTR:"; 997 case QDF_DP_TRACE_HIF_PACKET_PTR_RECORD: 998 return "HIF: TX: PTR:"; 999 case QDF_DP_TRACE_RX_TXRX_PACKET_PTR_RECORD: 1000 return "TXRX: RX: PTR:"; 1001 case QDF_DP_TRACE_HDD_TX_TIMEOUT: 1002 return "HDD: STA: TO:"; 1003 case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT: 1004 return "HDD: SAP: TO:"; 1005 default: 1006 return "Invalid"; 1007 } 1008 } 1009 1010 /** 1011 * qdf_dp_dir_to_str() - convert direction to string 1012 * @dir: direction 1013 * 1014 * Return: string version of direction 1015 */ 1016 static const char *qdf_dp_dir_to_str(enum qdf_proto_dir dir) 1017 { 1018 switch (dir) { 1019 case QDF_TX: 1020 return " --> "; 1021 case QDF_RX: 1022 return " <-- "; 1023 default: 1024 return "invalid"; 1025 } 1026 } 1027 1028 /** 1029 * qdf_dp_type_to_str() - convert packet type to string 1030 * @type: type 1031 * 1032 * Return: string version of packet type 1033 */ 1034 static const char *qdf_dp_type_to_str(enum qdf_proto_type type) 1035 { 1036 switch (type) { 1037 case QDF_PROTO_TYPE_DHCP: 1038 return "DHCP"; 1039 case QDF_PROTO_TYPE_EAPOL: 1040 return "EAPOL"; 1041 case QDF_PROTO_TYPE_ARP: 1042 return "ARP"; 1043 case QDF_PROTO_TYPE_MGMT: 1044 return "MGMT"; 1045 case QDF_PROTO_TYPE_EVENT: 1046 return "EVENT"; 1047 default: 1048 return "invalid"; 1049 } 1050 } 1051 1052 /** 1053 * qdf_dp_subtype_to_str() - convert packet subtype to string 1054 * @type: type 1055 * 1056 * Return: string version of packet subtype 1057 */ 1058 static const char *qdf_dp_subtype_to_str(enum qdf_proto_subtype subtype) 1059 { 1060 switch (subtype) { 1061 case QDF_PROTO_EAPOL_M1: 1062 return "M1"; 1063 case QDF_PROTO_EAPOL_M2: 1064 return "M2"; 1065 case QDF_PROTO_EAPOL_M3: 1066 return "M3"; 1067 case QDF_PROTO_EAPOL_M4: 1068 return "M4"; 1069 case QDF_PROTO_DHCP_DISCOVER: 1070 return "DISCOVER"; 1071 case QDF_PROTO_DHCP_REQUEST: 1072 return "REQUEST"; 1073 case QDF_PROTO_DHCP_OFFER: 1074 return "OFFER"; 1075 case QDF_PROTO_DHCP_ACK: 1076 return "ACK"; 1077 case QDF_PROTO_DHCP_NACK: 1078 return "NACK"; 1079 case QDF_PROTO_DHCP_RELEASE: 1080 return "RELEASE"; 1081 case QDF_PROTO_DHCP_INFORM: 1082 return "INFORM"; 1083 case QDF_PROTO_DHCP_DECLINE: 1084 return "DECLINE"; 1085 case QDF_PROTO_ARP_REQ: 1086 return "REQUEST"; 1087 case QDF_PROTO_ARP_RES: 1088 return "RESPONSE"; 1089 case QDF_PROTO_MGMT_ASSOC: 1090 return "ASSOC"; 1091 case QDF_PROTO_MGMT_DISASSOC: 1092 return "DISASSOC"; 1093 case QDF_PROTO_MGMT_AUTH: 1094 return "AUTH"; 1095 case QDF_PROTO_MGMT_DEAUTH: 1096 return "DEAUTH"; 1097 case QDF_ROAM_SYNCH: 1098 return "ROAM SYNCH"; 1099 case QDF_ROAM_COMPLETE: 1100 return "ROAM COMPLETE"; 1101 case QDF_ROAM_EVENTID: 1102 return "ROAM EVENTID"; 1103 default: 1104 return "invalid"; 1105 } 1106 } 1107 1108 /** 1109 * qdf_dp_enable_check() - check if dptrace is enable or not 1110 * @nbuf: nbuf 1111 * @code: dptrace code 1112 * 1113 * Return: true/false 1114 */ 1115 static bool qdf_dp_enable_check(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code, 1116 enum qdf_proto_dir dir) 1117 { 1118 /* Return when Dp trace is not enabled */ 1119 if (!g_qdf_dp_trace_data.enable) 1120 return false; 1121 1122 if (qdf_dp_trace_enable_track(code) == false) 1123 return false; 1124 1125 if ((nbuf) && ((QDF_NBUF_CB_TX_PACKET_TRACK(nbuf) != 1126 QDF_NBUF_TX_PKT_DATA_TRACK) || 1127 ((dir == QDF_TX) && (QDF_NBUF_CB_TX_DP_TRACE(nbuf) == 0)) || 1128 ((dir == QDF_RX) && (QDF_NBUF_CB_RX_DP_TRACE(nbuf) == 0)))) 1129 return false; 1130 1131 return true; 1132 } 1133 1134 /** 1135 * qdf_dp_add_record() - add dp trace record 1136 * @code: dptrace code 1137 * @data: data pointer 1138 * @size: size of buffer 1139 * @print: true to print it in kmsg 1140 * 1141 * Return: none 1142 */ 1143 static void qdf_dp_add_record(enum QDF_DP_TRACE_ID code, 1144 uint8_t *data, uint8_t size, bool print) 1145 { 1146 struct qdf_dp_trace_record_s *rec = NULL; 1147 int index; 1148 spin_lock_bh(&l_dp_trace_lock); 1149 1150 g_qdf_dp_trace_data.num++; 1151 1152 if (g_qdf_dp_trace_data.num > MAX_QDF_DP_TRACE_RECORDS) 1153 g_qdf_dp_trace_data.num = MAX_QDF_DP_TRACE_RECORDS; 1154 1155 if (INVALID_QDF_DP_TRACE_ADDR == g_qdf_dp_trace_data.head) { 1156 /* first record */ 1157 g_qdf_dp_trace_data.head = 0; 1158 g_qdf_dp_trace_data.tail = 0; 1159 } else { 1160 /* queue is not empty */ 1161 g_qdf_dp_trace_data.tail++; 1162 1163 if (MAX_QDF_DP_TRACE_RECORDS == g_qdf_dp_trace_data.tail) 1164 g_qdf_dp_trace_data.tail = 0; 1165 1166 if (g_qdf_dp_trace_data.head == g_qdf_dp_trace_data.tail) { 1167 /* full */ 1168 if (MAX_QDF_DP_TRACE_RECORDS == 1169 ++g_qdf_dp_trace_data.head) 1170 g_qdf_dp_trace_data.head = 0; 1171 } 1172 } 1173 1174 rec = &g_qdf_dp_trace_tbl[g_qdf_dp_trace_data.tail]; 1175 index = g_qdf_dp_trace_data.tail; 1176 rec->code = code; 1177 rec->size = 0; 1178 if (data != NULL && size > 0) { 1179 if (size > QDF_DP_TRACE_RECORD_SIZE) 1180 size = QDF_DP_TRACE_RECORD_SIZE; 1181 1182 rec->size = size; 1183 qdf_mem_copy(rec->data, data, size); 1184 } 1185 qdf_get_time_of_the_day_in_hr_min_sec_usec(rec->time, 1186 sizeof(rec->time)); 1187 rec->pid = (in_interrupt() ? 0 : current->pid); 1188 spin_unlock_bh(&l_dp_trace_lock); 1189 1190 if ((g_qdf_dp_trace_data.live_mode || (print == true)) && 1191 (rec->code < QDF_DP_TRACE_MAX)) 1192 qdf_dp_trace_cb_table[rec->code] (rec, index); 1193 } 1194 1195 1196 /** 1197 * qdf_log_eapol_pkt() - log EAPOL packet 1198 * @session_id: vdev_id 1199 * @skb: skb pointer 1200 * @dir: direction 1201 * 1202 * Return: true/false 1203 */ 1204 static bool qdf_log_eapol_pkt(uint8_t session_id, struct sk_buff *skb, 1205 enum qdf_proto_dir dir) 1206 { 1207 enum qdf_proto_subtype subtype; 1208 1209 if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_EAPOL) && 1210 ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_EAPOL == 1211 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) || 1212 (dir == QDF_RX && qdf_nbuf_is_ipv4_eapol_pkt(skb) == true))) { 1213 1214 subtype = qdf_nbuf_get_eapol_subtype(skb); 1215 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_EAPOL_PACKET_RECORD, 1216 session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET), 1217 (skb->data + QDF_NBUF_DEST_MAC_OFFSET), 1218 QDF_PROTO_TYPE_EAPOL, subtype, dir)); 1219 if (QDF_TX == dir) 1220 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1; 1221 else if (QDF_RX == dir) 1222 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1; 1223 1224 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true; 1225 return true; 1226 } 1227 return false; 1228 } 1229 1230 /** 1231 * qdf_log_dhcp_pkt() - log DHCP packet 1232 * @session_id: vdev_id 1233 * @skb: skb pointer 1234 * @dir: direction 1235 * 1236 * Return: true/false 1237 */ 1238 static bool qdf_log_dhcp_pkt(uint8_t session_id, struct sk_buff *skb, 1239 enum qdf_proto_dir dir) 1240 { 1241 enum qdf_proto_subtype subtype = QDF_PROTO_INVALID; 1242 1243 if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_DHCP) && 1244 ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_DHCP == 1245 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) || 1246 (dir == QDF_RX && qdf_nbuf_is_ipv4_dhcp_pkt(skb) == true))) { 1247 1248 subtype = qdf_nbuf_get_dhcp_subtype(skb); 1249 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_DHCP_PACKET_RECORD, 1250 session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET), 1251 (skb->data + QDF_NBUF_DEST_MAC_OFFSET), 1252 QDF_PROTO_TYPE_DHCP, subtype, dir)); 1253 if (QDF_TX == dir) 1254 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1; 1255 else if (QDF_RX == dir) 1256 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1; 1257 1258 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true; 1259 return true; 1260 } 1261 return false; 1262 } 1263 1264 /** 1265 * qdf_log_arp_pkt() - log ARP packet 1266 * @session_id: vdev_id 1267 * @skb: skb pointer 1268 * @dir: direction 1269 * 1270 * Return: true/false 1271 */ 1272 static bool qdf_log_arp_pkt(uint8_t session_id, struct sk_buff *skb, 1273 enum qdf_proto_dir dir) 1274 { 1275 enum qdf_proto_subtype proto_subtype; 1276 1277 if ((qdf_dp_get_proto_bitmap() & QDF_NBUF_PKT_TRAC_TYPE_ARP) && 1278 ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_ARP == 1279 QDF_NBUF_CB_GET_PACKET_TYPE(skb)) || 1280 (dir == QDF_RX && qdf_nbuf_is_ipv4_arp_pkt(skb) == true))) { 1281 1282 proto_subtype = qdf_nbuf_get_arp_subtype(skb); 1283 DPTRACE(qdf_dp_trace_proto_pkt(QDF_DP_TRACE_ARP_PACKET_RECORD, 1284 session_id, (skb->data + QDF_NBUF_SRC_MAC_OFFSET), 1285 (skb->data + QDF_NBUF_DEST_MAC_OFFSET), 1286 QDF_PROTO_TYPE_ARP, proto_subtype, dir)); 1287 if (QDF_TX == dir) 1288 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1; 1289 else if (QDF_RX == dir) 1290 QDF_NBUF_CB_RX_DP_TRACE(skb) = 1; 1291 1292 QDF_NBUF_CB_DP_TRACE_PRINT(skb) = true; 1293 return true; 1294 } 1295 return false; 1296 } 1297 1298 /** 1299 * qdf_dp_trace_log_pkt() - log packet type enabled through iwpriv 1300 * @session_id: vdev_id 1301 * @skb: skb pointer 1302 * @dir: direction 1303 * 1304 * Return: none 1305 */ 1306 void qdf_dp_trace_log_pkt(uint8_t session_id, struct sk_buff *skb, 1307 enum qdf_proto_dir dir) 1308 { 1309 if (qdf_dp_get_proto_bitmap()) { 1310 if (qdf_log_arp_pkt(session_id, 1311 skb, dir) == false) { 1312 if (qdf_log_dhcp_pkt(session_id, 1313 skb, dir) == false) { 1314 if (qdf_log_eapol_pkt(session_id, 1315 skb, dir) == false) { 1316 return; 1317 } 1318 } 1319 } 1320 } 1321 } 1322 EXPORT_SYMBOL(qdf_dp_trace_log_pkt); 1323 1324 /** 1325 * qdf_dp_display_mgmt_pkt() - display proto packet 1326 * @record: dptrace record 1327 * @index: index 1328 * 1329 * Return: none 1330 */ 1331 void qdf_dp_display_mgmt_pkt(struct qdf_dp_trace_record_s *record, 1332 uint16_t index) 1333 { 1334 struct qdf_dp_trace_mgmt_buf *buf = 1335 (struct qdf_dp_trace_mgmt_buf *)record->data; 1336 1337 DPTRACE_PRINT("DPT: %04d: %s: %s vdev_id %d", index, 1338 record->time, qdf_dp_code_to_string(record->code), 1339 buf->vdev_id); 1340 DPTRACE_PRINT("DPT: Type %s Subtype %s", qdf_dp_type_to_str(buf->type), 1341 qdf_dp_subtype_to_str(buf->subtype)); 1342 } 1343 EXPORT_SYMBOL(qdf_dp_display_mgmt_pkt); 1344 1345 /** 1346 * qdf_dp_trace_mgmt_pkt() - record mgmt packet 1347 * @code: dptrace code 1348 * @vdev_id: vdev id 1349 * @type: proto type 1350 * @subtype: proto subtype 1351 * 1352 * Return: none 1353 */ 1354 void qdf_dp_trace_mgmt_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id, 1355 enum qdf_proto_type type, enum qdf_proto_subtype subtype) 1356 { 1357 struct qdf_dp_trace_mgmt_buf buf; 1358 int buf_size = sizeof(struct qdf_dp_trace_mgmt_buf); 1359 1360 if (qdf_dp_enable_check(NULL, code, QDF_NA) == false) 1361 return; 1362 1363 if (buf_size > QDF_DP_TRACE_RECORD_SIZE) 1364 QDF_BUG(0); 1365 1366 buf.type = type; 1367 buf.subtype = subtype; 1368 buf.vdev_id = vdev_id; 1369 qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, true); 1370 } 1371 EXPORT_SYMBOL(qdf_dp_trace_mgmt_pkt); 1372 1373 /** 1374 * qdf_dp_display_event_record() - display event records 1375 * @record: dptrace record 1376 * @index: index 1377 * 1378 * Return: none 1379 */ 1380 void qdf_dp_display_event_record(struct qdf_dp_trace_record_s *record, 1381 uint16_t index) 1382 { 1383 struct qdf_dp_trace_event_buf *buf = 1384 (struct qdf_dp_trace_event_buf *)record->data; 1385 1386 DPTRACE_PRINT("DPT: %04d: %s: %s vdev_id %d", index, 1387 record->time, qdf_dp_code_to_string(record->code), 1388 buf->vdev_id); 1389 DPTRACE_PRINT("DPT: Type %s Subtype %s", qdf_dp_type_to_str(buf->type), 1390 qdf_dp_subtype_to_str(buf->subtype)); 1391 } 1392 EXPORT_SYMBOL(qdf_dp_display_event_record); 1393 1394 /** 1395 * qdf_dp_trace_record_event() - record events 1396 * @code: dptrace code 1397 * @vdev_id: vdev id 1398 * @type: proto type 1399 * @subtype: proto subtype 1400 * 1401 * Return: none 1402 */ 1403 void qdf_dp_trace_record_event(enum QDF_DP_TRACE_ID code, uint8_t vdev_id, 1404 enum qdf_proto_type type, enum qdf_proto_subtype subtype) 1405 { 1406 struct qdf_dp_trace_event_buf buf; 1407 int buf_size = sizeof(struct qdf_dp_trace_event_buf); 1408 1409 if (qdf_dp_enable_check(NULL, code, QDF_NA) == false) 1410 return; 1411 1412 if (buf_size > QDF_DP_TRACE_RECORD_SIZE) 1413 QDF_BUG(0); 1414 1415 buf.type = type; 1416 buf.subtype = subtype; 1417 buf.vdev_id = vdev_id; 1418 qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, true); 1419 } 1420 EXPORT_SYMBOL(qdf_dp_trace_record_event); 1421 1422 /** 1423 * qdf_dp_display_proto_pkt() - display proto packet 1424 * @record: dptrace record 1425 * @index: index 1426 * 1427 * Return: none 1428 */ 1429 void qdf_dp_display_proto_pkt(struct qdf_dp_trace_record_s *record, 1430 uint16_t index) 1431 { 1432 struct qdf_dp_trace_proto_buf *buf = 1433 (struct qdf_dp_trace_proto_buf *)record->data; 1434 1435 DPTRACE_PRINT("DPT: %04d: %s: %s vdev_id %d", index, 1436 record->time, qdf_dp_code_to_string(record->code), 1437 buf->vdev_id); 1438 DPTRACE_PRINT("DPT: SA: " QDF_MAC_ADDRESS_STR " %s DA: " 1439 QDF_MAC_ADDRESS_STR " Type %s Subtype %s", 1440 QDF_MAC_ADDR_ARRAY(buf->sa.bytes), qdf_dp_dir_to_str(buf->dir), 1441 QDF_MAC_ADDR_ARRAY(buf->da.bytes), 1442 qdf_dp_type_to_str(buf->type), 1443 qdf_dp_subtype_to_str(buf->subtype)); 1444 } 1445 EXPORT_SYMBOL(qdf_dp_display_proto_pkt); 1446 1447 /** 1448 * qdf_dp_trace_proto_pkt() - record proto packet 1449 * @code: dptrace code 1450 * @vdev_id: vdev id 1451 * @sa: source mac address 1452 * @da: destination mac address 1453 * @type: proto type 1454 * @subtype: proto subtype 1455 * @dir: direction 1456 * 1457 * Return: none 1458 */ 1459 void qdf_dp_trace_proto_pkt(enum QDF_DP_TRACE_ID code, uint8_t vdev_id, 1460 uint8_t *sa, uint8_t *da, enum qdf_proto_type type, 1461 enum qdf_proto_subtype subtype, enum qdf_proto_dir dir) 1462 { 1463 struct qdf_dp_trace_proto_buf buf; 1464 int buf_size = sizeof(struct qdf_dp_trace_ptr_buf); 1465 1466 if (qdf_dp_enable_check(NULL, code, dir) == false) 1467 return; 1468 1469 if (buf_size > QDF_DP_TRACE_RECORD_SIZE) 1470 QDF_BUG(0); 1471 1472 memcpy(&buf.sa, sa, QDF_NET_ETH_LEN); 1473 memcpy(&buf.da, da, QDF_NET_ETH_LEN); 1474 buf.dir = dir; 1475 buf.type = type; 1476 buf.subtype = subtype; 1477 buf.vdev_id = vdev_id; 1478 qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, true); 1479 } 1480 EXPORT_SYMBOL(qdf_dp_trace_proto_pkt); 1481 1482 /** 1483 * qdf_dp_display_ptr_record() - display record 1484 * @record: dptrace record 1485 * @index: index 1486 * 1487 * Return: none 1488 */ 1489 void qdf_dp_display_ptr_record(struct qdf_dp_trace_record_s *record, 1490 uint16_t index) 1491 { 1492 struct qdf_dp_trace_ptr_buf *buf = 1493 (struct qdf_dp_trace_ptr_buf *)record->data; 1494 1495 if (record->code == QDF_DP_TRACE_FREE_PACKET_PTR_RECORD) 1496 DPTRACE_PRINT("DPT: %04d: %s: %s msdu_id: %d, status: %d", 1497 index, record->time, 1498 qdf_dp_code_to_string(record->code), buf->msdu_id, 1499 buf->status); 1500 else 1501 DPTRACE_PRINT("DPT: %04d: %s: %s msdu_id: %d, vdev_id: %d", 1502 index, 1503 record->time, qdf_dp_code_to_string(record->code), 1504 buf->msdu_id, buf->status); 1505 dump_hex_trace("cookie", (uint8_t *)&buf->cookie, sizeof(buf->cookie)); 1506 } 1507 EXPORT_SYMBOL(qdf_dp_display_ptr_record); 1508 1509 /** 1510 * qdf_dp_trace_ptr() - record dptrace 1511 * @code: dptrace code 1512 * @data: data 1513 * @size: size of data 1514 * @msdu_id: msdu_id 1515 * @status: return status 1516 * 1517 * Return: none 1518 */ 1519 void qdf_dp_trace_ptr(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code, 1520 uint8_t *data, uint8_t size, uint16_t msdu_id, uint16_t status) 1521 { 1522 struct qdf_dp_trace_ptr_buf buf; 1523 int buf_size = sizeof(struct qdf_dp_trace_ptr_buf); 1524 1525 if (qdf_dp_enable_check(nbuf, code, QDF_TX) == false) 1526 return; 1527 1528 if (buf_size > QDF_DP_TRACE_RECORD_SIZE) 1529 QDF_BUG(0); 1530 1531 qdf_mem_copy(&buf.cookie, data, size); 1532 buf.msdu_id = msdu_id; 1533 buf.status = status; 1534 qdf_dp_add_record(code, (uint8_t *)&buf, buf_size, 1535 QDF_NBUF_CB_DP_TRACE_PRINT(nbuf)); 1536 } 1537 EXPORT_SYMBOL(qdf_dp_trace_ptr); 1538 1539 /** 1540 * qdf_dp_display_trace() - Displays a record in DP trace 1541 * @pRecord : pointer to a record in DP trace 1542 * @recIndex : record index 1543 * 1544 * Return: None 1545 */ 1546 void qdf_dp_display_record(struct qdf_dp_trace_record_s *pRecord, 1547 uint16_t recIndex) 1548 { 1549 DPTRACE_PRINT("DPT: %04d: %s: %s", recIndex, 1550 pRecord->time, qdf_dp_code_to_string(pRecord->code)); 1551 switch (pRecord->code) { 1552 case QDF_DP_TRACE_HDD_TX_TIMEOUT: 1553 DPTRACE_PRINT("DPT: HDD TX Timeout\n"); 1554 break; 1555 case QDF_DP_TRACE_HDD_SOFTAP_TX_TIMEOUT: 1556 DPTRACE_PRINT("DPT: HDD SoftAP TX Timeout\n"); 1557 break; 1558 case QDF_DP_TRACE_HDD_TX_PACKET_RECORD: 1559 case QDF_DP_TRACE_HDD_RX_PACKET_RECORD: 1560 dump_hex_trace("DATA", pRecord->data, pRecord->size); 1561 break; 1562 default: 1563 dump_hex_trace("cookie", pRecord->data, pRecord->size); 1564 } 1565 } 1566 EXPORT_SYMBOL(qdf_dp_display_record); 1567 1568 1569 /** 1570 * qdf_dp_trace() - Stores the data in buffer 1571 * @nbuf : defines the netbuf 1572 * @code : defines the event 1573 * @data : defines the data to be stored 1574 * @size : defines the size of the data record 1575 * 1576 * Return: None 1577 */ 1578 void qdf_dp_trace(qdf_nbuf_t nbuf, enum QDF_DP_TRACE_ID code, 1579 uint8_t *data, uint8_t size, enum qdf_proto_dir dir) 1580 { 1581 1582 if (qdf_dp_enable_check(nbuf, code, dir) == false) 1583 return; 1584 1585 qdf_dp_add_record(code, data, size, 1586 (nbuf != NULL) ? QDF_NBUF_CB_DP_TRACE_PRINT(nbuf) : false); 1587 } 1588 EXPORT_SYMBOL(qdf_dp_trace); 1589 1590 /** 1591 * qdf_dp_trace_spin_lock_init() - initializes the lock variable before use 1592 * This function will be called from cds_alloc_global_context, we will have lock 1593 * available to use ASAP 1594 * 1595 * Return: None 1596 */ 1597 void qdf_dp_trace_spin_lock_init(void) 1598 { 1599 spin_lock_init(&l_dp_trace_lock); 1600 } 1601 EXPORT_SYMBOL(qdf_dp_trace_spin_lock_init); 1602 1603 /** 1604 * qdf_dp_trace_enable_live_mode() - enable live mode for dptrace 1605 * 1606 * Return: none 1607 */ 1608 void qdf_dp_trace_enable_live_mode(void) 1609 { 1610 g_qdf_dp_trace_data.live_mode = 1; 1611 1612 } 1613 EXPORT_SYMBOL(qdf_dp_trace_enable_live_mode); 1614 1615 1616 /** 1617 * qdf_dp_trace_clear_buffer() - clear dp trace buffer 1618 * 1619 * Return: none 1620 */ 1621 void qdf_dp_trace_clear_buffer(void) 1622 { 1623 g_qdf_dp_trace_data.head = INVALID_QDF_DP_TRACE_ADDR; 1624 g_qdf_dp_trace_data.tail = INVALID_QDF_DP_TRACE_ADDR; 1625 g_qdf_dp_trace_data.num = 0; 1626 g_qdf_dp_trace_data.proto_bitmap = QDF_NBUF_PKT_TRAC_TYPE_EAPOL | 1627 QDF_NBUF_PKT_TRAC_TYPE_DHCP | 1628 QDF_NBUF_PKT_TRAC_TYPE_MGMT_ACTION | 1629 QDF_NBUF_PKT_TRAC_TYPE_ARP; 1630 g_qdf_dp_trace_data.no_of_record = 0; 1631 g_qdf_dp_trace_data.verbosity = QDF_DP_TRACE_VERBOSITY_HIGH; 1632 g_qdf_dp_trace_data.enable = true; 1633 g_qdf_dp_trace_data.tx_count = 0; 1634 g_qdf_dp_trace_data.rx_count = 0; 1635 g_qdf_dp_trace_data.live_mode = 0; 1636 1637 memset(g_qdf_dp_trace_tbl, 0, 1638 MAX_QDF_DP_TRACE_RECORDS * sizeof(struct qdf_dp_trace_record_s)); 1639 } 1640 EXPORT_SYMBOL(qdf_dp_trace_clear_buffer); 1641 1642 /** 1643 * qdf_dp_trace_dump_all() - Dump data from ring buffer via call back functions 1644 * registered with QDF 1645 * @code: Reason code 1646 * @count: Number of lines to dump starting from tail to head 1647 * 1648 * Return: None 1649 */ 1650 void qdf_dp_trace_dump_all(uint32_t count) 1651 { 1652 struct qdf_dp_trace_record_s p_record; 1653 int32_t i, tail; 1654 1655 if (!g_qdf_dp_trace_data.enable) { 1656 QDF_TRACE(QDF_MODULE_ID_SYS, 1657 QDF_TRACE_LEVEL_ERROR, "Tracing Disabled"); 1658 return; 1659 } 1660 1661 QDF_TRACE(QDF_MODULE_ID_SYS, QDF_TRACE_LEVEL_ERROR, 1662 "Total Records: %d, Head: %d, Tail: %d", 1663 g_qdf_dp_trace_data.num, g_qdf_dp_trace_data.head, 1664 g_qdf_dp_trace_data.tail); 1665 1666 /* aquire the lock so that only one thread at a time can read 1667 * the ring buffer 1668 */ 1669 spin_lock_bh(&l_dp_trace_lock); 1670 1671 if (g_qdf_dp_trace_data.head != INVALID_QDF_DP_TRACE_ADDR) { 1672 i = g_qdf_dp_trace_data.head; 1673 tail = g_qdf_dp_trace_data.tail; 1674 1675 if (count) { 1676 if (count > g_qdf_dp_trace_data.num) 1677 count = g_qdf_dp_trace_data.num; 1678 if (tail >= (count - 1)) 1679 i = tail - count + 1; 1680 else if (count != MAX_QDF_DP_TRACE_RECORDS) 1681 i = MAX_QDF_DP_TRACE_RECORDS - ((count - 1) - 1682 tail); 1683 } 1684 1685 p_record = g_qdf_dp_trace_tbl[i]; 1686 spin_unlock_bh(&l_dp_trace_lock); 1687 for (;; ) { 1688 1689 qdf_dp_trace_cb_table[p_record. 1690 code] (&p_record, (uint16_t)i); 1691 if (i == tail) 1692 break; 1693 i += 1; 1694 1695 spin_lock_bh(&l_dp_trace_lock); 1696 if (MAX_QDF_DP_TRACE_RECORDS == i) 1697 i = 0; 1698 1699 p_record = g_qdf_dp_trace_tbl[i]; 1700 spin_unlock_bh(&l_dp_trace_lock); 1701 } 1702 } else { 1703 spin_unlock_bh(&l_dp_trace_lock); 1704 } 1705 } 1706 EXPORT_SYMBOL(qdf_dp_trace_dump_all); 1707 1708 #endif 1709 1710 #else /* CONFIG_MCL */ 1711 1712 void qdf_trace_msg(QDF_MODULE_ID module, QDF_TRACE_LEVEL level, 1713 char *str_format, ...) 1714 { 1715 va_list val; 1716 1717 va_start(val, str_format); 1718 /* 1719 * TODO: remove this hack when modules start using the qdf_print_ctrl 1720 * framework. 1721 * Any newly added code that wishes to use QDF_TRACE needs to adapt 1722 * to the framework, and using it this way is not encouraged. 1723 */ 1724 qdf_trace_msg_cmn(qdf_pidx, module, level, str_format, val); 1725 va_end(val); 1726 } 1727 EXPORT_SYMBOL(qdf_trace_msg); 1728 #endif /* CONFIG_MCL */ 1729 1730 struct qdf_print_ctrl print_ctrl_obj[MAX_PRINT_CONFIG_SUPPORTED]; 1731 1732 struct category_name_info g_qdf_category_name[MAX_SUPPORTED_CATEGORY] = { 1733 [QDF_MODULE_ID_TDLS] = {"tdls"}, 1734 [QDF_MODULE_ID_ACS] = {"ACS"}, 1735 [QDF_MODULE_ID_SCAN_SM] = {"scan state machine"}, 1736 [QDF_MODULE_ID_SCANENTRY] = {"scan entry"}, 1737 [QDF_MODULE_ID_WDS] = {"WDS"}, 1738 [QDF_MODULE_ID_ACTION] = {"action"}, 1739 [QDF_MODULE_ID_ROAM] = {"STA roaming"}, 1740 [QDF_MODULE_ID_INACT] = {"inactivity"}, 1741 [QDF_MODULE_ID_DOTH] = {"11h"}, 1742 [QDF_MODULE_ID_IQUE] = {"IQUE"}, 1743 [QDF_MODULE_ID_WME] = {"WME"}, 1744 [QDF_MODULE_ID_ACL] = {"ACL"}, 1745 [QDF_MODULE_ID_WPA] = {"WPA/RSN"}, 1746 [QDF_MODULE_ID_RADKEYS] = {"dump 802.1x keys"}, 1747 [QDF_MODULE_ID_RADDUMP] = {"dump radius packet"}, 1748 [QDF_MODULE_ID_RADIUS] = {"802.1x radius client"}, 1749 [QDF_MODULE_ID_DOT1XSM] = {"802.1x state machine"}, 1750 [QDF_MODULE_ID_DOT1X] = {"802.1x authenticator"}, 1751 [QDF_MODULE_ID_POWER] = {"power save"}, 1752 [QDF_MODULE_ID_STATE] = {"state"}, 1753 [QDF_MODULE_ID_OUTPUT] = {"output"}, 1754 [QDF_MODULE_ID_SCAN] = {"scan"}, 1755 [QDF_MODULE_ID_AUTH] = {"authentication"}, 1756 [QDF_MODULE_ID_ASSOC] = {"association"}, 1757 [QDF_MODULE_ID_NODE] = {"node"}, 1758 [QDF_MODULE_ID_ELEMID] = {"element ID"}, 1759 [QDF_MODULE_ID_XRATE] = {"rate"}, 1760 [QDF_MODULE_ID_INPUT] = {"input"}, 1761 [QDF_MODULE_ID_CRYPTO] = {"crypto"}, 1762 [QDF_MODULE_ID_DUMPPKTS] = {"dump packet"}, 1763 [QDF_MODULE_ID_DEBUG] = {"debug"}, 1764 [QDF_MODULE_ID_MLME] = {"mlme"}, 1765 [QDF_MODULE_ID_RRM] = {"rrm"}, 1766 [QDF_MODULE_ID_WNM] = {"wnm"}, 1767 [QDF_MODULE_ID_P2P_PROT] = {"p2p_prot"}, 1768 [QDF_MODULE_ID_PROXYARP] = {"proxyarp"}, 1769 [QDF_MODULE_ID_L2TIF] = {"l2tif"}, 1770 [QDF_MODULE_ID_WIFIPOS] = {"wifipos"}, 1771 [QDF_MODULE_ID_WRAP] = {"wrap"}, 1772 [QDF_MODULE_ID_DFS] = {"dfs"}, 1773 [QDF_MODULE_ID_ATF] = {"atf"}, 1774 [QDF_MODULE_ID_SPLITMAC] = {"splitmac"}, 1775 [QDF_MODULE_ID_IOCTL] = {"ioctl"}, 1776 [QDF_MODULE_ID_NAC] = {"nac"}, 1777 [QDF_MODULE_ID_MESH] = {"mesh"}, 1778 [QDF_MODULE_ID_MBO] = {"mbo"}, 1779 [QDF_MODULE_ID_EXTIOCTL_CHANSWITCH] = {"extchanswitch"}, 1780 [QDF_MODULE_ID_EXTIOCTL_CHANSSCAN] = {"extchanscan"}, 1781 [QDF_MODULE_ID_TLSHIM] = {"tlshim"}, 1782 [QDF_MODULE_ID_WMI] = {"WMI"}, 1783 [QDF_MODULE_ID_HTT] = {"HTT"}, 1784 [QDF_MODULE_ID_HDD] = {"HDD"}, 1785 [QDF_MODULE_ID_SME] = {"SME"}, 1786 [QDF_MODULE_ID_PE] = {"PE"}, 1787 [QDF_MODULE_ID_WMA] = {"WMA"}, 1788 [QDF_MODULE_ID_SYS] = {"SYS"}, 1789 [QDF_MODULE_ID_QDF] = {"QDF"}, 1790 [QDF_MODULE_ID_SAP] = {"SAP"}, 1791 [QDF_MODULE_ID_HDD_SOFTAP] = {"HDD_SAP"}, 1792 [QDF_MODULE_ID_HDD_DATA] = {"DATA"}, 1793 [QDF_MODULE_ID_HDD_SAP_DATA] = {"SAP_DATA"}, 1794 [QDF_MODULE_ID_HIF] = {"HIF"}, 1795 [QDF_MODULE_ID_HTC] = {"HTC"}, 1796 [QDF_MODULE_ID_TXRX] = {"TXRX"}, 1797 [QDF_MODULE_ID_QDF_DEVICE] = {"QDF_DEV"}, 1798 [QDF_MODULE_ID_CFG] = {"CFG"}, 1799 [QDF_MODULE_ID_BMI] = {"BMI"}, 1800 [QDF_MODULE_ID_EPPING] = {"EPPING"}, 1801 [QDF_MODULE_ID_QVIT] = {"QVIT"}, 1802 [QDF_MODULE_ID_DP] = {"DP"}, 1803 [QDF_MODULE_ID_SOC] = {"SOC"}, 1804 [QDF_MODULE_ID_OS_IF] = {"OSIF"}, 1805 [QDF_MODULE_ID_TARGET_IF] = {"TIF"}, 1806 [QDF_MODULE_ID_SCHEDULER] = {"SCH"}, 1807 [QDF_MODULE_ID_MGMT_TXRX] = {"MGMT_TXRX"}, 1808 [QDF_MODULE_ID_PMO] = {"PMO"}, 1809 [QDF_MODULE_ID_POLICY_MGR] = {"POLICY_MGR"}, 1810 [QDF_MODULE_ID_NAN] = {"NAN"}, 1811 [QDF_MODULE_ID_P2P] = {"P2P"}, 1812 [QDF_MODULE_ID_OFFCHAN_TXRX] = {"OFFCHAN"}, 1813 [QDF_MODULE_ID_ANY] = {"ANY"}, 1814 }; 1815 1816 #ifdef CONFIG_MCL 1817 #define print_to_console(str) 1818 #else 1819 static inline void print_to_console(char *str_buffer) 1820 { 1821 pr_err("%s\n", str_buffer); 1822 } 1823 #endif 1824 1825 void qdf_trace_msg_cmn(unsigned int idx, 1826 QDF_MODULE_ID category, 1827 QDF_TRACE_LEVEL verbose, 1828 const char *str_format, va_list val) 1829 { 1830 char str_buffer[QDF_TRACE_BUFFER_SIZE]; 1831 int n; 1832 1833 /* Check if index passed is valid */ 1834 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 1835 pr_info("%s: Invalid index - %d\n", __func__, idx); 1836 return; 1837 } 1838 1839 /* Check if print control object is in use */ 1840 if (!print_ctrl_obj[idx].in_use) { 1841 pr_info("%s: Invalid print control object\n", __func__); 1842 return; 1843 } 1844 1845 /* Check if category passed is valid */ 1846 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) { 1847 pr_info("%s: Invalid category: %d\n", __func__, category); 1848 return; 1849 } 1850 1851 /* Check if verbose mask is valid */ 1852 if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) { 1853 pr_info("%s: Invalid verbose level %d\n", __func__, verbose); 1854 return; 1855 } 1856 1857 /* 1858 * Print the trace message when the desired verbose level is set in 1859 * the desired category for the print control object 1860 */ 1861 if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask & 1862 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) { 1863 /* 1864 * The verbose strings are in an array. These are ordered in 1865 * the same order as the verbose levels are defined in the enum 1866 * (see QDF_TRACE_LEVEL) so we can index into this array with 1867 * the level and get the right string. The qdf verbose 1868 * are... Off, Fatal, Error, Warning, Info, Info_high, 1869 * Info_med, Info_low, Debug 1870 */ 1871 static const char * const VERBOSE_STR[] = { " ", "F", "E", "W", 1872 "I", "IH", "IM", "IL", 1873 "D" }; 1874 1875 /* print the prefix string into the string buffer... */ 1876 n = scnprintf(str_buffer, QDF_TRACE_BUFFER_SIZE, 1877 "wlan: [%d:%2s:%s] ", 1878 in_interrupt() ? 0 : current->pid, 1879 VERBOSE_STR[verbose], 1880 g_qdf_category_name[category].category_name_str); 1881 1882 /* print the formatted log message after the prefix string */ 1883 vscnprintf(str_buffer + n, QDF_TRACE_BUFFER_SIZE - n, 1884 str_format, val); 1885 #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE) 1886 wlan_log_to_user(verbose, (char *)str_buffer, 1887 strlen(str_buffer)); 1888 print_to_console(str_buffer); 1889 #else 1890 pr_err("%s\n", str_buffer); 1891 #endif 1892 va_end(val); 1893 } 1894 } 1895 EXPORT_SYMBOL(qdf_trace_msg_cmn); 1896 1897 QDF_STATUS qdf_print_setup(void) 1898 { 1899 int i; 1900 1901 /* Loop through all print ctrl objects */ 1902 for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) { 1903 if (qdf_print_ctrl_cleanup(i)) 1904 return QDF_STATUS_E_FAILURE; 1905 } 1906 return QDF_STATUS_SUCCESS; 1907 } 1908 EXPORT_SYMBOL(qdf_print_setup); 1909 1910 QDF_STATUS qdf_print_ctrl_cleanup(unsigned int idx) 1911 { 1912 int i = 0; 1913 1914 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 1915 pr_info("%s: Invalid index - %d\n", __func__, idx); 1916 return QDF_STATUS_E_FAILURE; 1917 } 1918 1919 /* Clean up the print control object corresponding to that index 1920 * If success, callee to change print control index to -1 1921 */ 1922 1923 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) { 1924 print_ctrl_obj[idx].cat_info[i].category_verbose_mask = 1925 QDF_TRACE_LEVEL_NONE; 1926 } 1927 print_ctrl_obj[idx].custom_print = NULL; 1928 print_ctrl_obj[idx].custom_ctxt = NULL; 1929 qdf_print_clean_node_flag(idx); 1930 print_ctrl_obj[idx].in_use = false; 1931 1932 pr_info("%s: Print control object %d cleaned up\n", __func__, idx); 1933 1934 return QDF_STATUS_SUCCESS; 1935 } 1936 EXPORT_SYMBOL(qdf_print_ctrl_cleanup); 1937 1938 int qdf_print_ctrl_register(const struct category_info *cinfo, 1939 void *custom_print_handler, 1940 void *custom_ctx, 1941 const char *pctrl_name) 1942 { 1943 int idx = -1; 1944 int i = 0; 1945 1946 for (i = 0; i < MAX_PRINT_CONFIG_SUPPORTED; i++) { 1947 if (!print_ctrl_obj[i].in_use) { 1948 idx = i; 1949 break; 1950 } 1951 } 1952 1953 /* Callee to handle idx -1 appropriately */ 1954 if (idx == -1) { 1955 pr_info("%s: Allocation failed! No print control object free\n", 1956 __func__); 1957 return idx; 1958 } 1959 1960 print_ctrl_obj[idx].in_use = true; 1961 1962 /* 1963 * In case callee does not pass category info, 1964 * custom print handler, custom context and print control name, 1965 * we do not set any value here. Clean up for the print control 1966 * getting allocated would have taken care of initializing 1967 * default values. 1968 * 1969 * We need to only set in_use to 1 in such a case 1970 */ 1971 1972 if (pctrl_name) { 1973 qdf_str_lcopy(print_ctrl_obj[idx].name, pctrl_name, 1974 qdf_str_len(pctrl_name) + 1); 1975 } 1976 1977 if (custom_print_handler) 1978 print_ctrl_obj[idx].custom_print = custom_print_handler; 1979 1980 if (custom_ctx) 1981 print_ctrl_obj[idx].custom_ctxt = custom_ctx; 1982 1983 if (cinfo) { 1984 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) { 1985 if (cinfo[i].category_verbose_mask == 1986 QDF_TRACE_LEVEL_ALL) { 1987 print_ctrl_obj[idx].cat_info[i] 1988 .category_verbose_mask = 0xFFFF; 1989 } else { 1990 print_ctrl_obj[idx].cat_info[i] 1991 .category_verbose_mask = 1992 cinfo[i].category_verbose_mask; 1993 } 1994 } 1995 } 1996 1997 pr_info("%s: Allocated print control object %d\n", 1998 __func__, idx); 1999 return idx; 2000 } 2001 EXPORT_SYMBOL(qdf_print_ctrl_register); 2002 2003 #ifndef CONFIG_MCL 2004 void qdf_shared_print_ctrl_cleanup(void) 2005 { 2006 qdf_print_ctrl_cleanup(qdf_pidx); 2007 } 2008 EXPORT_SYMBOL(qdf_shared_print_ctrl_cleanup); 2009 2010 extern int qdf_dbg_mask; 2011 void qdf_shared_print_ctrl_init(void) 2012 { 2013 int i; 2014 QDF_TRACE_LEVEL level; 2015 struct category_info *cinfo = qdf_mem_malloc((sizeof(*cinfo))* 2016 MAX_SUPPORTED_CATEGORY); 2017 if (cinfo == NULL) { 2018 pr_info("ERROR!! qdf_mem_malloc failed. \ 2019 Shared Print Ctrl object not initialized \ 2020 \nQDF_TRACE messages may not be logged/displayed"); 2021 return; 2022 } 2023 for (i = 0; i < MAX_SUPPORTED_CATEGORY; i++) { 2024 cinfo[i].category_verbose_mask = 0; 2025 for (level = QDF_TRACE_LEVEL_NONE; level <= qdf_dbg_mask; level++) { 2026 cinfo[i].category_verbose_mask |= 2027 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(level); 2028 } 2029 } 2030 qdf_pidx = qdf_print_ctrl_register(cinfo, NULL, NULL, 2031 "LOG_SHARED_OBJ"); 2032 qdf_mem_free(cinfo); 2033 } 2034 EXPORT_SYMBOL(qdf_shared_print_ctrl_init); 2035 #endif 2036 2037 QDF_STATUS qdf_print_set_category_verbose(unsigned int idx, 2038 QDF_MODULE_ID category, 2039 QDF_TRACE_LEVEL verbose, 2040 bool is_set) 2041 { 2042 /* Check if index passed is valid */ 2043 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 2044 pr_info("%s: Invalid index - %d\n", __func__, idx); 2045 return QDF_STATUS_E_FAILURE; 2046 } 2047 2048 /* Check if print control object is in use */ 2049 if (!print_ctrl_obj[idx].in_use) { 2050 pr_info("%s: Invalid print control object\n", __func__); 2051 return QDF_STATUS_E_FAILURE; 2052 } 2053 2054 /* Check if category passed is valid */ 2055 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) { 2056 pr_info("%s: Invalid category: %d\n", __func__, category); 2057 return QDF_STATUS_E_FAILURE; 2058 } 2059 2060 /* Check if verbose mask is valid */ 2061 if (verbose < 0 || verbose >= QDF_TRACE_LEVEL_MAX) { 2062 pr_info("%s: Invalid verbose level %d\n", __func__, verbose); 2063 return QDF_STATUS_E_FAILURE; 2064 } 2065 2066 if (verbose == QDF_TRACE_LEVEL_ALL) { 2067 print_ctrl_obj[idx].cat_info[category].category_verbose_mask = 2068 0xFFFF; 2069 return QDF_STATUS_SUCCESS; 2070 } 2071 2072 if (verbose == QDF_TRACE_LEVEL_NONE) { 2073 print_ctrl_obj[idx].cat_info[category].category_verbose_mask = 2074 QDF_TRACE_LEVEL_NONE; 2075 return QDF_STATUS_SUCCESS; 2076 } 2077 2078 if (!is_set) { 2079 if (print_ctrl_obj[idx].cat_info[category].category_verbose_mask 2080 & QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) { 2081 print_ctrl_obj[idx].cat_info[category] 2082 .category_verbose_mask &= 2083 ~QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose); 2084 } 2085 } else { 2086 print_ctrl_obj[idx].cat_info[category].category_verbose_mask |= 2087 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose); 2088 } 2089 2090 pr_info("%s: Print control object %d, Category %d, Verbose level %d\n", 2091 __func__, 2092 idx, 2093 category, 2094 print_ctrl_obj[idx].cat_info[category].category_verbose_mask); 2095 2096 return QDF_STATUS_SUCCESS; 2097 } 2098 EXPORT_SYMBOL(qdf_print_set_category_verbose); 2099 2100 bool qdf_print_is_category_enabled(unsigned int idx, QDF_MODULE_ID category) 2101 { 2102 QDF_TRACE_LEVEL verbose_mask; 2103 2104 /* Check if index passed is valid */ 2105 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 2106 pr_info("%s: Invalid index - %d\n", __func__, idx); 2107 return false; 2108 } 2109 2110 /* Check if print control object is in use */ 2111 if (!print_ctrl_obj[idx].in_use) { 2112 pr_info("%s: Invalid print control object\n", __func__); 2113 return false; 2114 } 2115 2116 /* Check if category passed is valid */ 2117 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) { 2118 pr_info("%s: Invalid category: %d\n", __func__, category); 2119 return false; 2120 } 2121 2122 verbose_mask = 2123 print_ctrl_obj[idx].cat_info[category].category_verbose_mask; 2124 2125 if (verbose_mask == QDF_TRACE_LEVEL_NONE) 2126 return false; 2127 else 2128 return true; 2129 } 2130 EXPORT_SYMBOL(qdf_print_is_category_enabled); 2131 2132 bool qdf_print_is_verbose_enabled(unsigned int idx, QDF_MODULE_ID category, 2133 QDF_TRACE_LEVEL verbose) 2134 { 2135 bool verbose_enabled = false; 2136 2137 /* Check if index passed is valid */ 2138 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 2139 pr_info("%s: Invalid index - %d\n", __func__, idx); 2140 return verbose_enabled; 2141 } 2142 2143 /* Check if print control object is in use */ 2144 if (!print_ctrl_obj[idx].in_use) { 2145 pr_info("%s: Invalid print control object\n", __func__); 2146 return verbose_enabled; 2147 } 2148 2149 /* Check if category passed is valid */ 2150 if (category < 0 || category >= MAX_SUPPORTED_CATEGORY) { 2151 pr_info("%s: Invalid category: %d\n", __func__, category); 2152 return verbose_enabled; 2153 } 2154 2155 if ((verbose == QDF_TRACE_LEVEL_NONE) || 2156 (verbose >= QDF_TRACE_LEVEL_MAX)) { 2157 verbose_enabled = false; 2158 } else if (verbose == QDF_TRACE_LEVEL_ALL) { 2159 if (print_ctrl_obj[idx].cat_info[category] 2160 .category_verbose_mask == 0xFFFF) 2161 verbose_enabled = true; 2162 } else { 2163 verbose_enabled = 2164 (print_ctrl_obj[idx].cat_info[category].category_verbose_mask & 2165 QDF_TRACE_LEVEL_TO_MODULE_BITMASK(verbose)) ? true : false; 2166 } 2167 2168 return verbose_enabled; 2169 } 2170 EXPORT_SYMBOL(qdf_print_is_verbose_enabled); 2171 2172 #ifdef DBG_LVL_MAC_FILTERING 2173 2174 QDF_STATUS qdf_print_set_node_flag(unsigned int idx, uint8_t enable) 2175 { 2176 /* Check if index passed is valid */ 2177 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 2178 pr_info("%s: Invalid index - %d\n", __func__, idx); 2179 return QDF_STATUS_E_FAILURE; 2180 } 2181 2182 /* Check if print control object is in use */ 2183 if (!print_ctrl_obj[idx].in_use) { 2184 pr_info("%s: Invalid print control object\n", __func__); 2185 return QDF_STATUS_E_FAILURE; 2186 } 2187 2188 if (enable > 1) { 2189 pr_info("%s: Incorrect input: Use 1 or 0 to enable or disable\n", 2190 __func__); 2191 return QDF_STATUS_E_FAILURE; 2192 } 2193 2194 print_ctrl_obj[idx].dbglvlmac_on = enable; 2195 pr_info("%s: DbgLVLmac feature %s\n", 2196 __func__, 2197 ((enable) ? "enabled" : "disabled")); 2198 2199 return QDF_STATUS_SUCCESS; 2200 } 2201 EXPORT_SYMBOL(qdf_print_set_node_flag); 2202 2203 bool qdf_print_get_node_flag(unsigned int idx) 2204 { 2205 bool node_flag = false; 2206 2207 /* Check if index passed is valid */ 2208 if (idx < 0 || idx >= MAX_PRINT_CONFIG_SUPPORTED) { 2209 pr_info("%s: Invalid index - %d\n", __func__, idx); 2210 return node_flag; 2211 } 2212 2213 /* Check if print control object is in use */ 2214 if (!print_ctrl_obj[idx].in_use) { 2215 pr_info("%s: Invalid print control object\n", __func__); 2216 return node_flag; 2217 } 2218 2219 if (print_ctrl_obj[idx].dbglvlmac_on) 2220 node_flag = true; 2221 2222 return node_flag; 2223 } 2224 EXPORT_SYMBOL(qdf_print_get_node_flag); 2225 2226 void qdf_print_clean_node_flag(unsigned int idx) 2227 { 2228 /* Disable dbglvlmac_on during cleanup */ 2229 print_ctrl_obj[idx].dbglvlmac_on = 0; 2230 } 2231 2232 #else 2233 2234 void qdf_print_clean_node_flag(unsigned int idx) 2235 { 2236 /* No operation in case of no support for DBG_LVL_MAC_FILTERING */ 2237 return; 2238 } 2239 #endif 2240 2241 void QDF_PRINT_INFO(unsigned int idx, QDF_MODULE_ID module, 2242 QDF_TRACE_LEVEL level, 2243 char *str_format, ...) 2244 { 2245 va_list args; 2246 2247 /* Generic wrapper API will compile qdf_vprint in order to 2248 * log the message. Once QDF converged debug framework is in 2249 * place, this will be changed to adapt to the framework, compiling 2250 * call to converged tracing API 2251 */ 2252 va_start(args, str_format); 2253 qdf_vprint(str_format, args); 2254 va_end(args); 2255 } 2256 EXPORT_SYMBOL(QDF_PRINT_INFO); 2257 2258 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE 2259 void qdf_logging_init(void) 2260 { 2261 wlan_logging_sock_init_svc(); 2262 wlan_logging_sock_activate_svc(1, 10); 2263 nl_srv_init(NULL); 2264 } 2265 2266 void qdf_logging_exit(void) 2267 { 2268 nl_srv_exit(); 2269 wlan_logging_sock_deactivate_svc(); 2270 wlan_logging_sock_deinit_svc(); 2271 } 2272 #else 2273 void qdf_logging_init(void) 2274 { 2275 } 2276 2277 void qdf_logging_exit(void) 2278 { 2279 } 2280 #endif 2281 2282