/* * Process all the Netlink messages from Logger Socket app in user space */ static int wlan_logging_proc_sock_rx_msg(struct sk_buff *skb) { tAniNlHdr *wnl; int radio; int type; int ret; if (TRUE == vos_isUnloadInProgress()) { pr_info("%s: unload in progress\n",__func__); return -ENODEV; } wnl = (tAniNlHdr *) skb->data; radio = wnl->radio; type = wnl->nlh.nlmsg_type; if (radio < 0 || radio > ANI_MAX_RADIOS) { pr_err("%s: invalid radio id [%d]\n", __func__, radio); return -EINVAL; } if (gapp_pid != INVALID_PID) { if (wnl->nlh.nlmsg_pid > gapp_pid) { gapp_pid = wnl->nlh.nlmsg_pid; } spin_lock_bh(&gwlan_logging.spin_lock); if (gwlan_logging.pcur_node->filled_length) { wlan_queue_logmsg_for_app(); } spin_unlock_bh(&gwlan_logging.spin_lock); set_bit(HOST_LOG_POST, &gwlan_logging.event_flag); wake_up_interruptible(&gwlan_logging.wait_queue); } else { /* This is to set the default levels (WLAN logging * default values not the VOS trace default) when * logger app is registered for the first time. */ gapp_pid = wnl->nlh.nlmsg_pid; } ret = wlan_send_sock_msg_to_app(&wnl->wmsg, 0, ANI_NL_MSG_LOG, wnl->nlh.nlmsg_pid); if (ret < 0) { pr_err("wlan_send_sock_msg_to_app: failed"); } return ret; }
/* * Process all the Netlink messages from Logger Socket app in user space */ static int wlan_logging_proc_sock_rx_msg(struct sk_buff *skb) { tAniNlHdr *wnl; int radio; int type; int ret; wnl = (tAniNlHdr *) skb->data; radio = wnl->radio; type = wnl->nlh.nlmsg_type; if (radio < 0 || radio > ANI_MAX_RADIOS) { LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: invalid radio id [%d]\n", __func__, radio); return -EINVAL; } if (gapp_pid != INVALID_PID) { if (wnl->nlh.nlmsg_pid > gapp_pid) { gapp_pid = wnl->nlh.nlmsg_pid; } spin_lock_bh(&gwlan_logging.spin_lock); if (gwlan_logging.pcur_node->filled_length) { wlan_queue_logmsg_for_app(); } spin_unlock_bh(&gwlan_logging.spin_lock); gwlan_logging.wakeEvent = TRUE; wake_up_interruptible(&gwlan_logging.wait_queue); } else { /* This is to set the default levels (WLAN logging * default values not the VOS trace default) when * logger app is registered for the first time. */ gapp_pid = wnl->nlh.nlmsg_pid; set_default_logtoapp_log_level(); } ret = wlan_send_sock_msg_to_app(&wnl->wmsg, 0, ANI_NL_MSG_LOG, wnl->nlh.nlmsg_pid); if (ret < 0) { LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR, "wlan_send_sock_msg_to_app: failed"); } return ret; }
int wlan_log_to_user(VOS_TRACE_LEVEL log_level, char *to_be_sent, int length) { /* Add the current time stamp */ char *ptr; char tbuf[50]; int tlen; int total_log_len; unsigned int *pfilled_length; bool wake_up_thread = false; unsigned long flags; struct timeval tv; if (gapp_pid == INVALID_PID) { /* * This is to make sure that we print the logs to kmsg console * when no logger app is running. This is also needed to * log the initial messages during loading of driver where even * if app is running it will not be able to * register with driver immediately and start logging all the * messages. */ pr_err("%s\n", to_be_sent); } /* Format the Log time [Secondselapsedinaday.microseconds] */ do_gettimeofday(&tv); tlen = snprintf(tbuf, sizeof(tbuf), "[%s][%5lu.%06lu] ", current->comm, (unsigned long) (tv.tv_sec%SECONDS_IN_A_DAY), tv.tv_usec); /* 1+1 indicate '\n'+'\0' */ total_log_len = length + tlen + 1 + 1; spin_lock_irqsave(&gwlan_logging.spin_lock, flags); // wlan logging svc resources are not yet initialized if (!gwlan_logging.pcur_node) { spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); return -EIO; } pfilled_length = &gwlan_logging.pcur_node->filled_length; /* Check if we can accomodate more log into current node/buffer */ if ((MAX_LOGMSG_LENGTH - (*pfilled_length + sizeof(tAniNlHdr))) < total_log_len) { wake_up_thread = true; wlan_queue_logmsg_for_app(); pfilled_length = &gwlan_logging.pcur_node->filled_length; } ptr = &gwlan_logging.pcur_node->logbuf[sizeof(tAniHdr)]; /* Assumption here is that we receive logs which is always less than * MAX_LOGMSG_LENGTH, where we can accomodate the * tAniNlHdr + [context][timestamp] + log * VOS_ASSERT if we cannot accomodate the the complete log into * the available buffer. * * Continue and copy logs to the available length and discard the rest. */ if (MAX_LOGMSG_LENGTH < (sizeof(tAniNlHdr) + total_log_len)) { VOS_ASSERT(0); total_log_len = MAX_LOGMSG_LENGTH - sizeof(tAniNlHdr) - 2; } vos_mem_copy(&ptr[*pfilled_length], tbuf, tlen); vos_mem_copy(&ptr[*pfilled_length + tlen], to_be_sent, min(length, (total_log_len - tlen))); *pfilled_length += tlen + min(length, total_log_len - tlen); ptr[*pfilled_length] = '\n'; *pfilled_length += 1; spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); /* Wakeup logger thread */ if ((true == wake_up_thread)) { /* If there is logger app registered wakeup the logging * thread Else broadcast a Ready Indication message, * apps which are waiting on this message can * register for the logs. */ if ( (gapp_pid != INVALID_PID)) { wake_up_interruptible(&gwlan_logging.wait_queue); } else { wlan_logging_srv_nl_ready_indication(); } } if ((gapp_pid != INVALID_PID) && gwlan_logging.log_fe_to_console && ((VOS_TRACE_LEVEL_FATAL == log_level) || (VOS_TRACE_LEVEL_ERROR == log_level))) { pr_err("%s\n", to_be_sent); } return 0; }
int wlan_log_to_user(VOS_TRACE_LEVEL log_level, char *to_be_sent, int length) { /* Add the current time stamp */ char *ptr; char tbuf[100]; int tlen; int total_log_len; unsigned int *pfilled_length; bool wake_up_thread = false; unsigned long flags; struct timeval tv; struct rtc_time tm; unsigned long local_time; u64 qtimer_ticks; if (!vos_is_multicast_logging()) { /* * This is to make sure that we print the logs to kmsg console * when no logger app is running. This is also needed to * log the initial messages during loading of driver where even * if app is running it will not be able to * register with driver immediately and start logging all the * messages. */ pr_err("%s\n", to_be_sent); } else { /* Format the Log time [hr:min:sec.microsec] */ do_gettimeofday(&tv); /* Convert rtc to local time */ local_time = (u32)(tv.tv_sec - (sys_tz.tz_minuteswest * 60)); rtc_time_to_tm(local_time, &tm); /* Firmware Time Stamp */ qtimer_ticks = arch_counter_get_cntpct(); tlen = snprintf(tbuf, sizeof(tbuf), "[%02d:%02d:%02d.%06lu] [%016llX]" " [%.5s] ", tm.tm_hour, tm.tm_min, tm.tm_sec, tv.tv_usec, qtimer_ticks, current->comm); /* 1+1 indicate '\n'+'\0' */ total_log_len = length + tlen + 1 + 1; spin_lock_irqsave(&gwlan_logging.spin_lock, flags); // wlan logging svc resources are not yet initialized if (!gwlan_logging.pcur_node) { spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); return -EIO; } pfilled_length = &gwlan_logging.pcur_node->filled_length; /* Check if we can accomodate more log into current node/buffer */ if (MAX_LOGMSG_LENGTH < (*pfilled_length + sizeof(tAniNlHdr) + total_log_len)) { wake_up_thread = true; wlan_queue_logmsg_for_app(); pfilled_length = &gwlan_logging.pcur_node->filled_length; } ptr = &gwlan_logging.pcur_node->logbuf[sizeof(tAniHdr)]; /* Assumption here is that we receive logs which is always less than * MAX_LOGMSG_LENGTH, where we can accomodate the * tAniNlHdr + [context][timestamp] + log * VOS_ASSERT if we cannot accomodate the the complete log into * the available buffer. * * Continue and copy logs to the available length and discard the rest. */ if (MAX_LOGMSG_LENGTH < (sizeof(tAniNlHdr) + total_log_len)) { VOS_ASSERT(0); total_log_len = MAX_LOGMSG_LENGTH - sizeof(tAniNlHdr) - 2; } vos_mem_copy(&ptr[*pfilled_length], tbuf, tlen); vos_mem_copy(&ptr[*pfilled_length + tlen], to_be_sent, min(length, (total_log_len - tlen))); *pfilled_length += tlen + min(length, total_log_len - tlen); ptr[*pfilled_length] = '\n'; *pfilled_length += 1; spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); /* Wakeup logger thread */ if ((true == wake_up_thread)) { /* If there is logger app registered wakeup the logging * thread */ set_bit(HOST_LOG_POST, &gwlan_logging.event_flag); wake_up_interruptible(&gwlan_logging.wait_queue); } if (gwlan_logging.log_fe_to_console && ((VOS_TRACE_LEVEL_FATAL == log_level) || (VOS_TRACE_LEVEL_ERROR == log_level))) { pr_err("%s %s\n",tbuf, to_be_sent); } } return 0; }