1 /* 2 * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /****************************************************************************** 21 * wlan_logging_sock_svc.c 22 * 23 ******************************************************************************/ 24 25 #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE 26 #include <linux/vmalloc.h> 27 #include <wlan_logging_sock_svc.h> 28 #include <linux/kthread.h> 29 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)) 30 #include <linux/panic_notifier.h> 31 #endif 32 #include <qdf_time.h> 33 #include <qdf_trace.h> 34 #include <qdf_mc_timer.h> 35 #include <qdf_timer.h> 36 #include <qdf_lock.h> 37 #include <wlan_ptt_sock_svc.h> 38 #include <host_diag_core_event.h> 39 #include "host_diag_core_log.h" 40 #include <qdf_event.h> 41 #include <qdf_module.h> 42 #include <qdf_str.h> 43 #ifdef WLAN_FEATURE_CONNECTIVITY_LOGGING 44 #include <wlan_connectivity_logging.h> 45 #endif 46 47 #ifdef CNSS_GENL 48 #ifdef CONFIG_CNSS_OUT_OF_TREE 49 #include "cnss_nl.h" 50 #else 51 #include <net/cnss_nl.h> 52 #endif 53 #endif 54 55 #if defined(FEATURE_FW_LOG_PARSING) || defined(FEATURE_WLAN_DIAG_SUPPORT) || \ 56 defined(CONNECTIVITY_PKTLOG) 57 #include <cds_api.h> 58 #include "ani_global.h" 59 #endif 60 61 #ifdef CONNECTIVITY_PKTLOG 62 #include "wma.h" 63 #include "pktlog_ac.h" 64 #include <cdp_txrx_misc.h> 65 #endif 66 67 /* 68 * The following commit was introduced in v5.17: 69 * cead18552660 ("exit: Rename complete_and_exit to kthread_complete_and_exit") 70 * Use the old name for kernels before 5.17 71 */ 72 #if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0)) 73 #define kthread_complete_and_exit(c, s) complete_and_exit(c, s) 74 #endif 75 76 #define MAX_NUM_PKT_LOG 32 77 78 #define LOGGING_TRACE(level, args ...) \ 79 QDF_TRACE(QDF_MODULE_ID_HDD, level, ## args) 80 81 /* Global variables */ 82 83 #define ANI_NL_MSG_LOG_TYPE 89 84 #define ANI_NL_MSG_READY_IND_TYPE 90 85 #ifndef MAX_LOGMSG_COUNT 86 #define MAX_LOGMSG_COUNT 256 87 #endif 88 #define MAX_LOGMSG_LENGTH 2048 89 #define MAX_SKBMSG_LENGTH 4096 90 91 #define WLAN_LOG_BUFFER_SIZE 2048 92 #ifdef CONNECTIVITY_PKTLOG 93 /** 94 * Buffer to accommodate - 95 * pktlog buffer (2048 bytes) 96 * ath_pktlog_hdr (16 bytes) 97 * pkt_dump (8 bytes) 98 * extra padding (40 bytes) 99 * 100 * Note: pktlog buffer size is dependent on RX_BUFFER_SIZE and 101 * HTT_T2H_MAX_MSG_SIZE. Adjust WLAN_LOG_BUFFER_SIZE 102 * based on the above mentioned macros. 103 */ 104 #define ATH_PKTLOG_HDR_SIZE (sizeof(struct ath_pktlog_hdr)) 105 #define PKT_DUMP_HDR_SIZE (sizeof(struct packet_dump)) 106 #define EXTRA_PADDING 40 107 108 #define MAX_PKTSTATS_LENGTH \ 109 ((WLAN_LOG_BUFFER_SIZE) + (ATH_PKTLOG_HDR_SIZE) + \ 110 (PKT_DUMP_HDR_SIZE) + (EXTRA_PADDING)) 111 #else 112 #define MAX_PKTSTATS_LENGTH WLAN_LOG_BUFFER_SIZE 113 #endif /* CONNECTIVITY_PKTLOG */ 114 115 #define MAX_PKTSTATS_BUFF 16 116 #define HOST_LOG_DRIVER_MSG 0x001 117 #define HOST_LOG_PER_PKT_STATS 0x002 118 #define HOST_LOG_FW_FLUSH_COMPLETE 0x003 119 #define HOST_LOG_DRIVER_CONNECTIVITY_MSG 0x004 120 121 #define DIAG_TYPE_LOGS 1 122 #define PTT_MSG_DIAG_CMDS_TYPE 0x5050 123 #define MAX_LOG_LINE 500 124 125 /* default rate limit period - 2sec */ 126 #define PANIC_WIFILOG_PRINT_RATE_LIMIT_PERIOD (2*HZ) 127 /* default burst for rate limit */ 128 #define PANIC_WIFILOG_PRINT_RATE_LIMIT_BURST_DEFAULT 500 129 DEFINE_RATELIMIT_STATE(panic_wifilog_ratelimit, 130 PANIC_WIFILOG_PRINT_RATE_LIMIT_PERIOD, 131 PANIC_WIFILOG_PRINT_RATE_LIMIT_BURST_DEFAULT); 132 133 #define FLUSH_LOG_COMPLETION_TIMEOUT 3000 134 135 struct log_msg { 136 struct list_head node; 137 unsigned int radio; 138 unsigned int index; 139 /* indicates the current filled log length in logbuf */ 140 unsigned int filled_length; 141 /* 142 * Buf to hold the log msg 143 * tAniHdr + log 144 */ 145 char logbuf[MAX_LOGMSG_LENGTH]; 146 }; 147 148 /** 149 * struct packet_dump - This data structure contains the 150 * Tx/Rx packet stats 151 * @status: Status 152 * @type: Type 153 * @driver_ts: driver timestamp 154 * @fw_ts: fw timestamp 155 */ 156 struct packet_dump { 157 unsigned char status; 158 unsigned char type; 159 uint32_t driver_ts; 160 uint16_t fw_ts; 161 } __attribute__((__packed__)); 162 163 /** 164 * struct pkt_stats_msg - This data structure contains the 165 * pkt stats node for link list 166 * @node: LinkList node 167 * @node: Pointer to skb 168 */ 169 struct pkt_stats_msg { 170 struct list_head node; 171 struct sk_buff *skb; 172 }; 173 174 #define MAX_FLUSH_TIMER_PERIOD_VALUE 3600000 /* maximum of 1 hour (in ms) */ 175 struct wlan_logging { 176 /* Console log levels */ 177 uint32_t console_log_levels; 178 /* Number of buffers to be used for logging */ 179 uint32_t num_buf; 180 uint32_t buffer_length; 181 /* Lock to synchronize access to shared logging resource */ 182 spinlock_t spin_lock; 183 /* Holds the free node which can be used for filling logs */ 184 struct list_head free_list; 185 /* Holds the filled nodes which needs to be indicated to APP */ 186 struct list_head filled_list; 187 /* Holds nodes for console printing in case of kernel panic */ 188 struct list_head panic_list; 189 /* Wait queue for Logger thread */ 190 wait_queue_head_t wait_queue; 191 /* Logger thread */ 192 struct task_struct *thread; 193 /* Logging thread sets this variable on exit */ 194 struct completion shutdown_comp; 195 /* Indicates to logger thread to exit */ 196 bool exit; 197 /* Holds number of dropped logs */ 198 unsigned int drop_count; 199 /* current logbuf to which the log will be filled to */ 200 struct log_msg *pcur_node; 201 /* Event flag used for wakeup and post indication*/ 202 unsigned long eventFlag; 203 /* Indicates logger thread is activated */ 204 bool is_active; 205 /* Flush completion check */ 206 bool is_flush_complete; 207 /* parameters for pkt stats */ 208 struct list_head pkt_stat_free_list; 209 struct list_head pkt_stat_filled_list; 210 struct pkt_stats_msg *pkt_stats_pcur_node; 211 unsigned int pkt_stat_drop_cnt; 212 spinlock_t pkt_stats_lock; 213 unsigned int pkt_stats_msg_idx; 214 qdf_timer_t flush_timer; 215 bool is_flush_timer_initialized; 216 uint32_t flush_timer_period; 217 qdf_spinlock_t flush_timer_lock; 218 qdf_event_t flush_log_completion; 219 uint64_t wakup_ts; 220 uint64_t start_ts; 221 uint64_t reinitcompletion_ts; 222 uint64_t set_exit_ts; 223 uint64_t exit_ts; 224 }; 225 226 /* This global variable is intentionally not marked static because it 227 * is used by offline tools. Please do not use it outside this file. 228 */ 229 struct wlan_logging gwlan_logging; 230 static struct pkt_stats_msg *gpkt_stats_buffers; 231 232 #ifdef WLAN_LOGGING_BUFFERS_DYNAMICALLY 233 234 static struct log_msg *gplog_msg; 235 236 static inline QDF_STATUS allocate_log_msg_buffer(void) 237 { 238 gplog_msg = qdf_mem_valloc(MAX_LOGMSG_COUNT * sizeof(*gplog_msg)); 239 240 return gplog_msg ? QDF_STATUS_SUCCESS : QDF_STATUS_E_NOMEM; 241 } 242 243 static inline void free_log_msg_buffer(void) 244 { 245 qdf_mem_vfree(gplog_msg); 246 gplog_msg = NULL; 247 } 248 249 #else 250 static struct log_msg gplog_msg[MAX_LOGMSG_COUNT]; 251 252 static inline QDF_STATUS allocate_log_msg_buffer(void) 253 { 254 qdf_minidump_log(gplog_msg, sizeof(gplog_msg), "wlan_logs"); 255 return QDF_STATUS_SUCCESS; 256 } 257 258 static inline void free_log_msg_buffer(void) 259 { 260 qdf_minidump_remove(gplog_msg, sizeof(gplog_msg), "wlan_logs"); 261 } 262 #endif 263 264 /* Need to call this with spin_lock acquired */ 265 static int wlan_queue_logmsg_for_app(void) 266 { 267 char *ptr; 268 int ret = 0; 269 ptr = &gwlan_logging.pcur_node->logbuf[sizeof(tAniHdr)]; 270 ptr[gwlan_logging.pcur_node->filled_length] = '\0'; 271 272 *(unsigned short *)(gwlan_logging.pcur_node->logbuf) = 273 ANI_NL_MSG_LOG_TYPE; 274 *(unsigned short *)(gwlan_logging.pcur_node->logbuf + 2) = 275 gwlan_logging.pcur_node->filled_length; 276 list_add_tail(&gwlan_logging.pcur_node->node, 277 &gwlan_logging.filled_list); 278 279 if (!list_empty(&gwlan_logging.free_list)) { 280 /* Get buffer from free list */ 281 gwlan_logging.pcur_node = 282 (struct log_msg *)(gwlan_logging.free_list.next); 283 list_del_init(gwlan_logging.free_list.next); 284 } else if (!list_empty(&gwlan_logging.filled_list)) { 285 /* Get buffer from filled list */ 286 /* This condition will drop the packet from being 287 * indicated to app 288 */ 289 gwlan_logging.pcur_node = 290 (struct log_msg *)(gwlan_logging.filled_list.next); 291 ++gwlan_logging.drop_count; 292 list_del_init(gwlan_logging.filled_list.next); 293 ret = 1; 294 } 295 296 /* Reset the current node values */ 297 gwlan_logging.pcur_node->filled_length = 0; 298 return ret; 299 } 300 301 static const char *current_process_name(void) 302 { 303 if (in_irq()) 304 return "irq"; 305 306 if (in_softirq()) 307 return "soft_irq"; 308 309 return current->comm; 310 } 311 312 /** 313 * wlan_add_user_log_time_stamp() - populate firmware and kernel timestamps 314 * @tbuf: Pointer to time stamp buffer 315 * @tbuf_sz: Time buffer size 316 * @ts: Time stamp value 317 * 318 * For adrastea time stamp is QTIMER raw tick which will be used by cnss_diag 319 * to convert it into user visible time stamp. In adrstea FW also uses QTIMER 320 * raw ticks which is needed to synchronize host and fw log time stamps 321 * 322 * Also add logcat timestamp so that driver logs and 323 * logcat logs can be co-related 324 * 325 * For discrete solution e.g rome use system tick and convert it into 326 * seconds.milli seconds 327 * 328 * Return: number of characters written in target buffer not including 329 * trailing '/0' 330 */ 331 static int wlan_add_user_log_time_stamp(char *tbuf, size_t tbuf_sz, uint64_t ts) 332 { 333 char time_buf[20]; 334 335 qdf_get_time_of_the_day_in_hr_min_sec_usec(time_buf, sizeof(time_buf)); 336 337 return scnprintf(tbuf, tbuf_sz, "[%.6s][0x%llx]%s", 338 current_process_name(), (unsigned long long)ts, 339 time_buf); 340 } 341 342 #ifdef WLAN_MAX_LOGS_PER_SEC 343 static inline void wlan_panic_on_excessive_logging(void) 344 { 345 if (qdf_detected_excessive_logging()) 346 QDF_DEBUG_PANIC("Exceeded %d logs per second", 347 WLAN_MAX_LOGS_PER_SEC); 348 } 349 #else 350 static inline void wlan_panic_on_excessive_logging(void) {} 351 #endif /* WLAN_MAX_LOGS_PER_SEC */ 352 353 #ifdef QDF_TRACE_PRINT_ENABLE 354 static inline void 355 log_to_console(QDF_TRACE_LEVEL level, const char *timestamp, const char *msg) 356 { 357 if (qdf_detected_excessive_logging()) { 358 qdf_rl_print_suppressed_inc(); 359 return; 360 } 361 362 qdf_rl_print_suppressed_log(); 363 pr_err("%s %s\n", timestamp, msg); 364 } 365 #else 366 static inline void 367 log_to_console(QDF_TRACE_LEVEL level, const char *timestamp, const char *msg) 368 { 369 switch (level) { 370 case QDF_TRACE_LEVEL_FATAL: 371 pr_alert("%s %s\n", timestamp, msg); 372 wlan_panic_on_excessive_logging(); 373 break; 374 case QDF_TRACE_LEVEL_ERROR: 375 pr_err("%s %s\n", timestamp, msg); 376 wlan_panic_on_excessive_logging(); 377 break; 378 case QDF_TRACE_LEVEL_WARN: 379 pr_warn("%s %s\n", timestamp, msg); 380 wlan_panic_on_excessive_logging(); 381 break; 382 case QDF_TRACE_LEVEL_INFO: 383 pr_info("%s %s\n", timestamp, msg); 384 wlan_panic_on_excessive_logging(); 385 break; 386 case QDF_TRACE_LEVEL_INFO_HIGH: 387 case QDF_TRACE_LEVEL_INFO_MED: 388 case QDF_TRACE_LEVEL_INFO_LOW: 389 case QDF_TRACE_LEVEL_DEBUG: 390 default: 391 /* these levels should not be logged to console */ 392 break; 393 } 394 } 395 #endif 396 397 int wlan_log_to_user(QDF_TRACE_LEVEL log_level, char *to_be_sent, int length) 398 { 399 char *ptr; 400 char tbuf[60]; 401 int tlen; 402 int total_log_len; 403 unsigned int *pfilled_length; 404 bool wake_up_thread = false; 405 unsigned long flags; 406 uint64_t ts; 407 408 /* Add the current time stamp */ 409 ts = qdf_get_log_timestamp(); 410 tlen = wlan_add_user_log_time_stamp(tbuf, sizeof(tbuf), ts); 411 412 /* if logging isn't up yet, just dump to dmesg */ 413 if (!gwlan_logging.is_active) { 414 log_to_console(log_level, tbuf, to_be_sent); 415 return 0; 416 } 417 418 /* 1+1 indicate '\n'+'\0' */ 419 total_log_len = length + tlen + 1 + 1; 420 421 spin_lock_irqsave(&gwlan_logging.spin_lock, flags); 422 /* wlan logging svc resources are not yet initialized */ 423 if (!gwlan_logging.pcur_node) { 424 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 425 return -EIO; 426 } 427 428 pfilled_length = &gwlan_logging.pcur_node->filled_length; 429 430 /* Check if we can accommodate more log into current node/buffer */ 431 if ((MAX_LOGMSG_LENGTH - (*pfilled_length + 432 sizeof(tAniNlHdr))) < total_log_len) { 433 wake_up_thread = true; 434 wlan_queue_logmsg_for_app(); 435 pfilled_length = &gwlan_logging.pcur_node->filled_length; 436 } 437 438 ptr = &gwlan_logging.pcur_node->logbuf[sizeof(tAniHdr)]; 439 440 if (unlikely(MAX_LOGMSG_LENGTH < (sizeof(tAniNlHdr) + total_log_len))) { 441 /* 442 * Assumption here is that we receive logs which is less than 443 * MAX_LOGMSG_LENGTH, where we can accommodate the 444 * tAniNlHdr + [context][timestamp] + log 445 * If log length is over MAX_LOGMSG_LENGTH, 446 * the overflow part will be discarded. 447 */ 448 length = MAX_LOGMSG_LENGTH - sizeof(tAniNlHdr) - tlen - 2; 449 /* 450 * QDF_ASSERT if complete log was not accommodated into 451 * the available buffer. 452 */ 453 QDF_ASSERT(0); 454 } 455 456 memcpy(&ptr[*pfilled_length], tbuf, tlen); 457 memcpy(&ptr[*pfilled_length + tlen], to_be_sent, length); 458 *pfilled_length += tlen + length; 459 ptr[*pfilled_length] = '\n'; 460 *pfilled_length += 1; 461 462 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 463 464 /* Wakeup logger thread */ 465 if (wake_up_thread) { 466 set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); 467 wake_up_interruptible(&gwlan_logging.wait_queue); 468 } 469 470 if (gwlan_logging.console_log_levels & BIT(log_level)) 471 log_to_console(log_level, tbuf, to_be_sent); 472 473 return 0; 474 } 475 476 /** 477 * nl_srv_bcast_host_logs() - Wrapper to send bcast msgs to host logs mcast grp 478 * @skb: sk buffer pointer 479 * 480 * Sends the bcast message to host logs multicast group with generic nl socket 481 * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send. 482 * 483 * Return: zero on success, error code otherwise 484 */ 485 #ifdef CNSS_GENL 486 static int nl_srv_bcast_host_logs(struct sk_buff *skb) 487 { 488 return nl_srv_bcast(skb, CLD80211_MCGRP_HOST_LOGS, ANI_NL_MSG_LOG); 489 } 490 #else 491 static int nl_srv_bcast_host_logs(struct sk_buff *skb) 492 { 493 return nl_srv_bcast(skb); 494 } 495 #endif 496 497 #ifdef CONNECTIVITY_PKTLOG 498 /** 499 * pkt_stats_fill_headers() - This function adds headers to skb 500 * @skb: skb to which headers need to be added 501 * 502 * Return: 0 on success or Errno on failure 503 */ 504 static int pkt_stats_fill_headers(struct sk_buff *skb) 505 { 506 struct host_log_pktlog_info cds_pktlog; 507 int cds_pkt_size = sizeof(struct host_log_pktlog_info); 508 tAniNlHdr msg_header; 509 int extra_header_len, nl_payload_len; 510 static int nlmsg_seq; 511 int diag_type; 512 513 qdf_mem_zero(&cds_pktlog, cds_pkt_size); 514 cds_pktlog.version = VERSION_LOG_WLAN_PKT_LOG_INFO_C; 515 cds_pktlog.buf_len = skb->len; 516 cds_pktlog.seq_no = gwlan_logging.pkt_stats_msg_idx++; 517 host_diag_log_set_code(&cds_pktlog, LOG_WLAN_PKT_LOG_INFO_C); 518 host_diag_log_set_length(&cds_pktlog.log_hdr, skb->len + 519 cds_pkt_size); 520 521 if (unlikely(skb_headroom(skb) < cds_pkt_size)) { 522 qdf_nofl_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]", 523 __LINE__, skb->head, skb->data, 524 sizeof(msg_header)); 525 return -EIO; 526 } 527 528 qdf_mem_copy(skb_push(skb, cds_pkt_size), 529 &cds_pktlog, cds_pkt_size); 530 531 if (unlikely(skb_headroom(skb) < sizeof(int))) { 532 qdf_nofl_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]", 533 __LINE__, skb->head, skb->data, 534 sizeof(int)); 535 return -EIO; 536 } 537 538 diag_type = DIAG_TYPE_LOGS; 539 qdf_mem_copy(skb_push(skb, sizeof(int)), &diag_type, sizeof(int)); 540 541 extra_header_len = sizeof(msg_header.radio) + sizeof(tAniHdr) + 542 sizeof(struct nlmsghdr); 543 nl_payload_len = extra_header_len + skb->len; 544 545 msg_header.nlh.nlmsg_type = ANI_NL_MSG_PUMAC; 546 msg_header.nlh.nlmsg_len = nl_payload_len; 547 msg_header.nlh.nlmsg_flags = NLM_F_REQUEST; 548 msg_header.nlh.nlmsg_pid = 0; 549 msg_header.nlh.nlmsg_seq = nlmsg_seq++; 550 msg_header.radio = 0; 551 msg_header.wmsg.type = PTT_MSG_DIAG_CMDS_TYPE; 552 msg_header.wmsg.length = cpu_to_be16(skb->len); 553 554 if (unlikely(skb_headroom(skb) < sizeof(msg_header))) { 555 qdf_nofl_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]", 556 __LINE__, skb->head, skb->data, 557 sizeof(msg_header)); 558 return -EIO; 559 } 560 561 qdf_mem_copy(skb_push(skb, sizeof(msg_header)), &msg_header, 562 sizeof(msg_header)); 563 564 return 0; 565 } 566 567 /** 568 * nl_srv_bcast_diag() - Wrapper to send bcast msgs to diag events mcast grp 569 * @skb: sk buffer pointer 570 * 571 * Sends the bcast message to diag events multicast group with generic nl socket 572 * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send. 573 * 574 * Return: zero on success, error code otherwise 575 */ 576 static int nl_srv_bcast_diag(struct sk_buff *skb) 577 { 578 #ifdef CNSS_GENL 579 return nl_srv_bcast(skb, CLD80211_MCGRP_DIAG_EVENTS, ANI_NL_MSG_PUMAC); 580 #else 581 return nl_srv_bcast(skb); 582 #endif 583 } 584 585 /** 586 * pktlog_send_per_pkt_stats_to_user() - This function is used to send the per 587 * packet statistics to the user 588 * 589 * This function is used to send the per packet statistics to the user 590 * 591 * Return: Success if the message is posted to user 592 */ 593 static int pktlog_send_per_pkt_stats_to_user(void) 594 { 595 int ret = -1; 596 struct pkt_stats_msg *pstats_msg; 597 unsigned long flags; 598 struct sk_buff *skb_new = NULL; 599 static int rate_limit; 600 bool free_old_skb = false; 601 602 while (!list_empty(&gwlan_logging.pkt_stat_filled_list) 603 && !gwlan_logging.exit) { 604 skb_new = dev_alloc_skb(MAX_SKBMSG_LENGTH); 605 if (!skb_new) { 606 if (!rate_limit) { 607 qdf_err("dev_alloc_skb() failed for msg size[%d] drop count = %u", 608 MAX_SKBMSG_LENGTH, 609 gwlan_logging.drop_count); 610 } 611 rate_limit = 1; 612 ret = -ENOMEM; 613 break; 614 } 615 616 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags); 617 618 pstats_msg = (struct pkt_stats_msg *) 619 (gwlan_logging.pkt_stat_filled_list.next); 620 list_del_init(gwlan_logging.pkt_stat_filled_list.next); 621 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags); 622 623 ret = pkt_stats_fill_headers(pstats_msg->skb); 624 if (ret < 0) { 625 qdf_err("Failed to fill headers %d", ret); 626 free_old_skb = true; 627 goto err; 628 } 629 ret = nl_srv_bcast_diag(pstats_msg->skb); 630 if (ret < 0) { 631 qdf_info("Send Failed %d drop_count = %u", ret, 632 ++gwlan_logging.pkt_stat_drop_cnt); 633 } else { 634 ret = 0; 635 } 636 err: 637 /* 638 * Free old skb in case or error before assigning new skb 639 * to the free list. 640 */ 641 if (free_old_skb) 642 dev_kfree_skb(pstats_msg->skb); 643 644 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags); 645 pstats_msg->skb = skb_new; 646 list_add_tail(&pstats_msg->node, 647 &gwlan_logging.pkt_stat_free_list); 648 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags); 649 ret = 0; 650 } 651 652 return ret; 653 654 } 655 #else 656 static inline 657 int pktlog_send_per_pkt_stats_to_user(void) 658 { 659 return 0; 660 } 661 #endif 662 663 static int send_filled_buffers_to_user(void) 664 { 665 int ret = -1; 666 struct log_msg *plog_msg; 667 int payload_len; 668 int tot_msg_len; 669 tAniNlHdr *wnl; 670 struct sk_buff *skb = NULL; 671 struct nlmsghdr *nlh; 672 static int nlmsg_seq; 673 unsigned long flags; 674 static int rate_limit; 675 676 while (!list_empty(&gwlan_logging.filled_list) 677 && !gwlan_logging.exit) { 678 679 skb = dev_alloc_skb(MAX_LOGMSG_LENGTH); 680 if (!skb) { 681 if (!rate_limit) { 682 qdf_err("dev_alloc_skb() failed for msg size[%d] drop count = %u", 683 MAX_LOGMSG_LENGTH, 684 gwlan_logging.drop_count); 685 } 686 rate_limit = 1; 687 ret = -ENOMEM; 688 break; 689 } 690 rate_limit = 0; 691 692 spin_lock_irqsave(&gwlan_logging.spin_lock, flags); 693 694 plog_msg = (struct log_msg *) 695 (gwlan_logging.filled_list.next); 696 list_del_init(gwlan_logging.filled_list.next); 697 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 698 /* 4 extra bytes for the radio idx */ 699 payload_len = plog_msg->filled_length + 700 sizeof(wnl->radio) + sizeof(tAniHdr); 701 702 tot_msg_len = NLMSG_SPACE(payload_len); 703 nlh = nlmsg_put(skb, 0, nlmsg_seq++, 704 ANI_NL_MSG_LOG, payload_len, NLM_F_REQUEST); 705 if (!nlh) { 706 spin_lock_irqsave(&gwlan_logging.spin_lock, flags); 707 list_add_tail(&plog_msg->node, 708 &gwlan_logging.free_list); 709 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 710 qdf_err("drop_count = %u", ++gwlan_logging.drop_count); 711 qdf_err("nlmsg_put() failed for msg size[%d]", 712 tot_msg_len); 713 dev_kfree_skb(skb); 714 skb = NULL; 715 ret = -EINVAL; 716 continue; 717 } 718 719 wnl = (tAniNlHdr *) nlh; 720 wnl->radio = plog_msg->radio; 721 memcpy(&wnl->wmsg, plog_msg->logbuf, 722 plog_msg->filled_length + sizeof(tAniHdr)); 723 724 spin_lock_irqsave(&gwlan_logging.spin_lock, flags); 725 list_add_tail(&plog_msg->node, &gwlan_logging.free_list); 726 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 727 728 ret = nl_srv_bcast_host_logs(skb); 729 /* print every 64th drop count */ 730 if (ret < 0 && (!(gwlan_logging.drop_count % 0x40))) { 731 qdf_err("Send Failed %d drop_count = %u", 732 ret, ++gwlan_logging.drop_count); 733 } 734 } 735 736 return ret; 737 } 738 739 #ifdef FEATURE_WLAN_DIAG_SUPPORT 740 /** 741 * wlan_report_log_completion() - Report bug report completion to userspace 742 * @is_fatal: Type of event, fatal or not 743 * @indicator: Source of bug report, framework/host/firmware 744 * @reason_code: Reason for triggering bug report 745 * @ring_id: Ring id of logging entities 746 * 747 * This function is used to report the bug report completion to userspace 748 * 749 * Return: None 750 */ 751 void wlan_report_log_completion(uint32_t is_fatal, 752 uint32_t indicator, 753 uint32_t reason_code, 754 uint8_t ring_id) 755 { 756 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, 757 struct host_event_wlan_log_complete); 758 759 wlan_diag_event.is_fatal = is_fatal; 760 wlan_diag_event.indicator = indicator; 761 wlan_diag_event.reason_code = reason_code; 762 wlan_diag_event.reserved = ring_id; 763 764 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_LOG_COMPLETE); 765 } 766 #endif 767 768 #ifdef FEATURE_WLAN_DIAG_SUPPORT 769 /** 770 * send_flush_completion_to_user() - Indicate flush completion to the user 771 * @ring_id: Ring id of logging entities 772 * 773 * This function is used to send the flush completion message to user space 774 * 775 * Return: None 776 */ 777 static void send_flush_completion_to_user(uint8_t ring_id) 778 { 779 uint32_t is_fatal, indicator, reason_code; 780 bool recovery_needed; 781 782 cds_get_and_reset_log_completion(&is_fatal, 783 &indicator, &reason_code, &recovery_needed); 784 785 /* Error on purpose, so that it will get logged in the kmsg */ 786 LOGGING_TRACE(QDF_TRACE_LEVEL_DEBUG, 787 "%s: Sending flush done to userspace reason code %d", 788 __func__, reason_code); 789 790 wlan_report_log_completion(is_fatal, indicator, reason_code, ring_id); 791 792 if (recovery_needed) 793 cds_trigger_recovery(QDF_REASON_UNSPECIFIED); 794 } 795 #endif 796 797 static void wlan_logging_set_flush_log_completion(void) 798 { 799 qdf_event_set(&gwlan_logging.flush_log_completion); 800 } 801 802 QDF_STATUS wlan_logging_wait_for_flush_log_completion(void) 803 { 804 qdf_event_reset(&gwlan_logging.flush_log_completion); 805 806 return qdf_wait_for_event_completion( 807 &gwlan_logging.flush_log_completion, 808 FLUSH_LOG_COMPLETION_TIMEOUT); 809 } 810 811 static void setup_flush_timer(void) 812 { 813 qdf_spin_lock(&gwlan_logging.flush_timer_lock); 814 if (!gwlan_logging.is_flush_timer_initialized || 815 (gwlan_logging.flush_timer_period == 0)) { 816 qdf_spin_unlock(&gwlan_logging.flush_timer_lock); 817 return; 818 } 819 qdf_timer_mod(&gwlan_logging.flush_timer, 820 gwlan_logging.flush_timer_period); 821 qdf_spin_unlock(&gwlan_logging.flush_timer_lock); 822 } 823 824 #ifdef WLAN_FEATURE_CONNECTIVITY_LOGGING 825 static QDF_STATUS 826 wlan_logging_send_connectivity_event(void) 827 { 828 return wlan_connectivity_log_dequeue(); 829 } 830 #else 831 static inline QDF_STATUS 832 wlan_logging_send_connectivity_event(void) 833 { 834 return QDF_STATUS_E_NOSUPPORT; 835 } 836 #endif 837 838 /** 839 * wlan_logging_thread() - The WLAN Logger thread 840 * @Arg - pointer to the HDD context 841 * 842 * This thread logs log message to App registered for the logs. 843 */ 844 static int wlan_logging_thread(void *Arg) 845 { 846 int ret_wait_status = 0; 847 int ret = 0; 848 unsigned long flags; 849 850 gwlan_logging.start_ts = qdf_get_log_timestamp(); 851 852 while (!gwlan_logging.exit) { 853 setup_flush_timer(); 854 ret_wait_status = 855 wait_event_interruptible(gwlan_logging.wait_queue, 856 (!list_empty 857 (&gwlan_logging.filled_list) 858 || test_bit( 859 HOST_LOG_DRIVER_MSG, 860 &gwlan_logging.eventFlag) 861 || test_bit( 862 HOST_LOG_PER_PKT_STATS, 863 &gwlan_logging.eventFlag) 864 || test_bit( 865 HOST_LOG_FW_FLUSH_COMPLETE, 866 &gwlan_logging.eventFlag) 867 || test_bit( 868 HOST_LOG_DRIVER_CONNECTIVITY_MSG, 869 &gwlan_logging.eventFlag) 870 || gwlan_logging.exit)); 871 872 if (ret_wait_status == -ERESTARTSYS) { 873 qdf_err("wait_event_interruptible returned -ERESTARTSYS"); 874 break; 875 } 876 877 if (gwlan_logging.exit) 878 break; 879 880 881 if (test_and_clear_bit(HOST_LOG_DRIVER_MSG, 882 &gwlan_logging.eventFlag)) { 883 ret = send_filled_buffers_to_user(); 884 if (-ENOMEM == ret) 885 msleep(200); 886 #ifdef FEATURE_WLAN_DIAG_SUPPORT 887 if (WLAN_LOG_INDICATOR_HOST_ONLY == 888 cds_get_log_indicator()) { 889 send_flush_completion_to_user( 890 RING_ID_DRIVER_DEBUG); 891 } 892 #endif 893 } 894 895 if (test_and_clear_bit(HOST_LOG_PER_PKT_STATS, 896 &gwlan_logging.eventFlag)) { 897 ret = pktlog_send_per_pkt_stats_to_user(); 898 if (-ENOMEM == ret) 899 msleep(200); 900 } 901 902 if (test_and_clear_bit(HOST_LOG_FW_FLUSH_COMPLETE, 903 &gwlan_logging.eventFlag)) { 904 /* Flush bit could have been set while we were mid 905 * way in the logging thread. So, need to check other 906 * buffers like log messages, per packet stats again 907 * to flush any residual data in them 908 */ 909 if (gwlan_logging.is_flush_complete == true) { 910 gwlan_logging.is_flush_complete = false; 911 #ifdef FEATURE_WLAN_DIAG_SUPPORT 912 send_flush_completion_to_user( 913 RING_ID_DRIVER_DEBUG); 914 #endif 915 wlan_logging_set_flush_log_completion(); 916 } else { 917 gwlan_logging.is_flush_complete = true; 918 /* Flush all current host logs*/ 919 spin_lock_irqsave(&gwlan_logging.spin_lock, 920 flags); 921 wlan_queue_logmsg_for_app(); 922 spin_unlock_irqrestore(&gwlan_logging.spin_lock, 923 flags); 924 set_bit(HOST_LOG_DRIVER_MSG, 925 &gwlan_logging.eventFlag); 926 set_bit(HOST_LOG_PER_PKT_STATS, 927 &gwlan_logging.eventFlag); 928 set_bit(HOST_LOG_FW_FLUSH_COMPLETE, 929 &gwlan_logging.eventFlag); 930 wake_up_interruptible( 931 &gwlan_logging.wait_queue); 932 } 933 } 934 935 /* Dequeue the connectivity_log */ 936 wlan_logging_send_connectivity_event(); 937 clear_bit(HOST_LOG_DRIVER_CONNECTIVITY_MSG, 938 &gwlan_logging.eventFlag); 939 } 940 941 gwlan_logging.exit_ts = qdf_get_log_timestamp(); 942 kthread_complete_and_exit(&gwlan_logging.shutdown_comp, 0); 943 944 return 0; 945 } 946 947 void wlan_logging_set_active(bool active) 948 { 949 gwlan_logging.is_active = active; 950 } 951 952 void wlan_set_console_log_levels(uint32_t console_log_levels) 953 { 954 gwlan_logging.console_log_levels = console_log_levels; 955 } 956 957 qdf_export_symbol(wlan_set_console_log_levels); 958 959 static void flush_log_buffers_timer(void *dummy) 960 { 961 wlan_flush_host_logs_for_fatal(); 962 } 963 964 int wlan_logging_set_flush_timer(uint32_t milliseconds) 965 { 966 if (milliseconds > MAX_FLUSH_TIMER_PERIOD_VALUE) { 967 QDF_TRACE_ERROR(QDF_MODULE_ID_QDF, 968 "ERROR! value should be (0 - %d)\n", 969 MAX_FLUSH_TIMER_PERIOD_VALUE); 970 return -EINVAL; 971 } 972 if (!gwlan_logging.is_active) { 973 QDF_TRACE_ERROR(QDF_MODULE_ID_QDF, 974 "WLAN-Logging not active"); 975 return -EINVAL; 976 } 977 qdf_spin_lock(&gwlan_logging.flush_timer_lock); 978 if (!gwlan_logging.is_flush_timer_initialized) { 979 qdf_spin_unlock(&gwlan_logging.flush_timer_lock); 980 return -EINVAL; 981 } 982 gwlan_logging.flush_timer_period = milliseconds; 983 if (milliseconds) { 984 qdf_timer_mod(&gwlan_logging.flush_timer, 985 gwlan_logging.flush_timer_period); 986 } 987 qdf_spin_unlock(&gwlan_logging.flush_timer_lock); 988 return 0; 989 } 990 991 static int panic_wifilog_ratelimit_print(void) 992 { 993 return __ratelimit(&panic_wifilog_ratelimit); 994 } 995 996 /** 997 * wlan_logging_dump_last_logs() - Panic notifier callback's helper function 998 * 999 * This function prints buffered logs one line at a time. 1000 */ 1001 static void wlan_logging_dump_last_logs(void) 1002 { 1003 char *log; 1004 struct log_msg *plog_msg; 1005 char textbuf[MAX_LOG_LINE]; 1006 unsigned int filled_length; 1007 unsigned int text_len; 1008 unsigned long flags; 1009 1010 /* Iterate over panic list */ 1011 pr_err("\n"); 1012 while (!list_empty(&gwlan_logging.panic_list)) { 1013 plog_msg = (struct log_msg *) 1014 (gwlan_logging.panic_list.next); 1015 list_del_init(gwlan_logging.panic_list.next); 1016 log = &plog_msg->logbuf[sizeof(tAniHdr)]; 1017 filled_length = plog_msg->filled_length; 1018 while (filled_length) { 1019 text_len = qdf_str_copy_all_before_char(log, filled_length, 1020 textbuf, 1021 sizeof(textbuf) - 1, 1022 '\n'); 1023 textbuf[text_len] = '\0'; 1024 if (panic_wifilog_ratelimit_print()) 1025 pr_err("%s\n", textbuf); 1026 1027 if (log[text_len] == '\n') 1028 text_len += 1; /* skip newline */ 1029 log += text_len; 1030 filled_length -= text_len; 1031 } 1032 spin_lock_irqsave(&gwlan_logging.spin_lock, flags); 1033 list_add_tail(&plog_msg->node, 1034 &gwlan_logging.free_list); 1035 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 1036 } 1037 } 1038 1039 /** 1040 * wlan_logging_panic_handler() - Panic notifier callback 1041 * 1042 * This function extracts log buffers in filled list and 1043 * current node.Sends them to helper function for printing. 1044 */ 1045 static int wlan_logging_panic_handler(struct notifier_block *this, 1046 unsigned long event, void *ptr) 1047 { 1048 char *log; 1049 struct log_msg *plog_msg; 1050 unsigned long flags; 1051 1052 spin_lock_irqsave(&gwlan_logging.spin_lock, flags); 1053 /* Iterate over nodes queued for app */ 1054 while (!list_empty(&gwlan_logging.filled_list)) { 1055 plog_msg = (struct log_msg *) 1056 (gwlan_logging.filled_list.next); 1057 list_del_init(gwlan_logging.filled_list.next); 1058 list_add_tail(&plog_msg->node, 1059 &gwlan_logging.panic_list); 1060 } 1061 /* Check current node */ 1062 if (gwlan_logging.pcur_node && 1063 gwlan_logging.pcur_node->filled_length) { 1064 plog_msg = gwlan_logging.pcur_node; 1065 log = &plog_msg->logbuf[sizeof(tAniHdr)]; 1066 log[plog_msg->filled_length] = '\0'; 1067 list_add_tail(&gwlan_logging.pcur_node->node, 1068 &gwlan_logging.panic_list); 1069 if (!list_empty(&gwlan_logging.free_list)) { 1070 gwlan_logging.pcur_node = 1071 (struct log_msg *)(gwlan_logging.free_list.next); 1072 list_del_init(gwlan_logging.free_list.next); 1073 gwlan_logging.pcur_node->filled_length = 0; 1074 } else 1075 gwlan_logging.pcur_node = NULL; 1076 } 1077 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 1078 1079 wlan_logging_dump_last_logs(); 1080 1081 return NOTIFY_DONE; 1082 } 1083 1084 static struct notifier_block panic_nb = { 1085 .notifier_call = wlan_logging_panic_handler, 1086 }; 1087 1088 int wlan_logging_notifier_init(bool dump_at_kernel_enable) 1089 { 1090 int ret; 1091 1092 if (gwlan_logging.is_active && 1093 !dump_at_kernel_enable) { 1094 ret = atomic_notifier_chain_register(&panic_notifier_list, 1095 &panic_nb); 1096 if (ret) { 1097 QDF_TRACE_ERROR(QDF_MODULE_ID_QDF, 1098 "Failed to register panic notifier"); 1099 return -EINVAL; 1100 } 1101 } 1102 1103 return 0; 1104 } 1105 1106 int wlan_logging_notifier_deinit(bool dump_at_kernel_enable) 1107 { 1108 if (gwlan_logging.is_active && 1109 !dump_at_kernel_enable) { 1110 atomic_notifier_chain_unregister(&panic_notifier_list, 1111 &panic_nb); 1112 } 1113 1114 return 0; 1115 } 1116 1117 static void flush_timer_init(void) 1118 { 1119 qdf_spinlock_create(&gwlan_logging.flush_timer_lock); 1120 qdf_timer_init(NULL, &gwlan_logging.flush_timer, 1121 flush_log_buffers_timer, NULL, 1122 QDF_TIMER_TYPE_SW); 1123 gwlan_logging.is_flush_timer_initialized = true; 1124 gwlan_logging.flush_timer_period = 0; 1125 } 1126 1127 static void flush_timer_deinit(void) 1128 { 1129 gwlan_logging.is_flush_timer_initialized = false; 1130 qdf_spin_lock(&gwlan_logging.flush_timer_lock); 1131 qdf_timer_stop(&gwlan_logging.flush_timer); 1132 qdf_timer_free(&gwlan_logging.flush_timer); 1133 qdf_spin_unlock(&gwlan_logging.flush_timer_lock); 1134 qdf_spinlock_destroy(&gwlan_logging.flush_timer_lock); 1135 } 1136 1137 int wlan_logging_sock_init_svc(void) 1138 { 1139 int i = 0, j, pkt_stats_size; 1140 unsigned long irq_flag; 1141 QDF_STATUS status; 1142 1143 spin_lock_init(&gwlan_logging.spin_lock); 1144 spin_lock_init(&gwlan_logging.pkt_stats_lock); 1145 1146 gwlan_logging.console_log_levels = 0; 1147 gwlan_logging.num_buf = MAX_LOGMSG_COUNT; 1148 gwlan_logging.buffer_length = MAX_LOGMSG_LENGTH; 1149 1150 if (allocate_log_msg_buffer() != QDF_STATUS_SUCCESS) { 1151 qdf_err("Could not allocate memory for log_msg"); 1152 return -ENOMEM; 1153 } 1154 1155 spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag); 1156 INIT_LIST_HEAD(&gwlan_logging.free_list); 1157 INIT_LIST_HEAD(&gwlan_logging.filled_list); 1158 INIT_LIST_HEAD(&gwlan_logging.panic_list); 1159 1160 for (i = 0; i < gwlan_logging.num_buf; i++) { 1161 list_add(&gplog_msg[i].node, &gwlan_logging.free_list); 1162 gplog_msg[i].index = i; 1163 } 1164 gwlan_logging.pcur_node = (struct log_msg *) 1165 (gwlan_logging.free_list.next); 1166 list_del_init(gwlan_logging.free_list.next); 1167 spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag); 1168 1169 flush_timer_init(); 1170 1171 /* Initialize the pktStats data structure here */ 1172 pkt_stats_size = sizeof(struct pkt_stats_msg); 1173 gpkt_stats_buffers = qdf_mem_valloc(MAX_PKTSTATS_BUFF * pkt_stats_size); 1174 if (!gpkt_stats_buffers) { 1175 qdf_err("Could not allocate memory for Pkt stats"); 1176 goto err1; 1177 } 1178 qdf_mem_zero(gpkt_stats_buffers, 1179 MAX_PKTSTATS_BUFF * pkt_stats_size); 1180 1181 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag); 1182 gwlan_logging.pkt_stats_msg_idx = 0; 1183 INIT_LIST_HEAD(&gwlan_logging.pkt_stat_free_list); 1184 INIT_LIST_HEAD(&gwlan_logging.pkt_stat_filled_list); 1185 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag); 1186 1187 1188 for (i = 0; i < MAX_PKTSTATS_BUFF; i++) { 1189 gpkt_stats_buffers[i].skb = dev_alloc_skb(MAX_PKTSTATS_LENGTH); 1190 if (!gpkt_stats_buffers[i].skb) { 1191 qdf_err("Memory alloc failed for skb"); 1192 /* free previously allocated skb and return */ 1193 for (j = 0; j < i ; j++) 1194 dev_kfree_skb(gpkt_stats_buffers[j].skb); 1195 goto err2; 1196 } 1197 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag); 1198 list_add(&gpkt_stats_buffers[i].node, 1199 &gwlan_logging.pkt_stat_free_list); 1200 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag); 1201 } 1202 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag); 1203 gwlan_logging.pkt_stats_pcur_node = (struct pkt_stats_msg *) 1204 (gwlan_logging.pkt_stat_free_list.next); 1205 list_del_init(gwlan_logging.pkt_stat_free_list.next); 1206 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag); 1207 /* Pkt Stats initialization done */ 1208 1209 init_waitqueue_head(&gwlan_logging.wait_queue); 1210 gwlan_logging.exit = false; 1211 clear_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); 1212 clear_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag); 1213 clear_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag); 1214 clear_bit(HOST_LOG_DRIVER_CONNECTIVITY_MSG, &gwlan_logging.eventFlag); 1215 init_completion(&gwlan_logging.shutdown_comp); 1216 gwlan_logging.thread = kthread_create(wlan_logging_thread, NULL, 1217 "wlan_logging_thread"); 1218 if (IS_ERR(gwlan_logging.thread)) { 1219 qdf_err("Could not Create LogMsg Thread Controller"); 1220 goto err3; 1221 } 1222 wake_up_process(gwlan_logging.thread); 1223 gwlan_logging.wakup_ts = qdf_get_log_timestamp(); 1224 1225 gwlan_logging.is_active = true; 1226 gwlan_logging.is_flush_complete = false; 1227 1228 status = qdf_event_create(&gwlan_logging.flush_log_completion); 1229 if (!QDF_IS_STATUS_SUCCESS(status)) { 1230 qdf_err("Flush log completion event init failed"); 1231 goto err3; 1232 } 1233 1234 return 0; 1235 1236 err3: 1237 for (i = 0; i < MAX_PKTSTATS_BUFF; i++) { 1238 if (gpkt_stats_buffers[i].skb) 1239 dev_kfree_skb(gpkt_stats_buffers[i].skb); 1240 } 1241 err2: 1242 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag); 1243 gwlan_logging.pkt_stats_pcur_node = NULL; 1244 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag); 1245 qdf_mem_vfree(gpkt_stats_buffers); 1246 gpkt_stats_buffers = NULL; 1247 err1: 1248 flush_timer_deinit(); 1249 spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag); 1250 gwlan_logging.pcur_node = NULL; 1251 spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag); 1252 free_log_msg_buffer(); 1253 1254 return -ENOMEM; 1255 } 1256 1257 int wlan_logging_sock_deinit_svc(void) 1258 { 1259 unsigned long irq_flag; 1260 int i; 1261 1262 if (!gwlan_logging.pcur_node) 1263 return 0; 1264 1265 qdf_event_destroy(&gwlan_logging.flush_log_completion); 1266 1267 gwlan_logging.reinitcompletion_ts = qdf_get_log_timestamp(); 1268 INIT_COMPLETION(gwlan_logging.shutdown_comp); 1269 qdf_wmb(); 1270 gwlan_logging.exit = true; 1271 qdf_wmb(); 1272 gwlan_logging.set_exit_ts = qdf_get_log_timestamp(); 1273 1274 gwlan_logging.is_active = false; 1275 #if defined(FEATURE_FW_LOG_PARSING) || defined(FEATURE_WLAN_DIAG_SUPPORT) 1276 cds_set_multicast_logging(0); 1277 #endif 1278 gwlan_logging.is_flush_complete = false; 1279 clear_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); 1280 clear_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag); 1281 clear_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag); 1282 clear_bit(HOST_LOG_DRIVER_CONNECTIVITY_MSG, &gwlan_logging.eventFlag); 1283 wake_up_interruptible(&gwlan_logging.wait_queue); 1284 wait_for_completion(&gwlan_logging.shutdown_comp); 1285 1286 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag); 1287 gwlan_logging.pkt_stats_pcur_node = NULL; 1288 gwlan_logging.pkt_stats_msg_idx = 0; 1289 gwlan_logging.pkt_stat_drop_cnt = 0; 1290 for (i = 0; i < MAX_PKTSTATS_BUFF; i++) { 1291 if (gpkt_stats_buffers[i].skb) 1292 dev_kfree_skb(gpkt_stats_buffers[i].skb); 1293 } 1294 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag); 1295 qdf_mem_vfree(gpkt_stats_buffers); 1296 gpkt_stats_buffers = NULL; 1297 1298 /* Delete the Flush timer then mark pcur_node NULL */ 1299 flush_timer_deinit(); 1300 1301 spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag); 1302 gwlan_logging.pcur_node = NULL; 1303 spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag); 1304 1305 free_log_msg_buffer(); 1306 1307 return 0; 1308 } 1309 1310 /** 1311 * wlan_logging_set_per_pkt_stats() - This function triggers per packet logging 1312 * 1313 * This function is used to send signal to the logger thread for logging per 1314 * packet stats 1315 * 1316 * Return: None 1317 * 1318 */ 1319 void wlan_logging_set_per_pkt_stats(void) 1320 { 1321 if (gwlan_logging.is_active == false) 1322 return; 1323 1324 set_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag); 1325 wake_up_interruptible(&gwlan_logging.wait_queue); 1326 } 1327 1328 void wlan_logging_set_connectivity_log(void) 1329 { 1330 if (gwlan_logging.is_active == false) 1331 return; 1332 1333 set_bit(HOST_LOG_DRIVER_CONNECTIVITY_MSG, &gwlan_logging.eventFlag); 1334 wake_up_interruptible(&gwlan_logging.wait_queue); 1335 } 1336 1337 /* 1338 * wlan_logging_set_fw_flush_complete() - FW log flush completion 1339 * 1340 * This function is used to send signal to the logger thread to indicate 1341 * that the flushing of FW logs is complete by the FW 1342 * 1343 * Return: None 1344 * 1345 */ 1346 void wlan_logging_set_fw_flush_complete(void) 1347 { 1348 if (!gwlan_logging.is_active) 1349 return; 1350 1351 set_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag); 1352 wake_up_interruptible(&gwlan_logging.wait_queue); 1353 } 1354 1355 /** 1356 * wlan_flush_host_logs_for_fatal() - Flush host logs 1357 * 1358 * This function is used to send signal to the logger thread to 1359 * Flush the host logs 1360 * 1361 * Return: None 1362 */ 1363 void wlan_flush_host_logs_for_fatal(void) 1364 { 1365 unsigned long flags; 1366 1367 if (gwlan_logging.flush_timer_period == 0) 1368 qdf_info("Flush all host logs Setting HOST_LOG_POST_MAS"); 1369 spin_lock_irqsave(&gwlan_logging.spin_lock, flags); 1370 wlan_queue_logmsg_for_app(); 1371 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 1372 set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); 1373 wake_up_interruptible(&gwlan_logging.wait_queue); 1374 } 1375 1376 #ifdef CONNECTIVITY_PKTLOG 1377 1378 static uint8_t gtx_count; 1379 static uint8_t grx_count; 1380 1381 /** 1382 * wlan_get_pkt_stats_free_node() - Get the free node for pkt stats 1383 * 1384 * This function is used to get the free node for pkt stats from 1385 * free list/filled list 1386 * 1387 * Return: int 1388 * 1389 */ 1390 static int wlan_get_pkt_stats_free_node(void) 1391 { 1392 int ret = 0; 1393 1394 list_add_tail(&gwlan_logging.pkt_stats_pcur_node->node, 1395 &gwlan_logging.pkt_stat_filled_list); 1396 1397 if (!list_empty(&gwlan_logging.pkt_stat_free_list)) { 1398 /* Get buffer from free list */ 1399 gwlan_logging.pkt_stats_pcur_node = 1400 (struct pkt_stats_msg *)(gwlan_logging.pkt_stat_free_list.next); 1401 list_del_init(gwlan_logging.pkt_stat_free_list.next); 1402 } else if (!list_empty(&gwlan_logging.pkt_stat_filled_list)) { 1403 /* Get buffer from filled list. This condition will drop the 1404 * packet from being indicated to app 1405 */ 1406 gwlan_logging.pkt_stats_pcur_node = 1407 (struct pkt_stats_msg *) 1408 (gwlan_logging.pkt_stat_filled_list.next); 1409 ++gwlan_logging.pkt_stat_drop_cnt; 1410 /* print every 64th drop count */ 1411 if ( 1412 cds_is_multicast_logging() && 1413 (!(gwlan_logging.pkt_stat_drop_cnt % 0x40))) { 1414 qdf_err("drop_count = %u", 1415 gwlan_logging.pkt_stat_drop_cnt); 1416 } 1417 list_del_init(gwlan_logging.pkt_stat_filled_list.next); 1418 ret = 1; 1419 } 1420 1421 /* Reset the skb values, essential if dequeued from filled list */ 1422 skb_trim(gwlan_logging.pkt_stats_pcur_node->skb, 0); 1423 return ret; 1424 } 1425 1426 /** 1427 * wlan_pkt_stats_to_logger_thread() - Add the pkt stats to SKB 1428 * @pl_hdr: Pointer to pl_hdr 1429 * @pkt_dump: Pointer to pkt_dump 1430 * @data: Pointer to data 1431 * 1432 * This function adds the pktstats hdr and data to current 1433 * skb node of free list. 1434 * 1435 * Return: None 1436 */ 1437 void wlan_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, void *data) 1438 { 1439 struct ath_pktlog_hdr *pktlog_hdr; 1440 struct packet_dump *pkt_stats_dump; 1441 int total_stats_len = 0; 1442 bool wake_up_thread = false; 1443 unsigned long flags; 1444 struct sk_buff *ptr; 1445 int hdr_size; 1446 1447 pktlog_hdr = (struct ath_pktlog_hdr *)pl_hdr; 1448 1449 if (!pktlog_hdr) { 1450 qdf_err("Invalid pkt_stats_header"); 1451 return; 1452 } 1453 1454 pkt_stats_dump = (struct packet_dump *)pkt_dump; 1455 total_stats_len = sizeof(struct ath_pktlog_hdr) + 1456 pktlog_hdr->size; 1457 1458 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags); 1459 1460 if (!gwlan_logging.pkt_stats_pcur_node) { 1461 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags); 1462 return; 1463 } 1464 1465 /* Check if we can accommodate more log into current node/buffer */ 1466 hdr_size = sizeof(struct host_log_pktlog_info) + 1467 sizeof(tAniNlHdr); 1468 if ((total_stats_len + hdr_size) >= 1469 skb_tailroom(gwlan_logging.pkt_stats_pcur_node->skb)) { 1470 wake_up_thread = true; 1471 wlan_get_pkt_stats_free_node(); 1472 } 1473 1474 ptr = gwlan_logging.pkt_stats_pcur_node->skb; 1475 qdf_mem_copy(skb_put(ptr, 1476 sizeof(struct ath_pktlog_hdr)), 1477 pktlog_hdr, 1478 sizeof(struct ath_pktlog_hdr)); 1479 1480 if (pkt_stats_dump) { 1481 qdf_mem_copy(skb_put(ptr, 1482 sizeof(struct packet_dump)), 1483 pkt_stats_dump, 1484 sizeof(struct packet_dump)); 1485 pktlog_hdr->size -= sizeof(struct packet_dump); 1486 } 1487 1488 if (data) 1489 qdf_mem_copy(skb_put(ptr, 1490 pktlog_hdr->size), 1491 data, pktlog_hdr->size); 1492 1493 if (pkt_stats_dump && pkt_stats_dump->type == STOP_MONITOR) { 1494 wake_up_thread = true; 1495 wlan_get_pkt_stats_free_node(); 1496 } 1497 1498 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags); 1499 1500 /* Wakeup logger thread */ 1501 if (true == wake_up_thread) { 1502 set_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag); 1503 wake_up_interruptible(&gwlan_logging.wait_queue); 1504 } 1505 } 1506 1507 /** 1508 * qdf_hal_tx_status_map() - map Tx completion status with 1509 * packet dump Tx status 1510 * @status: Tx completion status 1511 * 1512 * Return: packet dump tx_status enum 1513 */ 1514 static inline enum tx_pkt_fate 1515 qdf_hal_tx_status_map(enum qdf_dp_tx_rx_status status) 1516 { 1517 switch (status) { 1518 case QDF_TX_RX_STATUS_OK: 1519 return TX_PKT_FATE_ACKED; 1520 case QDF_TX_RX_STATUS_FW_DISCARD: 1521 return TX_PKT_FATE_FW_DROP_OTHER; 1522 case QDF_TX_RX_STATUS_NO_ACK: 1523 return TX_PKT_FATE_SENT; 1524 case QDF_TX_RX_STATUS_DROP: 1525 return TX_PKT_FATE_DRV_DROP_OTHER; 1526 case QDF_TX_RX_STATUS_DOWNLOAD_SUCC: 1527 return TX_PKT_FATE_DRV_QUEUED; 1528 default: 1529 return TX_PKT_FATE_DRV_DROP_OTHER; 1530 } 1531 } 1532 1533 /** 1534 * qdf_hal_rx_status_map() - map Rx status with 1535 * packet dump Rx status 1536 * @status: Rx status 1537 * 1538 * Return: packet dump rx_status enum 1539 */ 1540 static inline enum rx_pkt_fate 1541 qdf_hal_rx_status_map(enum qdf_dp_tx_rx_status status) 1542 { 1543 switch (status) { 1544 case QDF_TX_RX_STATUS_OK: 1545 return RX_PKT_FATE_SUCCESS; 1546 case QDF_TX_RX_STATUS_FW_DISCARD: 1547 return RX_PKT_FATE_FW_DROP_OTHER; 1548 case QDF_TX_RX_STATUS_DROP: 1549 return RX_PKT_FATE_DRV_DROP_OTHER; 1550 case QDF_TX_RX_STATUS_DOWNLOAD_SUCC: 1551 return RX_PKT_FATE_DRV_QUEUED; 1552 default: 1553 return RX_PKT_FATE_DRV_DROP_OTHER; 1554 } 1555 } 1556 1557 /** 1558 * qdf_hal_pkt_type_map() - map qdf packet type with 1559 * packet dump packet type 1560 * @type: packet type 1561 * 1562 * Return: Packet dump packet type 1563 */ 1564 static inline enum pkt_type 1565 qdf_hal_pkt_type_map(enum qdf_pkt_type type) 1566 { 1567 switch (type) { 1568 case QDF_TX_MGMT_PKT: 1569 return TX_MGMT_PKT; 1570 case QDF_TX_DATA_PKT: 1571 return TX_DATA_PKT; 1572 case QDF_RX_MGMT_PKT: 1573 return RX_MGMT_PKT; 1574 case QDF_RX_DATA_PKT: 1575 return RX_DATA_PKT; 1576 default: 1577 return INVALID_PKT; 1578 } 1579 } 1580 1581 /* 1582 * send_packetdump() - send packet dump 1583 * @soc: soc handle 1584 * @vdev_id: ID of the virtual device handle 1585 * @netbuf: netbuf 1586 * @status: status of tx packet 1587 * @type: type of packet 1588 * 1589 * This function is used to send packet dump to HAL layer 1590 * using wlan_pkt_stats_to_logger_thread 1591 * 1592 * Return: None 1593 * 1594 */ 1595 static void send_packetdump(ol_txrx_soc_handle soc, 1596 uint8_t vdev_id, qdf_nbuf_t netbuf, 1597 uint8_t status, uint8_t type) 1598 { 1599 struct ath_pktlog_hdr pktlog_hdr = {0}; 1600 struct packet_dump pd_hdr = {0}; 1601 1602 if (!netbuf) { 1603 qdf_err("Invalid netbuf"); 1604 return; 1605 } 1606 1607 /* Send packet dump only for STA interface */ 1608 if (wlan_op_mode_sta != cdp_get_opmode(soc, vdev_id)) 1609 return; 1610 1611 pktlog_hdr.flags |= PKTLOG_HDR_SIZE_16; 1612 1613 pktlog_hdr.log_type = PKTLOG_TYPE_PKT_DUMP; 1614 pktlog_hdr.size = sizeof(pd_hdr) + netbuf->len; 1615 1616 pd_hdr.status = status; 1617 pd_hdr.type = type; 1618 pd_hdr.driver_ts = qdf_get_monotonic_boottime(); 1619 1620 if ((type == TX_MGMT_PKT) || (type == TX_DATA_PKT)) 1621 gtx_count++; 1622 else if ((type == RX_MGMT_PKT) || (type == RX_DATA_PKT)) 1623 grx_count++; 1624 1625 wlan_pkt_stats_to_logger_thread(&pktlog_hdr, &pd_hdr, netbuf->data); 1626 } 1627 1628 1629 /* 1630 * send_packetdump_monitor() - sends start/stop packet dump indication 1631 * @type: type of packet 1632 * 1633 * This function is used to indicate HAL layer to start/stop monitoring 1634 * of packets 1635 * 1636 * Return: None 1637 * 1638 */ 1639 static void send_packetdump_monitor(uint8_t type) 1640 { 1641 struct ath_pktlog_hdr pktlog_hdr = {0}; 1642 struct packet_dump pd_hdr = {0}; 1643 1644 pktlog_hdr.flags |= PKTLOG_HDR_SIZE_16; 1645 1646 pktlog_hdr.log_type = PKTLOG_TYPE_PKT_DUMP; 1647 pktlog_hdr.size = sizeof(pd_hdr); 1648 1649 pd_hdr.type = type; 1650 1651 LOGGING_TRACE(QDF_TRACE_LEVEL_DEBUG, 1652 "fate Tx-Rx %s: type: %d", __func__, type); 1653 1654 wlan_pkt_stats_to_logger_thread(&pktlog_hdr, &pd_hdr, NULL); 1655 } 1656 1657 void wlan_deregister_txrx_packetdump(uint8_t pdev_id) 1658 { 1659 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 1660 1661 if (!soc) 1662 return; 1663 1664 if (gtx_count || grx_count) { 1665 cdp_deregister_packetdump_cb(soc, pdev_id); 1666 wma_deregister_packetdump_callback(); 1667 send_packetdump_monitor(STOP_MONITOR); 1668 csr_packetdump_timer_stop(); 1669 1670 gtx_count = 0; 1671 grx_count = 0; 1672 } else 1673 LOGGING_TRACE(QDF_TRACE_LEVEL_DEBUG, 1674 "%s: deregistered packetdump already", __func__); 1675 } 1676 1677 /* 1678 * check_txrx_packetdump_count() - function to check 1679 * tx/rx packet dump global counts 1680 * @pdev_id: datapath pdev identifier 1681 * 1682 * This function is used to check global counts of tx/rx 1683 * packet dump functionality. 1684 * 1685 * Return: 1 if either gtx_count or grx_count reached 32 1686 * 0 otherwise 1687 * 1688 */ 1689 static bool check_txrx_packetdump_count(uint8_t pdev_id) 1690 { 1691 if (gtx_count == MAX_NUM_PKT_LOG || 1692 grx_count == MAX_NUM_PKT_LOG) { 1693 LOGGING_TRACE(QDF_TRACE_LEVEL_DEBUG, 1694 "%s gtx_count: %d grx_count: %d deregister packetdump", 1695 __func__, gtx_count, grx_count); 1696 wlan_deregister_txrx_packetdump(pdev_id); 1697 return 1; 1698 } 1699 return 0; 1700 } 1701 1702 /* 1703 * tx_packetdump_cb() - tx packet dump callback 1704 * @soc: soc handle 1705 * @pdev_id: datapath pdev id 1706 * @vdev_id: vdev id 1707 * @netbuf: netbuf 1708 * @status: status of tx packet 1709 * @type: packet type 1710 * 1711 * This function is used to send tx packet dump to HAL layer 1712 * and deregister packet dump callbacks 1713 * 1714 * Return: None 1715 * 1716 */ 1717 static void tx_packetdump_cb(ol_txrx_soc_handle soc, 1718 uint8_t pdev_id, uint8_t vdev_id, 1719 qdf_nbuf_t netbuf, 1720 enum qdf_dp_tx_rx_status status, 1721 enum qdf_pkt_type type) 1722 { 1723 bool temp; 1724 enum tx_pkt_fate tx_status = qdf_hal_tx_status_map(status); 1725 enum pkt_type pkt_type = qdf_hal_pkt_type_map(type); 1726 1727 if (!soc) 1728 return; 1729 1730 temp = check_txrx_packetdump_count(pdev_id); 1731 if (temp) 1732 return; 1733 1734 send_packetdump(soc, vdev_id, netbuf, tx_status, pkt_type); 1735 } 1736 1737 1738 /* 1739 * rx_packetdump_cb() - rx packet dump callback 1740 * @soc: soc handle 1741 * @pdev_id: datapath pdev id 1742 * @vdev_id: vdev id 1743 * @netbuf: netbuf 1744 * @status: status of rx packet 1745 * @type: packet type 1746 * 1747 * This function is used to send rx packet dump to HAL layer 1748 * and deregister packet dump callbacks 1749 * 1750 * Return: None 1751 * 1752 */ 1753 static void rx_packetdump_cb(ol_txrx_soc_handle soc, 1754 uint8_t pdev_id, uint8_t vdev_id, 1755 qdf_nbuf_t netbuf, 1756 enum qdf_dp_tx_rx_status status, 1757 enum qdf_pkt_type type) 1758 { 1759 bool temp; 1760 enum rx_pkt_fate rx_status = qdf_hal_rx_status_map(status); 1761 enum pkt_type pkt_type = qdf_hal_pkt_type_map(type); 1762 1763 if (!soc) 1764 return; 1765 1766 temp = check_txrx_packetdump_count(pdev_id); 1767 if (temp) 1768 return; 1769 1770 send_packetdump(soc, vdev_id, netbuf, rx_status, pkt_type); 1771 } 1772 1773 void wlan_register_txrx_packetdump(uint8_t pdev_id) 1774 { 1775 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 1776 1777 if (!soc) 1778 return; 1779 1780 cdp_register_packetdump_cb(soc, pdev_id, 1781 tx_packetdump_cb, rx_packetdump_cb); 1782 wma_register_packetdump_callback(tx_packetdump_cb, 1783 rx_packetdump_cb); 1784 send_packetdump_monitor(START_MONITOR); 1785 1786 gtx_count = 0; 1787 grx_count = 0; 1788 1789 csr_packetdump_timer_start(); 1790 } 1791 #endif /* CONNECTIVITY_PKTLOG */ 1792 #endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ 1793