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