ASoC: msm: Use spin lock to protect the shared data

- Two different locks (spin lock and mutex lock) are used
  to protect the shared data, this may cause kernel panic.
- Use spin lock to protect the shared data between interrupt
  function and non-interrupt functions.

CRs-fixed: 375637
Change-Id: I10c93e2ca80d821908b93c22525695d89143825a
Signed-off-by: Helen Zeng <xiaoyunz@codeaurora.org>
diff --git a/sound/soc/msm/msm-pcm-voip.c b/sound/soc/msm/msm-pcm-voip.c
index 570d71c..b18117c 100644
--- a/sound/soc/msm/msm-pcm-voip.c
+++ b/sound/soc/msm/msm-pcm-voip.c
@@ -106,10 +106,9 @@
 	wait_queue_head_t in_wait;
 
 	struct mutex lock;
-	struct mutex in_lock;
-	struct mutex out_lock;
 
 	spinlock_t dsp_lock;
+	spinlock_t dsp_ul_lock;
 
 	uint32_t mode;
 	uint32_t rate_type;
@@ -268,7 +267,7 @@
 		return;
 
 	/* Copy up-link packet into out_queue. */
-	spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
+	spin_lock_irqsave(&prtd->dsp_ul_lock, dsp_flags);
 
 	/* discarding UL packets till start is received */
 	if (!list_empty(&prtd->free_out_queue) && prtd->capture_start) {
@@ -321,10 +320,10 @@
 		pr_debug("ul_pkt: pkt_len =%d, frame.len=%d\n", pkt_len,
 			buf_node->frame.len);
 		prtd->pcm_capture_irq_pos += prtd->pcm_capture_count;
-		spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
+		spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
 		snd_pcm_period_elapsed(prtd->capture_substream);
 	} else {
-		spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
+		spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
 		pr_err("UL data dropped\n");
 	}
 
@@ -516,6 +515,7 @@
 	struct voip_buf_node *buf_node = NULL;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct voip_drv_info *prtd = runtime->private_data;
+	unsigned long dsp_flags;
 
 	int count = frames_to_bytes(runtime, frames);
 	pr_debug("%s: count = %d, frames=%d\n", __func__, count, (int)frames);
@@ -525,8 +525,8 @@
 				prtd->state == VOIP_STOPPED),
 				1 * HZ);
 	if (ret > 0) {
-		mutex_lock(&prtd->in_lock);
 		if (count <= VOIP_MAX_VOC_PKT_SIZE) {
+			spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
 			buf_node =
 				list_first_entry(&prtd->free_in_queue,
 						struct voip_buf_node, list);
@@ -539,13 +539,13 @@
 				ret = copy_from_user(&buf_node->frame,
 							buf, count);
 			list_add_tail(&buf_node->list, &prtd->in_queue);
+			spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
 		} else {
 			pr_err("%s: Write cnt %d is > VOIP_MAX_VOC_PKT_SIZE\n",
 				__func__, count);
 			ret = -ENOMEM;
 		}
 
-		mutex_unlock(&prtd->in_lock);
 	} else if (ret == 0) {
 		pr_err("%s: No free DL buffs\n", __func__);
 		ret = -ETIMEDOUT;
@@ -564,6 +564,7 @@
 	struct voip_buf_node *buf_node = NULL;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct voip_drv_info *prtd = runtime->private_data;
+	unsigned long dsp_flags;
 
 	count = frames_to_bytes(runtime, frames);
 
@@ -575,9 +576,9 @@
 				1 * HZ);
 
 	if (ret > 0) {
-		mutex_lock(&prtd->out_lock);
 
 		if (count <= VOIP_MAX_VOC_PKT_SIZE) {
+			spin_lock_irqsave(&prtd->dsp_ul_lock, dsp_flags);
 			buf_node = list_first_entry(&prtd->out_queue,
 					struct voip_buf_node, list);
 			list_del(&buf_node->list);
@@ -596,13 +597,14 @@
 			}
 			list_add_tail(&buf_node->list,
 						&prtd->free_out_queue);
+			spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
+
 		} else {
 			pr_err("%s: Read count %d > VOIP_MAX_VOC_PKT_SIZE\n",
 				__func__, count);
 			ret = -ENOMEM;
 		}
 
-		mutex_unlock(&prtd->out_lock);
 
 	} else if (ret == 0) {
 		pr_err("%s: No UL data available\n", __func__);
@@ -636,6 +638,7 @@
 	struct snd_pcm_substream *p_substream, *c_substream;
 	struct snd_pcm_runtime *runtime;
 	struct voip_drv_info *prtd;
+	unsigned long dsp_flags;
 
 	if (substream == NULL) {
 		pr_err("substream is NULL\n");
@@ -674,7 +677,7 @@
 			goto capt;
 		}
 		if (p_dma_buf->area != NULL) {
-			mutex_lock(&prtd->in_lock);
+			spin_lock_irqsave(&prtd->dsp_lock, dsp_flags);
 			list_for_each_safe(ptr, next, &prtd->in_queue) {
 				buf_node = list_entry(ptr,
 						struct voip_buf_node, list);
@@ -685,11 +688,11 @@
 						struct voip_buf_node, list);
 				list_del(&buf_node->list);
 			}
+			spin_unlock_irqrestore(&prtd->dsp_lock, dsp_flags);
 			dma_free_coherent(p_substream->pcm->card->dev,
 				runtime->hw.buffer_bytes_max, p_dma_buf->area,
 				p_dma_buf->addr);
 			p_dma_buf->area = NULL;
-			mutex_unlock(&prtd->in_lock);
 		}
 		/* release out_queue and free_out_queue */
 capt:		c_substream = prtd->capture_substream;
@@ -703,7 +706,7 @@
 			goto done;
 		}
 		if (c_dma_buf->area != NULL) {
-			mutex_lock(&prtd->out_lock);
+			spin_lock_irqsave(&prtd->dsp_ul_lock, dsp_flags);
 			list_for_each_safe(ptr, next, &prtd->out_queue) {
 				buf_node = list_entry(ptr,
 						struct voip_buf_node, list);
@@ -714,11 +717,11 @@
 						struct voip_buf_node, list);
 				list_del(&buf_node->list);
 			}
+			spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
 			dma_free_coherent(c_substream->pcm->card->dev,
 				runtime->hw.buffer_bytes_max, c_dma_buf->area,
 				c_dma_buf->addr);
 			c_dma_buf->area = NULL;
-			mutex_unlock(&prtd->out_lock);
 		}
 done:
 		prtd->capture_substream = NULL;
@@ -888,19 +891,15 @@
 		for (i = 0; i < VOIP_MAX_Q_LEN; i++) {
 			buf_node = (void *)dma_buf->area + offset;
 
-			mutex_lock(&voip_info.in_lock);
 			list_add_tail(&buf_node->list,
 					&voip_info.free_in_queue);
-			mutex_unlock(&voip_info.in_lock);
 			offset = offset + sizeof(struct voip_buf_node);
 		}
 	} else {
 		for (i = 0; i < VOIP_MAX_Q_LEN; i++) {
 			buf_node = (void *) dma_buf->area + offset;
-			mutex_lock(&voip_info.out_lock);
 			list_add_tail(&buf_node->list,
 					&voip_info.free_out_queue);
-			mutex_unlock(&voip_info.out_lock);
 			offset = offset + sizeof(struct voip_buf_node);
 		}
 	}
@@ -1142,10 +1141,9 @@
 	memset(&voip_info, 0, sizeof(voip_info));
 	voip_info.mode = MODE_PCM;
 	mutex_init(&voip_info.lock);
-	mutex_init(&voip_info.in_lock);
-	mutex_init(&voip_info.out_lock);
 
 	spin_lock_init(&voip_info.dsp_lock);
+	spin_lock_init(&voip_info.dsp_ul_lock);
 
 	init_waitqueue_head(&voip_info.out_wait);
 	init_waitqueue_head(&voip_info.in_wait);