ASoC: msm8960: Avoid the mutex access from event handler

Because q6asm_write use mutex to protect the shared data, this API
should not be called from event handler. Instead, calling
q6asm_write_nolock interface.

CRs-fixed: 298006
Signed-off-by: Jay Wang <jaywang@codeaurora.org>
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 9c76942..e3507ee 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -186,6 +186,9 @@
 void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac,
 				uint32_t *size, uint32_t *idx);
 
+void *q6asm_is_cpu_buf_avail_nolock(int dir, struct audio_client *ac,
+					uint32_t *size, uint32_t *idx);
+
 int q6asm_is_dsp_buf_avail(int dir, struct audio_client *ac);
 
 /* File format specific configurations to be added below */
diff --git a/sound/soc/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index 5ae11dd..1826a57 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -96,12 +96,12 @@
 			break;
 		if (!prtd->mmap_flag)
 			break;
-		if (q6asm_is_cpu_buf_avail(IN,
+		if (q6asm_is_cpu_buf_avail_nolock(IN,
 				prtd->audio_client,
 				&size, &idx)) {
 			pr_debug("%s:writing %d bytes of buffer to dsp 2\n",
 					__func__, prtd->pcm_count);
-			q6asm_write(prtd->audio_client,
+			q6asm_write_nolock(prtd->audio_client,
 				prtd->pcm_count, 0, 0, NO_TIMESTAMP);
 		}
 		break;
@@ -126,27 +126,26 @@
 			atomic_inc(&prtd->in_count);
 		wake_up(&the_locks.read_wait);
 		if (prtd->mmap_flag
-			&& q6asm_is_cpu_buf_avail(OUT,
+			&& q6asm_is_cpu_buf_avail_nolock(OUT,
 				prtd->audio_client,
 				&size, &idx))
-			q6asm_read(prtd->audio_client);
+			q6asm_read_nolock(prtd->audio_client);
 		break;
 	}
 	case APR_BASIC_RSP_RESULT: {
-		if (!prtd->mmap_flag
-			&& !atomic_read(&prtd->out_needed))
-			break;
 		switch (payload[0]) {
 		case ASM_SESSION_CMD_RUN:
 			if (substream->stream
-				!= SNDRV_PCM_STREAM_PLAYBACK)
+				!= SNDRV_PCM_STREAM_PLAYBACK) {
+				atomic_set(&prtd->start, 1);
 				break;
+			}
 			if (prtd->mmap_flag) {
 				pr_debug("%s:writing %d bytes"
 					" of buffer to dsp\n",
 					__func__,
 					prtd->pcm_count);
-				q6asm_write(prtd->audio_client,
+				q6asm_write_nolock(prtd->audio_client,
 					prtd->pcm_count,
 					0, 0, NO_TIMESTAMP);
 			} else {
@@ -155,13 +154,14 @@
 						 " of buffer to dsp\n",
 						__func__,
 						prtd->pcm_count);
-					q6asm_write(prtd->audio_client,
+					q6asm_write_nolock(prtd->audio_client,
 						prtd->pcm_count,
 						0, 0, NO_TIMESTAMP);
 					atomic_dec(&prtd->out_needed);
 					wake_up(&the_locks.write_wait);
 				};
 			}
+			atomic_set(&prtd->start, 1);
 			break;
 		default:
 			break;
@@ -249,7 +249,6 @@
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
 		pr_debug("%s: Trigger start\n", __func__);
 		q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
-		atomic_set(&prtd->start, 1);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
 		pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 981f252..fddf34f 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -919,6 +919,52 @@
 	return NULL;
 }
 
+void *q6asm_is_cpu_buf_avail_nolock(int dir, struct audio_client *ac,
+					uint32_t *size, uint32_t *index)
+{
+	void *data;
+	unsigned char idx;
+	struct audio_port_data *port;
+
+	if (!ac || ((dir != IN) && (dir != OUT)))
+		return NULL;
+
+	port = &ac->port[dir];
+
+	idx = port->cpu_buf;
+	if (port->buf == NULL) {
+		pr_debug("%s:Buffer pointer null\n", __func__);
+		return NULL;
+	}
+	/*
+	 * dir 0: used = 0 means buf in use
+	 * dir 1: used = 1 means buf in use
+	 */
+	if (port->buf[idx].used == dir) {
+		/*
+		 * To make it more robust, we could loop and get the
+		 * next avail buf, its risky though
+		 */
+		pr_debug("%s:Next buf idx[0x%x] not available,\
+			dir[%d]\n", __func__, idx, dir);
+		return NULL;
+	}
+	*size = port->buf[idx].actual_size;
+	*index = port->cpu_buf;
+	data = port->buf[idx].data;
+	pr_debug("%s:session[%d]index[%d] data[%p]size[%d]\n",
+		__func__, ac->session, port->cpu_buf,
+		data, *size);
+	/*
+	 * By default increase the cpu_buf cnt
+	 * user accesses this function,increase cpu
+	 * buf(to avoid another api)
+	 */
+	port->buf[idx].used = dir;
+	port->cpu_buf = ((port->cpu_buf + 1) & (port->max_buf_cnt - 1));
+	return data;
+}
+
 int q6asm_is_dsp_buf_avail(int dir, struct audio_client *ac)
 {
 	int ret = -1;