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