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