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