Revert "bcmdhd_88: improve data integrity of nv_logger"
Bibhay Ranjan [Wed, 4 Jan 2017 06:58:04 +0000 (11:58 +0530)]
This reverts commit 49308708221379d6749b0f596b1e0f1011a29d0c.

Bug 200231321

Change-Id: Ia51bdc77ae5c86b888a3ecabaf22d296473ae30f
Signed-off-by: Bibhay Ranjan <bibhayr@nvidia.com>
Reviewed-on: http://git-master/r/1279946
Reviewed-by: Dhiren Parmar <dparmar@nvidia.com>
Tested-by: Dhiren Parmar <dparmar@nvidia.com>

drivers/net/wireless/bcmdhd_88/nv_logger.c
drivers/net/wireless/bcmdhd_88/nv_logger.h

index e353a3a..9360a24 100644 (file)
@@ -25,7 +25,9 @@ char nv_error_buffer[MAX_ERROR_SIZE];
 bool enable_file_logging;
 struct list_head list1;
 struct list_head list2;
-bool select_list;
+static int reset_log_size;
+struct mutex sysfs_dump_mtx;
+struct mutex suspend_lock;
 
 struct workqueue_struct *logger_wqueue;
 struct log_buffer {
@@ -33,7 +35,6 @@ struct log_buffer {
        char *buf;
        char *info;
        int event;
-       int size;
 };
 
 struct log_node {
@@ -60,9 +61,12 @@ void write_log_init()
        if (dhdlog_sysfs_init())
                goto netlink_fail;
 
+       mutex_init(&sysfs_dump_mtx);
+       mutex_init(&suspend_lock);
+
        dhd_log_netlink_send_msg(0, 0, 0, NULL, 0);
        enable_file_logging = true;
-       select_list = true;
+
        return;
 
 netlink_fail:
@@ -89,17 +93,30 @@ int write_log(int event, const char *buf, const char *info)
        int info_len = 0;
        int time_len = 0;
        struct timespec ts;
+       static int list1_size;
+       static int list2_size;
        struct timeval now;
        struct tm date_time;
-       static int count = 0;
 
+       mutex_lock(&suspend_lock);
        if (!enable_file_logging) {
+               mutex_unlock(&suspend_lock);
                return -1;
        }
+       mutex_unlock(&suspend_lock);
 
        if (buf == NULL)
                return -1;
 
+       if (mutex_trylock(&sysfs_dump_mtx)) {
+               if (1 == reset_log_size) {
+                       reset_log_size = 0;
+                       list1_size = 0;
+                       list2_size = 0;
+               }
+               mutex_unlock(&sysfs_dump_mtx);
+       }
+
        switch (event) {
 
        case WLC_E_ESCAN_RESULT:
@@ -149,31 +166,30 @@ int write_log(int event, const char *buf, const char *info)
                        temp->log->info = NULL;
                }
                temp->log->event = event;
-               temp->log->size = time_len + buf_len + info_len;
-               /* whichever list is not busy, dump data in that list.
-                  Make sure we fill the last active list with MAX_LOG_NUM
-                  before switching the lists
-               */
-               if (select_list && (1 == atomic_read(&list1_val))) {
-                       count++;
+
+       /* whichever list is not busy, dump data in that list */
+               if (1 == atomic_read(&list1_val)) {
                        list_add_tail(&(temp->list), &(list1));
-               } else if (!select_list && (1 == atomic_read(&list2_val))) {
-                       count++;
+                       list1_size += time_len + buf_len + info_len;
+               } else if (1 == atomic_read(&list2_val)) {
                        list_add_tail(&(temp->list), &(list2));
+                       list2_size += time_len + buf_len + info_len;
                } else {
                /* send data directly over netlink because both lists are busy*/
                        pr_err("Message dropped due to busy queues");
                }
 
-               if (count == MAX_LOG_NUM) {
-                       count = 0;
-                       if (select_list)
-                               atomic_set(&list1_val, 0);
-                       else
-                               atomic_set(&list2_val, 0);
+               if (list1_size > MAX_LOGLIMIT) {
+                       atomic_set(&list1_val, 0);
+                       queue_work(logger_wqueue, &enqueue_work);
+                       list1_size = 0;
+               } else if (list2_size > MAX_LOGLIMIT) {
+                       atomic_set(&list2_val, 0);
                        queue_work(logger_wqueue, &enqueue_work);
-                       select_list = (select_list == false);
+                       list2_size = 0;
                }
+
+               break;
        }
        return buf_len + info_len;
 }
@@ -183,42 +199,29 @@ void write_queue_work(struct work_struct *work)
        struct log_node *temp = NULL;
        struct list_head *pos = NULL, *n = NULL;
        char *log = NULL;
-       int list1_size = 0;
-       int list2_size = 0;
-
-       /* iterate over the listi until list_for_each_safe empties the list.
-          The list is empty is deduced if pos == head, where for eg &(list1)
-          is the head for list1.
-       */
 
        /* queuing in list1 is blocked, so can dequeue list1*/
        if (atomic_read(&list1_val) == 0) {
-               while (pos != &list1) {
-                       list_for_each_safe(pos, n, &(list1)) {
-                               if (list1_size > MAX_LOGLIMIT)
-                                       break;
-                               temp = list_entry(pos, struct log_node, list);
-                               /* for the correct string of the event */
-                               strcat(logbuf, temp->log->tmstmp);
-
-                               if (temp->log->buf != NULL)
-                                       strcat(logbuf, temp->log->buf);
-                               strcat(logbuf, " ");
-                               if (temp->log->info != NULL)
-                                       strcat(logbuf, temp->log->info);
-                               strcat(logbuf, "\n");
-                               list1_size += temp->log->size;
-
-                               list_del(pos);
-                               kfree(temp->log->info);
-                               kfree(temp->log->buf);
-                               kfree(temp->log);
-                               kfree(temp);
-                       }
-                       write_log_file(logbuf);
-                       memset(logbuf, '\0', sizeof(logbuf));
-                       list1_size = 0;
+
+               list_for_each_safe(pos, n, &(list1)) {
+                       temp = list_entry(pos, struct log_node, list);
+               /* for the correct string of the event */
+                       strcat(logbuf, temp->log->tmstmp);
+
+                       if (temp->log->buf != NULL)
+                               strcat(logbuf, temp->log->buf);
+                       strcat(logbuf, " ");
+                       if (temp->log->info != NULL)
+                               strcat(logbuf, temp->log->info);
+                       strcat(logbuf, "\n");
+                       list_del(pos);
+                       kfree(temp->log->info);
+                       kfree(temp->log->buf);
+                       kfree(temp->log);
+                       kfree(temp);
                }
+               write_log_file(logbuf);
+               memset(logbuf, '\0', sizeof(logbuf));
                /* make this list available for writing now */
                atomic_set(&list1_val, 1);
 
@@ -226,32 +229,27 @@ void write_queue_work(struct work_struct *work)
 
        /* queuing in list1 is blocked, so can dequeue list1*/
        if (atomic_read(&list2_val) == 0) {
-               while (pos != &list2) {
-                       list_for_each_safe(pos, n, &(list2)) {
-                               if (list1_size > MAX_LOGLIMIT)
-                                       break;
-                               temp = list_entry(pos, struct log_node, list);
-                       /* for the correct string of the event */
-                               strcat(logbuf, temp->log->tmstmp);
-
-                               if (temp->log->buf != NULL)
-                                       strcat(logbuf, temp->log->buf);
-                               strcat(logbuf, " ");
-                               if (temp->log->info != NULL)
-                                       strcat(logbuf, temp->log->info);
-                               strcat(logbuf, "\n");
-                               list2_size += temp->log->size;
-
-                               list_del(pos);
-                               kfree(temp->log->info);
-                               kfree(temp->log->buf);
-                               kfree(temp->log);
-                               kfree(temp);
-                       }
-                       write_log_file(logbuf);
-                       memset(logbuf, '\0', sizeof(logbuf));
-                       list2_size = 0;
+
+               list_for_each_safe(pos, n, &(list2)) {
+                       temp = list_entry(pos, struct log_node, list);
+               /* for the correct string of the event */
+                       strcat(logbuf, temp->log->tmstmp);
+
+                       if (temp->log->buf != NULL)
+                               strcat(logbuf, temp->log->buf);
+                       strcat(logbuf, " ");
+                       if (temp->log->info != NULL)
+                               strcat(logbuf, temp->log->info);
+                       strcat(logbuf, "\n");
+
+                       list_del(pos);
+                       kfree(temp->log->info);
+                       kfree(temp->log->buf);
+                       kfree(temp->log);
+                       kfree(temp);
                }
+               write_log_file(logbuf);
+               memset(logbuf, '\0', sizeof(logbuf));
                /* make this list available for writing now */
                atomic_set(&list2_val, 1);
        }
@@ -268,7 +266,9 @@ void write_log_file(const char *log)
 
 void nvlogger_suspend_work()
 {
+       mutex_lock(&suspend_lock);
        enable_file_logging = false;
+       mutex_unlock(&suspend_lock);
        pr_info("nvlogger_suspend_work\n");
        cancel_work_sync(&enqueue_work);
 }
@@ -276,7 +276,9 @@ void nvlogger_suspend_work()
 void nvlogger_resume_work()
 {
        pr_info("nvlogger_resume_work\n");
+       mutex_lock(&suspend_lock);
        enable_file_logging = true;
+       mutex_unlock(&suspend_lock);
 }
 
 #define NETLINK_CARBON     29
@@ -369,6 +371,9 @@ void dumplogs()
        atomic_set(&list1_val, 0);
        atomic_set(&list2_val, 0);
        queue_work(logger_wqueue, &enqueue_work);
+       mutex_lock(&sysfs_dump_mtx);
+       reset_log_size = 1;
+       mutex_unlock(&sysfs_dump_mtx);
 }
 
 struct kobject *dhdlog_sysfs_kobj;
@@ -381,12 +386,16 @@ static ssize_t dhdlog_sysfs_enablelog_store(struct kobject *kobj,
        pr_info("dhdlog_sysfs_enablelog_store = %s", buf);
        if (strncmp(buf, "0", 1) == 0 || strncmp(buf, "false", 5) == 0
                || strncmp(buf, "no", 2) == 0) {
+               mutex_lock(&suspend_lock);
                enable_file_logging = false;
+               mutex_unlock(&suspend_lock);
        } else if (strncmp(buf, "dump", 4) == 0) {
                dumplogs();
        } else if (strncmp(buf, "1", 1) == 0 || strncmp(buf, "true", 4) == 0
                || strncmp(buf, "yes", 3) == 0) {
+               mutex_lock(&suspend_lock);
                enable_file_logging = true;
+               mutex_unlock(&suspend_lock);
        }
 
        return count;
index 86d767a..056812d 100644 (file)
@@ -35,7 +35,6 @@
 #define MAX_LOGLIMIT 1024
 #define TIMESTAMPSIZE 40
 #define MAX_ERROR_SIZE 512
-#define MAX_LOG_NUM 20
 #define nv_sprintf(fmt, args...) \
 do { \
        snprintf(nv_error_buffer, MAX_ERROR_SIZE-1, fmt , ## args); \