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