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 inline void wlan_panic_on_excessive_logging(void) 312 { 313 if (qdf_detected_excessive_logging()) 314 QDF_DEBUG_PANIC("Exceeded %d logs per second", 315 WLAN_MAX_LOGS_PER_SEC); 316 } 317 #else 318 static inline void wlan_panic_on_excessive_logging(void) {} 319 #endif /* WLAN_MAX_LOGS_PER_SEC */ 320 321 static inline void 322 log_to_console(QDF_TRACE_LEVEL level, const char *timestamp, const char *msg) 323 { 324 switch (level) { 325 case QDF_TRACE_LEVEL_FATAL: 326 pr_alert("%s %s\n", timestamp, msg); 327 wlan_panic_on_excessive_logging(); 328 break; 329 case QDF_TRACE_LEVEL_ERROR: 330 pr_err("%s %s\n", timestamp, msg); 331 wlan_panic_on_excessive_logging(); 332 break; 333 case QDF_TRACE_LEVEL_WARN: 334 pr_warn("%s %s\n", timestamp, msg); 335 wlan_panic_on_excessive_logging(); 336 break; 337 case QDF_TRACE_LEVEL_INFO: 338 pr_info("%s %s\n", timestamp, msg); 339 wlan_panic_on_excessive_logging(); 340 break; 341 case QDF_TRACE_LEVEL_INFO_HIGH: 342 case QDF_TRACE_LEVEL_INFO_MED: 343 case QDF_TRACE_LEVEL_INFO_LOW: 344 case QDF_TRACE_LEVEL_DEBUG: 345 default: 346 /* these levels should not be logged to console */ 347 break; 348 } 349 } 350 351 int wlan_log_to_user(QDF_TRACE_LEVEL log_level, char *to_be_sent, int length) 352 { 353 char *ptr; 354 char tbuf[60]; 355 int tlen; 356 int total_log_len; 357 unsigned int *pfilled_length; 358 bool wake_up_thread = false; 359 unsigned long flags; 360 uint64_t ts; 361 362 /* Add the current time stamp */ 363 ts = qdf_get_log_timestamp(); 364 tlen = wlan_add_user_log_time_stamp(tbuf, sizeof(tbuf), ts); 365 366 /* if logging isn't up yet, just dump to dmesg */ 367 if (!gwlan_logging.is_active) { 368 log_to_console(log_level, tbuf, to_be_sent); 369 return 0; 370 } 371 372 /* 1+1 indicate '\n'+'\0' */ 373 total_log_len = length + tlen + 1 + 1; 374 375 spin_lock_irqsave(&gwlan_logging.spin_lock, flags); 376 /* wlan logging svc resources are not yet initialized */ 377 if (!gwlan_logging.pcur_node) { 378 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 379 return -EIO; 380 } 381 382 pfilled_length = &gwlan_logging.pcur_node->filled_length; 383 384 /* Check if we can accommodate more log into current node/buffer */ 385 if ((MAX_LOGMSG_LENGTH - (*pfilled_length + 386 sizeof(tAniNlHdr))) < total_log_len) { 387 wake_up_thread = true; 388 wlan_queue_logmsg_for_app(); 389 pfilled_length = &gwlan_logging.pcur_node->filled_length; 390 } 391 392 ptr = &gwlan_logging.pcur_node->logbuf[sizeof(tAniHdr)]; 393 394 if (unlikely(MAX_LOGMSG_LENGTH < (sizeof(tAniNlHdr) + total_log_len))) { 395 /* 396 * Assumption here is that we receive logs which is less than 397 * MAX_LOGMSG_LENGTH, where we can accommodate the 398 * tAniNlHdr + [context][timestamp] + log 399 * If log length is over MAX_LOGMSG_LENGTH, 400 * the overflow part will be discarded. 401 */ 402 length = MAX_LOGMSG_LENGTH - sizeof(tAniNlHdr) - tlen - 2; 403 /* 404 * QDF_ASSERT if complete log was not accommodated into 405 * the available buffer. 406 */ 407 QDF_ASSERT(0); 408 } 409 410 memcpy(&ptr[*pfilled_length], tbuf, tlen); 411 memcpy(&ptr[*pfilled_length + tlen], to_be_sent, length); 412 *pfilled_length += tlen + length; 413 ptr[*pfilled_length] = '\n'; 414 *pfilled_length += 1; 415 416 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 417 418 /* Wakeup logger thread */ 419 if (wake_up_thread) { 420 set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); 421 wake_up_interruptible(&gwlan_logging.wait_queue); 422 } 423 424 if (gwlan_logging.console_log_levels & BIT(log_level)) 425 log_to_console(log_level, tbuf, to_be_sent); 426 427 return 0; 428 } 429 430 /** 431 * nl_srv_bcast_host_logs() - Wrapper to send bcast msgs to host logs mcast grp 432 * @skb: sk buffer pointer 433 * 434 * Sends the bcast message to host logs multicast group with generic nl socket 435 * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send. 436 * 437 * Return: zero on success, error code otherwise 438 */ 439 #ifdef CNSS_GENL 440 static int nl_srv_bcast_host_logs(struct sk_buff *skb) 441 { 442 return nl_srv_bcast(skb, CLD80211_MCGRP_HOST_LOGS, ANI_NL_MSG_LOG); 443 } 444 #else 445 static int nl_srv_bcast_host_logs(struct sk_buff *skb) 446 { 447 return nl_srv_bcast(skb); 448 } 449 #endif 450 451 #ifndef REMOVE_PKT_LOG 452 /** 453 * pkt_stats_fill_headers() - This function adds headers to skb 454 * @skb: skb to which headers need to be added 455 * 456 * Return: 0 on success or Errno on failure 457 */ 458 static int pkt_stats_fill_headers(struct sk_buff *skb) 459 { 460 struct host_log_pktlog_info cds_pktlog; 461 int cds_pkt_size = sizeof(struct host_log_pktlog_info); 462 tAniNlHdr msg_header; 463 int extra_header_len, nl_payload_len; 464 static int nlmsg_seq; 465 int diag_type; 466 467 qdf_mem_zero(&cds_pktlog, cds_pkt_size); 468 cds_pktlog.version = VERSION_LOG_WLAN_PKT_LOG_INFO_C; 469 cds_pktlog.buf_len = skb->len; 470 cds_pktlog.seq_no = gwlan_logging.pkt_stats_msg_idx++; 471 host_diag_log_set_code(&cds_pktlog, LOG_WLAN_PKT_LOG_INFO_C); 472 host_diag_log_set_length(&cds_pktlog.log_hdr, skb->len + 473 cds_pkt_size); 474 475 if (unlikely(skb_headroom(skb) < cds_pkt_size)) { 476 qdf_nofl_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]", 477 __LINE__, skb->head, skb->data, 478 sizeof(msg_header)); 479 return -EIO; 480 } 481 482 qdf_mem_copy(skb_push(skb, cds_pkt_size), 483 &cds_pktlog, cds_pkt_size); 484 485 if (unlikely(skb_headroom(skb) < sizeof(int))) { 486 qdf_nofl_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]", 487 __LINE__, skb->head, skb->data, 488 sizeof(int)); 489 return -EIO; 490 } 491 492 diag_type = DIAG_TYPE_LOGS; 493 qdf_mem_copy(skb_push(skb, sizeof(int)), &diag_type, sizeof(int)); 494 495 extra_header_len = sizeof(msg_header.radio) + sizeof(tAniHdr) + 496 sizeof(struct nlmsghdr); 497 nl_payload_len = extra_header_len + skb->len; 498 499 msg_header.nlh.nlmsg_type = ANI_NL_MSG_PUMAC; 500 msg_header.nlh.nlmsg_len = nl_payload_len; 501 msg_header.nlh.nlmsg_flags = NLM_F_REQUEST; 502 msg_header.nlh.nlmsg_pid = 0; 503 msg_header.nlh.nlmsg_seq = nlmsg_seq++; 504 msg_header.radio = 0; 505 msg_header.wmsg.type = PTT_MSG_DIAG_CMDS_TYPE; 506 msg_header.wmsg.length = cpu_to_be16(skb->len); 507 508 if (unlikely(skb_headroom(skb) < sizeof(msg_header))) { 509 qdf_nofl_err("VPKT [%d]: Insufficient headroom, head[%pK], data[%pK], req[%zu]", 510 __LINE__, skb->head, skb->data, 511 sizeof(msg_header)); 512 return -EIO; 513 } 514 515 qdf_mem_copy(skb_push(skb, sizeof(msg_header)), &msg_header, 516 sizeof(msg_header)); 517 518 return 0; 519 } 520 521 /** 522 * nl_srv_bcast_diag() - Wrapper to send bcast msgs to diag events mcast grp 523 * @skb: sk buffer pointer 524 * 525 * Sends the bcast message to diag events multicast group with generic nl socket 526 * if CNSS_GENL is enabled. Else, use the legacy netlink socket to send. 527 * 528 * Return: zero on success, error code otherwise 529 */ 530 static int nl_srv_bcast_diag(struct sk_buff *skb) 531 { 532 #ifdef CNSS_GENL 533 return nl_srv_bcast(skb, CLD80211_MCGRP_DIAG_EVENTS, ANI_NL_MSG_PUMAC); 534 #else 535 return nl_srv_bcast(skb); 536 #endif 537 } 538 539 /** 540 * pktlog_send_per_pkt_stats_to_user() - This function is used to send the per 541 * packet statistics to the user 542 * 543 * This function is used to send the per packet statistics to the user 544 * 545 * Return: Success if the message is posted to user 546 */ 547 static int pktlog_send_per_pkt_stats_to_user(void) 548 { 549 int ret = -1; 550 struct pkt_stats_msg *pstats_msg; 551 unsigned long flags; 552 struct sk_buff *skb_new = NULL; 553 static int rate_limit; 554 bool free_old_skb = false; 555 556 while (!list_empty(&gwlan_logging.pkt_stat_filled_list) 557 && !gwlan_logging.exit) { 558 skb_new = dev_alloc_skb(MAX_SKBMSG_LENGTH); 559 if (!skb_new) { 560 if (!rate_limit) { 561 qdf_err("dev_alloc_skb() failed for msg size[%d] drop count = %u", 562 MAX_SKBMSG_LENGTH, 563 gwlan_logging.drop_count); 564 } 565 rate_limit = 1; 566 ret = -ENOMEM; 567 break; 568 } 569 570 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags); 571 572 pstats_msg = (struct pkt_stats_msg *) 573 (gwlan_logging.pkt_stat_filled_list.next); 574 list_del_init(gwlan_logging.pkt_stat_filled_list.next); 575 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags); 576 577 ret = pkt_stats_fill_headers(pstats_msg->skb); 578 if (ret < 0) { 579 qdf_err("Failed to fill headers %d", ret); 580 free_old_skb = true; 581 goto err; 582 } 583 ret = nl_srv_bcast_diag(pstats_msg->skb); 584 if (ret < 0) { 585 qdf_info("Send Failed %d drop_count = %u", ret, 586 ++gwlan_logging.pkt_stat_drop_cnt); 587 } else { 588 ret = 0; 589 } 590 err: 591 /* 592 * Free old skb in case or error before assigning new skb 593 * to the free list. 594 */ 595 if (free_old_skb) 596 dev_kfree_skb(pstats_msg->skb); 597 598 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags); 599 pstats_msg->skb = skb_new; 600 list_add_tail(&pstats_msg->node, 601 &gwlan_logging.pkt_stat_free_list); 602 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags); 603 ret = 0; 604 } 605 606 return ret; 607 608 } 609 #else 610 static inline 611 int pktlog_send_per_pkt_stats_to_user(void) 612 { 613 return 0; 614 } 615 #endif 616 617 static int send_filled_buffers_to_user(void) 618 { 619 int ret = -1; 620 struct log_msg *plog_msg; 621 int payload_len; 622 int tot_msg_len; 623 tAniNlHdr *wnl; 624 struct sk_buff *skb = NULL; 625 struct nlmsghdr *nlh; 626 static int nlmsg_seq; 627 unsigned long flags; 628 static int rate_limit; 629 630 while (!list_empty(&gwlan_logging.filled_list) 631 && !gwlan_logging.exit) { 632 633 skb = dev_alloc_skb(MAX_LOGMSG_LENGTH); 634 if (!skb) { 635 if (!rate_limit) { 636 qdf_err("dev_alloc_skb() failed for msg size[%d] drop count = %u", 637 MAX_LOGMSG_LENGTH, 638 gwlan_logging.drop_count); 639 } 640 rate_limit = 1; 641 ret = -ENOMEM; 642 break; 643 } 644 rate_limit = 0; 645 646 spin_lock_irqsave(&gwlan_logging.spin_lock, flags); 647 648 plog_msg = (struct log_msg *) 649 (gwlan_logging.filled_list.next); 650 list_del_init(gwlan_logging.filled_list.next); 651 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 652 /* 4 extra bytes for the radio idx */ 653 payload_len = plog_msg->filled_length + 654 sizeof(wnl->radio) + sizeof(tAniHdr); 655 656 tot_msg_len = NLMSG_SPACE(payload_len); 657 nlh = nlmsg_put(skb, 0, nlmsg_seq++, 658 ANI_NL_MSG_LOG, payload_len, NLM_F_REQUEST); 659 if (!nlh) { 660 spin_lock_irqsave(&gwlan_logging.spin_lock, flags); 661 list_add_tail(&plog_msg->node, 662 &gwlan_logging.free_list); 663 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 664 qdf_err("drop_count = %u", ++gwlan_logging.drop_count); 665 qdf_err("nlmsg_put() failed for msg size[%d]", 666 tot_msg_len); 667 dev_kfree_skb(skb); 668 skb = NULL; 669 ret = -EINVAL; 670 continue; 671 } 672 673 wnl = (tAniNlHdr *) nlh; 674 wnl->radio = plog_msg->radio; 675 memcpy(&wnl->wmsg, plog_msg->logbuf, 676 plog_msg->filled_length + sizeof(tAniHdr)); 677 678 spin_lock_irqsave(&gwlan_logging.spin_lock, flags); 679 list_add_tail(&plog_msg->node, &gwlan_logging.free_list); 680 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 681 682 ret = nl_srv_bcast_host_logs(skb); 683 /* print every 64th drop count */ 684 if (ret < 0 && (!(gwlan_logging.drop_count % 0x40))) { 685 qdf_err("Send Failed %d drop_count = %u", 686 ret, ++gwlan_logging.drop_count); 687 } 688 } 689 690 return ret; 691 } 692 693 #ifdef FEATURE_WLAN_DIAG_SUPPORT 694 /** 695 * wlan_report_log_completion() - Report bug report completion to userspace 696 * @is_fatal: Type of event, fatal or not 697 * @indicator: Source of bug report, framework/host/firmware 698 * @reason_code: Reason for triggering bug report 699 * @ring_id: Ring id of logging entities 700 * 701 * This function is used to report the bug report completion to userspace 702 * 703 * Return: None 704 */ 705 void wlan_report_log_completion(uint32_t is_fatal, 706 uint32_t indicator, 707 uint32_t reason_code, 708 uint8_t ring_id) 709 { 710 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, 711 struct host_event_wlan_log_complete); 712 713 wlan_diag_event.is_fatal = is_fatal; 714 wlan_diag_event.indicator = indicator; 715 wlan_diag_event.reason_code = reason_code; 716 wlan_diag_event.reserved = ring_id; 717 718 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_LOG_COMPLETE); 719 } 720 #endif 721 722 #ifdef FEATURE_WLAN_DIAG_SUPPORT 723 /** 724 * send_flush_completion_to_user() - Indicate flush completion to the user 725 * @ring_id: Ring id of logging entities 726 * 727 * This function is used to send the flush completion message to user space 728 * 729 * Return: None 730 */ 731 static void send_flush_completion_to_user(uint8_t ring_id) 732 { 733 uint32_t is_fatal, indicator, reason_code; 734 bool recovery_needed; 735 736 cds_get_and_reset_log_completion(&is_fatal, 737 &indicator, &reason_code, &recovery_needed); 738 739 /* Error on purpose, so that it will get logged in the kmsg */ 740 LOGGING_TRACE(QDF_TRACE_LEVEL_DEBUG, 741 "%s: Sending flush done to userspace reason code %d", 742 __func__, reason_code); 743 744 wlan_report_log_completion(is_fatal, indicator, reason_code, ring_id); 745 746 if (recovery_needed) 747 cds_trigger_recovery(QDF_REASON_UNSPECIFIED); 748 } 749 #endif 750 751 static void setup_flush_timer(void) 752 { 753 qdf_spin_lock(&gwlan_logging.flush_timer_lock); 754 if (!gwlan_logging.is_flush_timer_initialized || 755 (gwlan_logging.flush_timer_period == 0)) { 756 qdf_spin_unlock(&gwlan_logging.flush_timer_lock); 757 return; 758 } 759 qdf_timer_mod(&gwlan_logging.flush_timer, 760 gwlan_logging.flush_timer_period); 761 qdf_spin_unlock(&gwlan_logging.flush_timer_lock); 762 } 763 764 /** 765 * wlan_logging_thread() - The WLAN Logger thread 766 * @Arg - pointer to the HDD context 767 * 768 * This thread logs log message to App registered for the logs. 769 */ 770 static int wlan_logging_thread(void *Arg) 771 { 772 int ret_wait_status = 0; 773 int ret = 0; 774 unsigned long flags; 775 776 while (!gwlan_logging.exit) { 777 setup_flush_timer(); 778 ret_wait_status = 779 wait_event_interruptible(gwlan_logging.wait_queue, 780 (!list_empty 781 (&gwlan_logging.filled_list) 782 || test_bit( 783 HOST_LOG_DRIVER_MSG, 784 &gwlan_logging.eventFlag) 785 || test_bit( 786 HOST_LOG_PER_PKT_STATS, 787 &gwlan_logging.eventFlag) 788 || test_bit( 789 HOST_LOG_FW_FLUSH_COMPLETE, 790 &gwlan_logging.eventFlag) 791 || gwlan_logging.exit)); 792 793 if (ret_wait_status == -ERESTARTSYS) { 794 qdf_err("wait_event_interruptible returned -ERESTARTSYS"); 795 break; 796 } 797 798 if (gwlan_logging.exit) 799 break; 800 801 802 if (test_and_clear_bit(HOST_LOG_DRIVER_MSG, 803 &gwlan_logging.eventFlag)) { 804 ret = send_filled_buffers_to_user(); 805 if (-ENOMEM == ret) 806 msleep(200); 807 #ifdef FEATURE_WLAN_DIAG_SUPPORT 808 if (WLAN_LOG_INDICATOR_HOST_ONLY == 809 cds_get_log_indicator()) { 810 send_flush_completion_to_user( 811 RING_ID_DRIVER_DEBUG); 812 } 813 #endif 814 } 815 816 if (test_and_clear_bit(HOST_LOG_PER_PKT_STATS, 817 &gwlan_logging.eventFlag)) { 818 ret = pktlog_send_per_pkt_stats_to_user(); 819 if (-ENOMEM == ret) 820 msleep(200); 821 } 822 823 if (test_and_clear_bit(HOST_LOG_FW_FLUSH_COMPLETE, 824 &gwlan_logging.eventFlag)) { 825 /* Flush bit could have been set while we were mid 826 * way in the logging thread. So, need to check other 827 * buffers like log messages, per packet stats again 828 * to flush any residual data in them 829 */ 830 if (gwlan_logging.is_flush_complete == true) { 831 gwlan_logging.is_flush_complete = false; 832 #ifdef FEATURE_WLAN_DIAG_SUPPORT 833 send_flush_completion_to_user( 834 RING_ID_DRIVER_DEBUG); 835 #endif 836 } else { 837 gwlan_logging.is_flush_complete = true; 838 /* Flush all current host logs*/ 839 spin_lock_irqsave(&gwlan_logging.spin_lock, 840 flags); 841 wlan_queue_logmsg_for_app(); 842 spin_unlock_irqrestore(&gwlan_logging.spin_lock, 843 flags); 844 set_bit(HOST_LOG_DRIVER_MSG, 845 &gwlan_logging.eventFlag); 846 set_bit(HOST_LOG_PER_PKT_STATS, 847 &gwlan_logging.eventFlag); 848 set_bit(HOST_LOG_FW_FLUSH_COMPLETE, 849 &gwlan_logging.eventFlag); 850 wake_up_interruptible( 851 &gwlan_logging.wait_queue); 852 } 853 } 854 } 855 856 complete_and_exit(&gwlan_logging.shutdown_comp, 0); 857 858 return 0; 859 } 860 861 void wlan_logging_set_active(bool active) 862 { 863 gwlan_logging.is_active = active; 864 } 865 866 void wlan_set_console_log_levels(uint32_t console_log_levels) 867 { 868 gwlan_logging.console_log_levels = console_log_levels; 869 } 870 871 qdf_export_symbol(wlan_set_console_log_levels); 872 873 static void flush_log_buffers_timer(void *dummy) 874 { 875 wlan_flush_host_logs_for_fatal(); 876 } 877 878 int wlan_logging_set_flush_timer(uint32_t milliseconds) 879 { 880 if (milliseconds > MAX_FLUSH_TIMER_PERIOD_VALUE) { 881 QDF_TRACE_ERROR(QDF_MODULE_ID_QDF, 882 "ERROR! value should be (0 - %d)\n", 883 MAX_FLUSH_TIMER_PERIOD_VALUE); 884 return -EINVAL; 885 } 886 if (!gwlan_logging.is_active) { 887 QDF_TRACE_ERROR(QDF_MODULE_ID_QDF, 888 "WLAN-Logging not active"); 889 return -EINVAL; 890 } 891 qdf_spin_lock(&gwlan_logging.flush_timer_lock); 892 if (!gwlan_logging.is_flush_timer_initialized) { 893 qdf_spin_unlock(&gwlan_logging.flush_timer_lock); 894 return -EINVAL; 895 } 896 gwlan_logging.flush_timer_period = milliseconds; 897 if (milliseconds) { 898 qdf_timer_mod(&gwlan_logging.flush_timer, 899 gwlan_logging.flush_timer_period); 900 } 901 qdf_spin_unlock(&gwlan_logging.flush_timer_lock); 902 return 0; 903 } 904 905 static int panic_wifilog_ratelimit_print(void) 906 { 907 return __ratelimit(&panic_wifilog_ratelimit); 908 } 909 910 /** 911 * wlan_logging_dump_last_logs() - Panic notifier callback's helper function 912 * 913 * This function prints buffered logs in chunks of MAX_LOG_LINE. 914 */ 915 static void wlan_logging_dump_last_logs(void) 916 { 917 char *log; 918 struct log_msg *plog_msg; 919 char textbuf[MAX_LOG_LINE]; 920 unsigned int filled_length; 921 unsigned int text_len; 922 unsigned long flags; 923 924 /* Iterate over panic list */ 925 pr_err("\n"); 926 while (!list_empty(&gwlan_logging.panic_list)) { 927 plog_msg = (struct log_msg *) 928 (gwlan_logging.panic_list.next); 929 list_del_init(gwlan_logging.panic_list.next); 930 log = &plog_msg->logbuf[sizeof(tAniHdr)]; 931 filled_length = plog_msg->filled_length; 932 while (filled_length) { 933 text_len = scnprintf(textbuf, 934 sizeof(textbuf), 935 "%s", log); 936 if (panic_wifilog_ratelimit_print()) 937 pr_err("%s\n", textbuf); 938 log += text_len; 939 filled_length -= text_len; 940 } 941 spin_lock_irqsave(&gwlan_logging.spin_lock, flags); 942 list_add_tail(&plog_msg->node, 943 &gwlan_logging.free_list); 944 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 945 } 946 } 947 948 /** 949 * wlan_logging_panic_handler() - Panic notifier callback 950 * 951 * This function extracts log buffers in filled list and 952 * current node.Sends them to helper function for printing. 953 */ 954 static int wlan_logging_panic_handler(struct notifier_block *this, 955 unsigned long event, void *ptr) 956 { 957 char *log; 958 struct log_msg *plog_msg; 959 unsigned long flags; 960 961 spin_lock_irqsave(&gwlan_logging.spin_lock, flags); 962 /* Iterate over nodes queued for app */ 963 while (!list_empty(&gwlan_logging.filled_list)) { 964 plog_msg = (struct log_msg *) 965 (gwlan_logging.filled_list.next); 966 list_del_init(gwlan_logging.filled_list.next); 967 list_add_tail(&plog_msg->node, 968 &gwlan_logging.panic_list); 969 } 970 /* Check current node */ 971 if (gwlan_logging.pcur_node && 972 gwlan_logging.pcur_node->filled_length) { 973 plog_msg = gwlan_logging.pcur_node; 974 log = &plog_msg->logbuf[sizeof(tAniHdr)]; 975 log[plog_msg->filled_length] = '\0'; 976 list_add_tail(&gwlan_logging.pcur_node->node, 977 &gwlan_logging.panic_list); 978 if (!list_empty(&gwlan_logging.free_list)) { 979 gwlan_logging.pcur_node = 980 (struct log_msg *)(gwlan_logging.free_list.next); 981 list_del_init(gwlan_logging.free_list.next); 982 gwlan_logging.pcur_node->filled_length = 0; 983 } else 984 gwlan_logging.pcur_node = NULL; 985 } 986 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 987 988 wlan_logging_dump_last_logs(); 989 990 return NOTIFY_DONE; 991 } 992 993 static struct notifier_block panic_nb = { 994 .notifier_call = wlan_logging_panic_handler, 995 }; 996 997 int wlan_logging_notifier_init(bool dump_at_kernel_enable) 998 { 999 int ret; 1000 1001 if (gwlan_logging.is_active && 1002 !dump_at_kernel_enable) { 1003 ret = atomic_notifier_chain_register(&panic_notifier_list, 1004 &panic_nb); 1005 if (ret) { 1006 QDF_TRACE_ERROR(QDF_MODULE_ID_QDF, 1007 "Failed to register panic notifier"); 1008 return -EINVAL; 1009 } 1010 } 1011 1012 return 0; 1013 } 1014 1015 int wlan_logging_notifier_deinit(bool dump_at_kernel_enable) 1016 { 1017 if (gwlan_logging.is_active && 1018 !dump_at_kernel_enable) { 1019 atomic_notifier_chain_unregister(&panic_notifier_list, 1020 &panic_nb); 1021 } 1022 1023 return 0; 1024 } 1025 1026 static void flush_timer_init(void) 1027 { 1028 qdf_spinlock_create(&gwlan_logging.flush_timer_lock); 1029 qdf_timer_init(NULL, &gwlan_logging.flush_timer, 1030 flush_log_buffers_timer, NULL, 1031 QDF_TIMER_TYPE_SW); 1032 gwlan_logging.is_flush_timer_initialized = true; 1033 gwlan_logging.flush_timer_period = 0; 1034 } 1035 1036 int wlan_logging_sock_init_svc(void) 1037 { 1038 int i = 0, j, pkt_stats_size; 1039 unsigned long irq_flag; 1040 1041 flush_timer_init(); 1042 spin_lock_init(&gwlan_logging.spin_lock); 1043 spin_lock_init(&gwlan_logging.pkt_stats_lock); 1044 1045 gwlan_logging.console_log_levels = 0; 1046 gwlan_logging.num_buf = MAX_LOGMSG_COUNT; 1047 gwlan_logging.buffer_length = MAX_LOGMSG_LENGTH; 1048 1049 if (allocate_log_msg_buffer() != QDF_STATUS_SUCCESS) { 1050 qdf_err("Could not allocate memory for log_msg"); 1051 return -ENOMEM; 1052 } 1053 1054 spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag); 1055 INIT_LIST_HEAD(&gwlan_logging.free_list); 1056 INIT_LIST_HEAD(&gwlan_logging.filled_list); 1057 INIT_LIST_HEAD(&gwlan_logging.panic_list); 1058 1059 for (i = 0; i < gwlan_logging.num_buf; i++) { 1060 list_add(&gplog_msg[i].node, &gwlan_logging.free_list); 1061 gplog_msg[i].index = i; 1062 } 1063 gwlan_logging.pcur_node = (struct log_msg *) 1064 (gwlan_logging.free_list.next); 1065 list_del_init(gwlan_logging.free_list.next); 1066 spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag); 1067 1068 /* Initialize the pktStats data structure here */ 1069 pkt_stats_size = sizeof(struct pkt_stats_msg); 1070 gpkt_stats_buffers = vmalloc(MAX_PKTSTATS_BUFF * pkt_stats_size); 1071 if (!gpkt_stats_buffers) { 1072 qdf_err("Could not allocate memory for Pkt stats"); 1073 goto err1; 1074 } 1075 qdf_mem_zero(gpkt_stats_buffers, 1076 MAX_PKTSTATS_BUFF * pkt_stats_size); 1077 1078 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag); 1079 gwlan_logging.pkt_stats_msg_idx = 0; 1080 INIT_LIST_HEAD(&gwlan_logging.pkt_stat_free_list); 1081 INIT_LIST_HEAD(&gwlan_logging.pkt_stat_filled_list); 1082 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag); 1083 1084 1085 for (i = 0; i < MAX_PKTSTATS_BUFF; i++) { 1086 gpkt_stats_buffers[i].skb = dev_alloc_skb(MAX_PKTSTATS_LENGTH); 1087 if (!gpkt_stats_buffers[i].skb) { 1088 qdf_err("Memory alloc failed for skb"); 1089 /* free previously allocated skb and return */ 1090 for (j = 0; j < i ; j++) 1091 dev_kfree_skb(gpkt_stats_buffers[j].skb); 1092 goto err2; 1093 } 1094 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag); 1095 list_add(&gpkt_stats_buffers[i].node, 1096 &gwlan_logging.pkt_stat_free_list); 1097 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag); 1098 } 1099 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag); 1100 gwlan_logging.pkt_stats_pcur_node = (struct pkt_stats_msg *) 1101 (gwlan_logging.pkt_stat_free_list.next); 1102 list_del_init(gwlan_logging.pkt_stat_free_list.next); 1103 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag); 1104 /* Pkt Stats intialization done */ 1105 1106 init_waitqueue_head(&gwlan_logging.wait_queue); 1107 gwlan_logging.exit = false; 1108 clear_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); 1109 clear_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag); 1110 clear_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag); 1111 init_completion(&gwlan_logging.shutdown_comp); 1112 gwlan_logging.thread = kthread_create(wlan_logging_thread, NULL, 1113 "wlan_logging_thread"); 1114 if (IS_ERR(gwlan_logging.thread)) { 1115 qdf_err("Could not Create LogMsg Thread Controller"); 1116 goto err3; 1117 } 1118 wake_up_process(gwlan_logging.thread); 1119 gwlan_logging.is_active = true; 1120 gwlan_logging.is_flush_complete = false; 1121 1122 return 0; 1123 1124 err3: 1125 for (i = 0; i < MAX_PKTSTATS_BUFF; i++) { 1126 if (gpkt_stats_buffers[i].skb) 1127 dev_kfree_skb(gpkt_stats_buffers[i].skb); 1128 } 1129 err2: 1130 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag); 1131 gwlan_logging.pkt_stats_pcur_node = NULL; 1132 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag); 1133 vfree(gpkt_stats_buffers); 1134 gpkt_stats_buffers = NULL; 1135 err1: 1136 spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag); 1137 gwlan_logging.pcur_node = NULL; 1138 spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag); 1139 free_log_msg_buffer(); 1140 1141 return -ENOMEM; 1142 } 1143 1144 static void flush_timer_deinit(void) 1145 { 1146 gwlan_logging.is_flush_timer_initialized = false; 1147 qdf_spin_lock(&gwlan_logging.flush_timer_lock); 1148 qdf_timer_stop(&gwlan_logging.flush_timer); 1149 qdf_timer_free(&gwlan_logging.flush_timer); 1150 qdf_spin_unlock(&gwlan_logging.flush_timer_lock); 1151 qdf_spinlock_destroy(&gwlan_logging.flush_timer_lock); 1152 } 1153 1154 int wlan_logging_sock_deinit_svc(void) 1155 { 1156 unsigned long irq_flag; 1157 int i; 1158 1159 if (!gwlan_logging.pcur_node) 1160 return 0; 1161 1162 INIT_COMPLETION(gwlan_logging.shutdown_comp); 1163 gwlan_logging.exit = true; 1164 gwlan_logging.is_active = false; 1165 #if defined(FEATURE_FW_LOG_PARSING) || defined(FEATURE_WLAN_DIAG_SUPPORT) 1166 cds_set_multicast_logging(0); 1167 #endif 1168 gwlan_logging.is_flush_complete = false; 1169 clear_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); 1170 clear_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag); 1171 clear_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag); 1172 wake_up_interruptible(&gwlan_logging.wait_queue); 1173 wait_for_completion(&gwlan_logging.shutdown_comp); 1174 1175 spin_lock_irqsave(&gwlan_logging.spin_lock, irq_flag); 1176 gwlan_logging.pcur_node = NULL; 1177 spin_unlock_irqrestore(&gwlan_logging.spin_lock, irq_flag); 1178 1179 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, irq_flag); 1180 gwlan_logging.pkt_stats_pcur_node = NULL; 1181 gwlan_logging.pkt_stats_msg_idx = 0; 1182 gwlan_logging.pkt_stat_drop_cnt = 0; 1183 for (i = 0; i < MAX_PKTSTATS_BUFF; i++) { 1184 if (gpkt_stats_buffers[i].skb) 1185 dev_kfree_skb(gpkt_stats_buffers[i].skb); 1186 } 1187 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, irq_flag); 1188 1189 vfree(gpkt_stats_buffers); 1190 gpkt_stats_buffers = NULL; 1191 free_log_msg_buffer(); 1192 flush_timer_deinit(); 1193 1194 return 0; 1195 } 1196 1197 /** 1198 * wlan_logging_set_per_pkt_stats() - This function triggers per packet logging 1199 * 1200 * This function is used to send signal to the logger thread for logging per 1201 * packet stats 1202 * 1203 * Return: None 1204 * 1205 */ 1206 void wlan_logging_set_per_pkt_stats(void) 1207 { 1208 if (gwlan_logging.is_active == false) 1209 return; 1210 1211 set_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag); 1212 wake_up_interruptible(&gwlan_logging.wait_queue); 1213 } 1214 1215 /* 1216 * wlan_logging_set_fw_flush_complete() - FW log flush completion 1217 * 1218 * This function is used to send signal to the logger thread to indicate 1219 * that the flushing of FW logs is complete by the FW 1220 * 1221 * Return: None 1222 * 1223 */ 1224 void wlan_logging_set_fw_flush_complete(void) 1225 { 1226 if (!gwlan_logging.is_active) 1227 return; 1228 1229 set_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag); 1230 wake_up_interruptible(&gwlan_logging.wait_queue); 1231 } 1232 1233 /** 1234 * wlan_flush_host_logs_for_fatal() - Flush host logs 1235 * 1236 * This function is used to send signal to the logger thread to 1237 * Flush the host logs 1238 * 1239 * Return: None 1240 */ 1241 void wlan_flush_host_logs_for_fatal(void) 1242 { 1243 unsigned long flags; 1244 1245 if (gwlan_logging.flush_timer_period == 0) 1246 qdf_info("Flush all host logs Setting HOST_LOG_POST_MAS"); 1247 spin_lock_irqsave(&gwlan_logging.spin_lock, flags); 1248 wlan_queue_logmsg_for_app(); 1249 spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); 1250 set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); 1251 wake_up_interruptible(&gwlan_logging.wait_queue); 1252 } 1253 1254 #ifdef FEATURE_PKTLOG 1255 #ifndef REMOVE_PKT_LOG 1256 1257 static uint8_t gtx_count; 1258 static uint8_t grx_count; 1259 1260 /** 1261 * wlan_get_pkt_stats_free_node() - Get the free node for pkt stats 1262 * 1263 * This function is used to get the free node for pkt stats from 1264 * free list/filles list 1265 * 1266 * Return: int 1267 * 1268 */ 1269 static int wlan_get_pkt_stats_free_node(void) 1270 { 1271 int ret = 0; 1272 1273 list_add_tail(&gwlan_logging.pkt_stats_pcur_node->node, 1274 &gwlan_logging.pkt_stat_filled_list); 1275 1276 if (!list_empty(&gwlan_logging.pkt_stat_free_list)) { 1277 /* Get buffer from free list */ 1278 gwlan_logging.pkt_stats_pcur_node = 1279 (struct pkt_stats_msg *)(gwlan_logging.pkt_stat_free_list.next); 1280 list_del_init(gwlan_logging.pkt_stat_free_list.next); 1281 } else if (!list_empty(&gwlan_logging.pkt_stat_filled_list)) { 1282 /* Get buffer from filled list. This condition will drop the 1283 * packet from being indicated to app 1284 */ 1285 gwlan_logging.pkt_stats_pcur_node = 1286 (struct pkt_stats_msg *) 1287 (gwlan_logging.pkt_stat_filled_list.next); 1288 ++gwlan_logging.pkt_stat_drop_cnt; 1289 /* print every 64th drop count */ 1290 if ( 1291 cds_is_multicast_logging() && 1292 (!(gwlan_logging.pkt_stat_drop_cnt % 0x40))) { 1293 qdf_err("drop_count = %u", 1294 gwlan_logging.pkt_stat_drop_cnt); 1295 } 1296 list_del_init(gwlan_logging.pkt_stat_filled_list.next); 1297 ret = 1; 1298 } 1299 1300 /* Reset the skb values, essential if dequeued from filled list */ 1301 skb_trim(gwlan_logging.pkt_stats_pcur_node->skb, 0); 1302 return ret; 1303 } 1304 1305 /** 1306 * wlan_pkt_stats_to_logger_thread() - Add the pkt stats to SKB 1307 * @pl_hdr: Pointer to pl_hdr 1308 * @pkt_dump: Pointer to pkt_dump 1309 * @data: Pointer to data 1310 * 1311 * This function adds the pktstats hdr and data to current 1312 * skb node of free list. 1313 * 1314 * Return: None 1315 */ 1316 void wlan_pkt_stats_to_logger_thread(void *pl_hdr, void *pkt_dump, void *data) 1317 { 1318 struct ath_pktlog_hdr *pktlog_hdr; 1319 struct packet_dump *pkt_stats_dump; 1320 int total_stats_len = 0; 1321 bool wake_up_thread = false; 1322 unsigned long flags; 1323 struct sk_buff *ptr; 1324 int hdr_size; 1325 1326 pktlog_hdr = (struct ath_pktlog_hdr *)pl_hdr; 1327 1328 if (!pktlog_hdr) { 1329 qdf_err("Invalid pkt_stats_header"); 1330 return; 1331 } 1332 1333 pkt_stats_dump = (struct packet_dump *)pkt_dump; 1334 total_stats_len = sizeof(struct ath_pktlog_hdr) + 1335 pktlog_hdr->size; 1336 1337 spin_lock_irqsave(&gwlan_logging.pkt_stats_lock, flags); 1338 1339 if (!gwlan_logging.pkt_stats_pcur_node) { 1340 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags); 1341 return; 1342 } 1343 1344 /* Check if we can accommodate more log into current node/buffer */ 1345 hdr_size = sizeof(struct host_log_pktlog_info) + 1346 sizeof(tAniNlHdr); 1347 if ((total_stats_len + hdr_size) >= 1348 skb_tailroom(gwlan_logging.pkt_stats_pcur_node->skb)) { 1349 wake_up_thread = true; 1350 wlan_get_pkt_stats_free_node(); 1351 } 1352 1353 ptr = gwlan_logging.pkt_stats_pcur_node->skb; 1354 qdf_mem_copy(skb_put(ptr, 1355 sizeof(struct ath_pktlog_hdr)), 1356 pktlog_hdr, 1357 sizeof(struct ath_pktlog_hdr)); 1358 1359 if (pkt_stats_dump) { 1360 qdf_mem_copy(skb_put(ptr, 1361 sizeof(struct packet_dump)), 1362 pkt_stats_dump, 1363 sizeof(struct packet_dump)); 1364 pktlog_hdr->size -= sizeof(struct packet_dump); 1365 } 1366 1367 if (data) 1368 qdf_mem_copy(skb_put(ptr, 1369 pktlog_hdr->size), 1370 data, pktlog_hdr->size); 1371 1372 if (pkt_stats_dump && pkt_stats_dump->type == STOP_MONITOR) { 1373 wake_up_thread = true; 1374 wlan_get_pkt_stats_free_node(); 1375 } 1376 1377 spin_unlock_irqrestore(&gwlan_logging.pkt_stats_lock, flags); 1378 1379 /* Wakeup logger thread */ 1380 if (true == wake_up_thread) { 1381 set_bit(HOST_LOG_PER_PKT_STATS, &gwlan_logging.eventFlag); 1382 wake_up_interruptible(&gwlan_logging.wait_queue); 1383 } 1384 } 1385 1386 /** 1387 * driver_hal_status_map() - maps driver to hal 1388 * status 1389 * @status: status to be mapped 1390 * 1391 * This function is used to map driver to hal status 1392 * 1393 * Return: None 1394 * 1395 */ 1396 static void driver_hal_status_map(uint8_t *status) 1397 { 1398 switch (*status) { 1399 case tx_status_ok: 1400 *status = TX_PKT_FATE_ACKED; 1401 break; 1402 case tx_status_discard: 1403 *status = TX_PKT_FATE_DRV_DROP_OTHER; 1404 break; 1405 case tx_status_no_ack: 1406 *status = TX_PKT_FATE_SENT; 1407 break; 1408 case tx_status_download_fail: 1409 *status = TX_PKT_FATE_FW_QUEUED; 1410 break; 1411 default: 1412 *status = TX_PKT_FATE_DRV_DROP_OTHER; 1413 break; 1414 } 1415 } 1416 1417 /* 1418 * send_packetdump() - send packet dump 1419 * @soc: soc handle 1420 * @vdev_id: ID of the virtual device handle 1421 * @netbuf: netbuf 1422 * @status: status of tx packet 1423 * @type: type of packet 1424 * 1425 * This function is used to send packet dump to HAL layer 1426 * using wlan_pkt_stats_to_logger_thread 1427 * 1428 * Return: None 1429 * 1430 */ 1431 static void send_packetdump(ol_txrx_soc_handle soc, 1432 uint8_t vdev_id, qdf_nbuf_t netbuf, 1433 uint8_t status, uint8_t type) 1434 { 1435 struct ath_pktlog_hdr pktlog_hdr = {0}; 1436 struct packet_dump pd_hdr = {0}; 1437 1438 if (!netbuf) { 1439 qdf_err("Invalid netbuf"); 1440 return; 1441 } 1442 1443 /* Send packet dump only for STA interface */ 1444 if (wlan_op_mode_sta != cdp_get_opmode(soc, vdev_id)) 1445 return; 1446 1447 #if defined(HELIUMPLUS) 1448 pktlog_hdr.flags |= PKTLOG_HDR_SIZE_16; 1449 #endif 1450 1451 pktlog_hdr.log_type = PKTLOG_TYPE_PKT_DUMP; 1452 pktlog_hdr.size = sizeof(pd_hdr) + netbuf->len; 1453 1454 pd_hdr.status = status; 1455 pd_hdr.type = type; 1456 pd_hdr.driver_ts = qdf_get_monotonic_boottime(); 1457 1458 if ((type == TX_MGMT_PKT) || (type == TX_DATA_PKT)) 1459 gtx_count++; 1460 else if ((type == RX_MGMT_PKT) || (type == RX_DATA_PKT)) 1461 grx_count++; 1462 1463 wlan_pkt_stats_to_logger_thread(&pktlog_hdr, &pd_hdr, netbuf->data); 1464 } 1465 1466 1467 /* 1468 * send_packetdump_monitor() - sends start/stop packet dump indication 1469 * @type: type of packet 1470 * 1471 * This function is used to indicate HAL layer to start/stop monitoring 1472 * of packets 1473 * 1474 * Return: None 1475 * 1476 */ 1477 static void send_packetdump_monitor(uint8_t type) 1478 { 1479 struct ath_pktlog_hdr pktlog_hdr = {0}; 1480 struct packet_dump pd_hdr = {0}; 1481 1482 #if defined(HELIUMPLUS) 1483 pktlog_hdr.flags |= PKTLOG_HDR_SIZE_16; 1484 #endif 1485 1486 pktlog_hdr.log_type = PKTLOG_TYPE_PKT_DUMP; 1487 pktlog_hdr.size = sizeof(pd_hdr); 1488 1489 pd_hdr.type = type; 1490 1491 LOGGING_TRACE(QDF_TRACE_LEVEL_DEBUG, 1492 "fate Tx-Rx %s: type: %d", __func__, type); 1493 1494 wlan_pkt_stats_to_logger_thread(&pktlog_hdr, &pd_hdr, NULL); 1495 } 1496 1497 void wlan_deregister_txrx_packetdump(uint8_t pdev_id) 1498 { 1499 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 1500 1501 if (!soc) 1502 return; 1503 1504 if (gtx_count || grx_count) { 1505 cdp_deregister_packetdump_cb(soc, pdev_id); 1506 wma_deregister_packetdump_callback(); 1507 send_packetdump_monitor(STOP_MONITOR); 1508 csr_packetdump_timer_stop(); 1509 1510 gtx_count = 0; 1511 grx_count = 0; 1512 } else 1513 LOGGING_TRACE(QDF_TRACE_LEVEL_DEBUG, 1514 "%s: deregistered packetdump already", __func__); 1515 } 1516 1517 /* 1518 * check_txrx_packetdump_count() - function to check 1519 * tx/rx packet dump global counts 1520 * @pdev_id: datapath pdev identifier 1521 * 1522 * This function is used to check global counts of tx/rx 1523 * packet dump functionality. 1524 * 1525 * Return: 1 if either gtx_count or grx_count reached 32 1526 * 0 otherwise 1527 * 1528 */ 1529 static bool check_txrx_packetdump_count(uint8_t pdev_id) 1530 { 1531 if (gtx_count == MAX_NUM_PKT_LOG || 1532 grx_count == MAX_NUM_PKT_LOG) { 1533 LOGGING_TRACE(QDF_TRACE_LEVEL_DEBUG, 1534 "%s gtx_count: %d grx_count: %d deregister packetdump", 1535 __func__, gtx_count, grx_count); 1536 wlan_deregister_txrx_packetdump(pdev_id); 1537 return 1; 1538 } 1539 return 0; 1540 } 1541 1542 /* 1543 * tx_packetdump_cb() - tx packet dump callback 1544 * @soc: soc handle 1545 * @pdev_id: datapath pdev id 1546 * @vdev_id: vdev id 1547 * @netbuf: netbuf 1548 * @status: status of tx packet 1549 * @type: packet type 1550 * 1551 * This function is used to send tx packet dump to HAL layer 1552 * and deregister packet dump callbacks 1553 * 1554 * Return: None 1555 * 1556 */ 1557 static void tx_packetdump_cb(ol_txrx_soc_handle soc, 1558 uint8_t pdev_id, uint8_t vdev_id, 1559 qdf_nbuf_t netbuf, 1560 uint8_t status, uint8_t type) 1561 { 1562 bool temp; 1563 1564 if (!soc) 1565 return; 1566 1567 temp = check_txrx_packetdump_count(pdev_id); 1568 if (temp) 1569 return; 1570 1571 driver_hal_status_map(&status); 1572 send_packetdump(soc, vdev_id, netbuf, status, type); 1573 } 1574 1575 1576 /* 1577 * rx_packetdump_cb() - rx packet dump callback 1578 * @soc: soc handle 1579 * @pdev_id: datapath pdev id 1580 * @vdev_id: vdev id 1581 * @netbuf: netbuf 1582 * @status: status of rx packet 1583 * @type: packet type 1584 * 1585 * This function is used to send rx packet dump to HAL layer 1586 * and deregister packet dump callbacks 1587 * 1588 * Return: None 1589 * 1590 */ 1591 static void rx_packetdump_cb(ol_txrx_soc_handle soc, 1592 uint8_t pdev_id, uint8_t vdev_id, 1593 qdf_nbuf_t netbuf, 1594 uint8_t status, uint8_t type) 1595 { 1596 bool temp; 1597 1598 if (!soc) 1599 return; 1600 1601 temp = check_txrx_packetdump_count(pdev_id); 1602 if (temp) 1603 return; 1604 1605 send_packetdump(soc, vdev_id, netbuf, status, type); 1606 } 1607 1608 void wlan_register_txrx_packetdump(uint8_t pdev_id) 1609 { 1610 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 1611 1612 if (!soc) 1613 return; 1614 1615 cdp_register_packetdump_cb(soc, pdev_id, 1616 tx_packetdump_cb, rx_packetdump_cb); 1617 wma_register_packetdump_callback(tx_packetdump_cb, 1618 rx_packetdump_cb); 1619 send_packetdump_monitor(START_MONITOR); 1620 1621 gtx_count = 0; 1622 grx_count = 0; 1623 1624 csr_packetdump_timer_start(); 1625 } 1626 #endif /* REMOVE_PKT_LOG */ 1627 #endif /* FEATURE_PKTLOG */ 1628 #endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ 1629