From 12205b544bc2ceef742bc2dc94440e70960c784c Mon Sep 17 00:00:00 2001 From: Adil Saeed Musthafa Date: Tue, 7 Aug 2018 09:39:20 -0700 Subject: [PATCH] qcacmn: Add timer to flush out log buffers periodically Add timer to flush out log buffers periodically. Add command to set the time period value. Change-Id: I8e796a9bc7caac2661d00852420dd5fa66f5bca5 CRs-Fixed: 2296362 --- qdf/inc/qdf_trace.h | 25 +++++++ qdf/linux/src/qdf_trace.c | 48 +++++++++++++- utils/logging/inc/wlan_logging_sock_svc.h | 13 ++++ utils/logging/src/wlan_logging_sock_svc.c | 80 ++++++++++++++++++++++- 4 files changed, 163 insertions(+), 3 deletions(-) diff --git a/qdf/inc/qdf_trace.h b/qdf/inc/qdf_trace.h index ec4321c81385..8537b26fa2f7 100644 --- a/qdf/inc/qdf_trace.h +++ b/qdf/inc/qdf_trace.h @@ -1238,6 +1238,31 @@ QDF_STATUS qdf_print_set_category_verbose(unsigned int idx, QDF_TRACE_LEVEL verbose, bool is_set); +/** + * qdf_log_dump_at_kernel_level() - Enable/Disable printk call + * @enable: Indicates whether printk is enabled in QDF_TRACE + * + * Return: void + */ +void qdf_log_dump_at_kernel_level(bool enable); + +/** + * qdf_logging_set_flush_timer() - Set the time period in which host logs + * should be flushed out to user-space + * @milliseconds: milliseconds after which the logs should be flushed out to + * user-space + * + * Return: QDF_STATUS_SUCCESS for success and QDF_STATUS_E_FAILURE for failure + */ +int qdf_logging_set_flush_timer(uint32_t milliseconds); + +/** + * qdf_logging_flush_logs() - Flush out the logs to user-space one time + * + * Return: void + */ +void qdf_logging_flush_logs(void); + /** * qdf_print_is_category_enabled() - Get category information for the * print control object diff --git a/qdf/linux/src/qdf_trace.c b/qdf/linux/src/qdf_trace.c index a379d92061a2..3f872a7488d2 100644 --- a/qdf/linux/src/qdf_trace.c +++ b/qdf/linux/src/qdf_trace.c @@ -33,6 +33,12 @@ #include #include static int qdf_pidx = -1; +static bool qdf_log_dump_at_kernel_enable = true; +qdf_declare_param(qdf_log_dump_at_kernel_enable, bool); + +/* This value of 0 will disable the timer by default. */ +static uint32_t qdf_log_flush_timer_period; +qdf_declare_param(qdf_log_flush_timer_period, uint); #include "qdf_time.h" #include "qdf_mc_timer.h" @@ -2959,7 +2965,8 @@ void qdf_trace_msg_cmn(unsigned int idx, #if defined(WLAN_LOGGING_SOCK_SVC_ENABLE) wlan_log_to_user(verbose, (char *)str_buffer, strlen(str_buffer)); - print_to_console(str_buffer); + if (qdf_likely(qdf_log_dump_at_kernel_enable)) + print_to_console(str_buffer); #else pr_err("%s\n", str_buffer); #endif @@ -3393,6 +3400,18 @@ QDF_STATUS qdf_print_set_category_verbose(unsigned int idx, } qdf_export_symbol(qdf_print_set_category_verbose); +void qdf_log_dump_at_kernel_level(bool enable) +{ + if (qdf_log_dump_at_kernel_enable == enable) { + QDF_TRACE_INFO(QDF_MODULE_ID_QDF, + "qdf_log_dump_at_kernel_enable is already %d\n", + enable); + } + qdf_log_dump_at_kernel_enable = enable; +} + +qdf_export_symbol(qdf_log_dump_at_kernel_level); + bool qdf_print_is_category_enabled(unsigned int idx, QDF_MODULE_ID category) { QDF_TRACE_LEVEL verbose_mask; @@ -3556,6 +3575,7 @@ void qdf_logging_init(void) { wlan_logging_sock_init_svc(); nl_srv_init(NULL); + wlan_logging_set_flush_timer(qdf_log_flush_timer_period); } void qdf_logging_exit(void) @@ -3563,6 +3583,20 @@ void qdf_logging_exit(void) nl_srv_exit(); wlan_logging_sock_deinit_svc(); } + +int qdf_logging_set_flush_timer(uint32_t milliseconds) +{ + if (wlan_logging_set_flush_timer(milliseconds) == 0) + return QDF_STATUS_SUCCESS; + else + return QDF_STATUS_E_FAILURE; +} + +void qdf_logging_flush_logs(void) +{ + wlan_flush_host_logs_for_fatal(); +} + #else void qdf_logging_init(void) { @@ -3573,8 +3607,20 @@ void qdf_logging_exit(void) { nl_srv_exit(); } + +int qdf_logging_set_flush_timer(uint32_t milliseconds) +{ + return QDF_STATUS_E_FAILURE; +} + +void qdf_logging_flush_logs(void) +{ +} #endif +qdf_export_symbol(qdf_logging_set_flush_timer); +qdf_export_symbol(qdf_logging_flush_logs); + #ifdef CONFIG_KALLSYMS inline int qdf_sprint_symbol(char *buffer, void *addr) { diff --git a/utils/logging/inc/wlan_logging_sock_svc.h b/utils/logging/inc/wlan_logging_sock_svc.h index bf538a2c6ed3..49e91e4f20d9 100644 --- a/utils/logging/inc/wlan_logging_sock_svc.h +++ b/utils/logging/inc/wlan_logging_sock_svc.h @@ -33,6 +33,19 @@ int wlan_logging_sock_init_svc(void); int wlan_logging_sock_deinit_svc(void); int wlan_log_to_user(QDF_TRACE_LEVEL log_level, char *to_be_sent, int length); +/** + * wlan_logging_set_flush_timer() - Sets the time period for log flush timer + * @milliseconds: Time period in milliseconds + * + * This function sets the time period interval during which the log buffers + * will be flushed out to user space. Setting this interval can set an + * approximate maximum delay after which any message logged through QDF_TRACE + * will appear at user-space + * + * Return: void + */ +int wlan_logging_set_flush_timer(uint32_t milliseconds); + #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE void wlan_logging_set_per_pkt_stats(void); void wlan_logging_set_fw_flush_complete(void); diff --git a/utils/logging/src/wlan_logging_sock_svc.c b/utils/logging/src/wlan_logging_sock_svc.c index 703c2107176c..117dc66a09be 100644 --- a/utils/logging/src/wlan_logging_sock_svc.c +++ b/utils/logging/src/wlan_logging_sock_svc.c @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include #include #include "host_diag_core_log.h" @@ -134,6 +136,7 @@ struct pkt_stats_msg { struct sk_buff *skb; }; +#define MAX_FLUSH_TIMER_PERIOD_VALUE 3600000 /* maximum of 1 hour (in ms) */ struct wlan_logging { /* Log Fatal and ERROR to console */ bool log_to_console; @@ -171,6 +174,10 @@ struct wlan_logging { unsigned int pkt_stat_drop_cnt; spinlock_t pkt_stats_lock; unsigned int pkt_stats_msg_idx; + qdf_timer_t flush_timer; + bool is_flush_timer_initialized; + uint32_t flush_timer_period; + qdf_spinlock_t flush_timer_lock; }; static struct wlan_logging gwlan_logging; @@ -744,6 +751,19 @@ static void send_flush_completion_to_user(uint8_t ring_id) } #endif +static void setup_flush_timer(void) +{ + qdf_spin_lock(&gwlan_logging.flush_timer_lock); + if (!gwlan_logging.is_flush_timer_initialized || + (gwlan_logging.flush_timer_period == 0)) { + qdf_spin_unlock(&gwlan_logging.flush_timer_lock); + return; + } + qdf_timer_mod(&gwlan_logging.flush_timer, + gwlan_logging.flush_timer_period); + qdf_spin_unlock(&gwlan_logging.flush_timer_lock); +} + /** * wlan_logging_thread() - The WLAN Logger thread * @Arg - pointer to the HDD context @@ -757,6 +777,7 @@ static int wlan_logging_thread(void *Arg) unsigned long flags; while (!gwlan_logging.exit) { + setup_flush_timer(); ret_wait_status = wait_event_interruptible(gwlan_logging.wait_queue, (!list_empty @@ -852,11 +873,54 @@ void wlan_logging_set_log_to_console(bool log_to_console) gwlan_logging.log_to_console = log_to_console; } +static void flush_log_buffers_timer(void *dummy) +{ + wlan_flush_host_logs_for_fatal(); +} + +int wlan_logging_set_flush_timer(uint32_t milliseconds) +{ + if (milliseconds > MAX_FLUSH_TIMER_PERIOD_VALUE) { + QDF_TRACE_ERROR(QDF_MODULE_ID_QDF, + "ERROR! value should be (0 - %d)\n", + MAX_FLUSH_TIMER_PERIOD_VALUE); + return -EINVAL; + } + if (!gwlan_logging.is_active) { + QDF_TRACE_ERROR(QDF_MODULE_ID_QDF, + "WLAN-Logging not active"); + return -EINVAL; + } + qdf_spin_lock(&gwlan_logging.flush_timer_lock); + if (!gwlan_logging.is_flush_timer_initialized) { + qdf_spin_unlock(&gwlan_logging.flush_timer_lock); + return -EINVAL; + } + gwlan_logging.flush_timer_period = milliseconds; + if (milliseconds) { + qdf_timer_mod(&gwlan_logging.flush_timer, + gwlan_logging.flush_timer_period); + } + qdf_spin_unlock(&gwlan_logging.flush_timer_lock); + return 0; +} + +static void flush_timer_init(void) +{ + qdf_spinlock_create(&gwlan_logging.flush_timer_lock); + qdf_timer_init(NULL, &gwlan_logging.flush_timer, + flush_log_buffers_timer, NULL, + QDF_TIMER_TYPE_SW); + gwlan_logging.is_flush_timer_initialized = true; + gwlan_logging.flush_timer_period = 0; +} + int wlan_logging_sock_init_svc(void) { int i = 0, j, pkt_stats_size; unsigned long irq_flag; + flush_timer_init(); spin_lock_init(&gwlan_logging.spin_lock); spin_lock_init(&gwlan_logging.pkt_stats_lock); @@ -961,6 +1025,16 @@ err1: return -ENOMEM; } +static void flush_timer_deinit(void) +{ + gwlan_logging.is_flush_timer_initialized = false; + qdf_spin_lock(&gwlan_logging.flush_timer_lock); + qdf_timer_stop(&gwlan_logging.flush_timer); + qdf_timer_free(&gwlan_logging.flush_timer); + qdf_spin_unlock(&gwlan_logging.flush_timer_lock); + qdf_spinlock_destroy(&gwlan_logging.flush_timer_lock); +} + int wlan_logging_sock_deinit_svc(void) { unsigned long irq_flag; @@ -1001,6 +1075,7 @@ int wlan_logging_sock_deinit_svc(void) vfree(gpkt_stats_buffers); gpkt_stats_buffers = NULL; free_log_msg_buffer(); + flush_timer_deinit(); return 0; } @@ -1060,8 +1135,9 @@ void wlan_flush_host_logs_for_fatal(void) #ifdef CONFIG_MCL if (cds_is_log_report_in_progress()) { #endif - pr_info("%s:flush all host logs Setting HOST_LOG_POST_MASK\n", - __func__); + if (gwlan_logging.flush_timer_period == 0) + pr_info("%s:flush all host logs Setting HOST_LOG_POST_MASK\n", + __func__); spin_lock_irqsave(&gwlan_logging.spin_lock, flags); wlan_queue_logmsg_for_app(); spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags);