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