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