msm: ipc_logging: Replace spinlock_t with rwlock_t

Currently with the spinlock, all drivers are serialized(SMD_PKT,
BAM_DMUX etc.) when they try to log into the IPC logging even though the
drivers log into their own context space. The read/write lock will
enable multiple drivers to log into their context space in parallel.
This will help more in the case of drivers which are
performance-critical like BAM_DMUX.

ipc_log_context_list is read often and updated rarely so replace the
usage of spinlock_t with rwlock_t.

Change-Id: I91f18ef67b80edf6f045f93f51ad2f48e46b3bb4
Signed-off-by: Arun Kumar Neelakantam <aneela@codeaurora.org>
diff --git a/arch/arm/mach-msm/ipc_logging.c b/arch/arm/mach-msm/ipc_logging.c
index 1260a1a..280f237 100644
--- a/arch/arm/mach-msm/ipc_logging.c
+++ b/arch/arm/mach-msm/ipc_logging.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -32,7 +32,7 @@
 #include "ipc_logging.h"
 
 static LIST_HEAD(ipc_log_context_list);
-DEFINE_SPINLOCK(ipc_log_context_list_lock);
+DEFINE_RWLOCK(ipc_log_context_list_lock);
 static atomic_t next_log_id = ATOMIC_INIT(0);
 
 static struct ipc_log_page *get_first_page(struct ipc_log_context *ilctxt)
@@ -140,7 +140,7 @@
 		return;
 	}
 
-	spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+	read_lock_irqsave(&ipc_log_context_list_lock, flags);
 	spin_lock(&ilctxt->ipc_log_context_lock);
 	while (ilctxt->write_avail < ectxt->offset)
 		msg_read(ilctxt, NULL);
@@ -165,7 +165,7 @@
 	ilctxt->write_avail -= ectxt->offset;
 	complete(&ilctxt->read_avail);
 	spin_unlock(&ilctxt->ipc_log_context_lock);
-	spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+	read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
 }
 EXPORT_SYMBOL(ipc_log_write);
 
@@ -471,13 +471,13 @@
 	if (!df_info)
 		return -ENOSPC;
 
-	spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+	read_lock_irqsave(&ipc_log_context_list_lock, flags);
 	spin_lock(&ilctxt->ipc_log_context_lock);
 	df_info->type = type;
 	df_info->dfunc = dfunc;
 	list_add_tail(&df_info->list, &ilctxt->dfunc_info_list);
 	spin_unlock(&ilctxt->ipc_log_context_lock);
-	spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+	read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
 	return 0;
 }
 EXPORT_SYMBOL(add_deserialization_func);
@@ -528,9 +528,9 @@
 
 	create_ctx_debugfs(ctxt, mod_name);
 
-	spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+	write_lock_irqsave(&ipc_log_context_list_lock, flags);
 	list_add_tail(&ctxt->list, &ipc_log_context_list);
-	spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+	write_unlock_irqrestore(&ipc_log_context_list_lock, flags);
 	return (void *)ctxt;
 
 release_ipc_log_context:
diff --git a/arch/arm/mach-msm/ipc_logging.h b/arch/arm/mach-msm/ipc_logging.h
index 0eb82a5..36b4171 100644
--- a/arch/arm/mach-msm/ipc_logging.h
+++ b/arch/arm/mach-msm/ipc_logging.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -65,7 +65,7 @@
 #define IS_MSG_TYPE(x) (((x) > TSV_TYPE_MSG_START) && \
 			((x) < TSV_TYPE_MSG_END))
 
-extern spinlock_t ipc_log_context_list_lock;
+extern rwlock_t ipc_log_context_list_lock;
 
 extern int msg_read(struct ipc_log_context *ilctxt,
 		    struct encode_context *ectxt);
diff --git a/arch/arm/mach-msm/ipc_logging_debug.c b/arch/arm/mach-msm/ipc_logging_debug.c
index ff947ef..246fb99 100644
--- a/arch/arm/mach-msm/ipc_logging_debug.c
+++ b/arch/arm/mach-msm/ipc_logging_debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -62,7 +62,7 @@
 	dctxt.output_format = OUTPUT_DEBUGFS;
 	dctxt.buff = buff;
 	dctxt.size = size;
-	spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+	read_lock_irqsave(&ipc_log_context_list_lock, flags);
 	spin_lock(&ilctxt->ipc_log_context_lock);
 	while (dctxt.size >= MAX_MSG_DECODED_SIZE &&
 	       !is_ilctxt_empty(ilctxt)) {
@@ -70,19 +70,19 @@
 		deserialize_func = get_deserialization_func(ilctxt,
 							ectxt.hdr.type);
 		spin_unlock(&ilctxt->ipc_log_context_lock);
-		spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+		read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
 		if (deserialize_func)
 			deserialize_func(&ectxt, &dctxt);
 		else
 			pr_err("%s: unknown message 0x%x\n",
 				__func__, ectxt.hdr.type);
-		spin_lock_irqsave(&ipc_log_context_list_lock, flags);
+		read_lock_irqsave(&ipc_log_context_list_lock, flags);
 		spin_lock(&ilctxt->ipc_log_context_lock);
 	}
 	if ((size - dctxt.size) == 0)
 		init_completion(&ilctxt->read_avail);
 	spin_unlock(&ilctxt->ipc_log_context_lock);
-	spin_unlock_irqrestore(&ipc_log_context_list_lock, flags);
+	read_unlock_irqrestore(&ipc_log_context_list_lock, flags);
 	return size - dctxt.size;
 }