ASoC: msm: Release ocmem in cases of map/unmap failure

Release ocmem when ocmem_map or ocmem_unmap returned
failure due to mapping misaligned ocmem chunks.

Change-Id: Idbde98ed5e1943a10572d4105e3dff8286cab4be
Signed-off-by: Phani Kumar Uppalapati <phaniu@codeaurora.org>
diff --git a/sound/soc/msm/qdsp6v2/audio_ocmem.c b/sound/soc/msm/qdsp6v2/audio_ocmem.c
index 08d7277..bedaba0 100644
--- a/sound/soc/msm/qdsp6v2/audio_ocmem.c
+++ b/sound/soc/msm/qdsp6v2/audio_ocmem.c
@@ -243,7 +243,7 @@
 	struct ocmem_buf *buf = NULL;
 	struct avcs_cmd_rsp_get_low_power_segments_info_t *lp_segptr;
 
-	pr_debug("%s\n", __func__);
+	pr_debug("%s, %p\n", __func__, &audio_ocmem_lcl);
 	atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_DEFAULT);
 	if (audio_ocmem_lcl.lp_memseg_ptr == NULL) {
 		/* Retrieve low power segments */
@@ -329,6 +329,7 @@
 	if (ret) {
 		pr_err("%s: ocmem_map failed\n", __func__);
 		atomic_set(&audio_ocmem_lcl.audio_state, OCMEM_STATE_MAP_FAIL);
+		goto fail_cmd1;
 	}
 
 	wait_event_interruptible(audio_ocmem_lcl.audio_wait,
@@ -372,7 +373,7 @@
 				pr_err("%s: ocmem_unmap failed, state[%d]\n",
 				__func__,
 				atomic_read(&audio_ocmem_lcl.audio_state));
-				goto fail_cmd;
+				goto fail_cmd1;
 			}
 
 			wait_event_interruptible(audio_ocmem_lcl.audio_wait,
@@ -384,7 +385,7 @@
 				pr_err("%s: ocmem_shrink failed, state[%d]\n",
 				__func__,
 				atomic_read(&audio_ocmem_lcl.audio_state));
-				goto fail_cmd;
+				goto fail_cmd1;
 			}
 			atomic_set(&audio_ocmem_lcl.audio_cond, 1);
 			clear_bit_pos(audio_ocmem_lcl.audio_state,
@@ -405,7 +406,7 @@
 				pr_err("%s: ocmem_map failed, state[%d]\n",
 				__func__,
 				atomic_read(&audio_ocmem_lcl.audio_state));
-				goto fail_cmd;
+				goto fail_cmd1;
 			}
 			wait_event_interruptible(audio_ocmem_lcl.audio_wait,
 				(atomic_read(&audio_ocmem_lcl.audio_state) &
@@ -428,7 +429,7 @@
 					pr_err("%s: ocmem_unmap failed, state[0x%x]\n",
 					__func__,
 				atomic_read(&audio_ocmem_lcl.audio_state));
-					goto fail_cmd;
+					goto fail_cmd1;
 				}
 				wait_event_interruptible(
 				audio_ocmem_lcl.audio_wait,
@@ -446,14 +447,16 @@
 					pr_err("%s: ocmem_shrink failed, state[0x%x]\n",
 						__func__,
 				atomic_read(&audio_ocmem_lcl.audio_state));
-					goto fail_cmd;
+					goto fail_cmd1;
 				}
 				clear_bit_pos(audio_ocmem_lcl.audio_state,
 						OCMEM_STATE_SHRINK);
 
 			}
 
-			pr_debug("%s: calling ocmem free\n", __func__);
+			pr_debug("%s: calling ocmem free, state:0x%x\n",
+				__func__,
+				atomic_read(&audio_ocmem_lcl.audio_state));
 			ret = ocmem_free(OCMEM_LP_AUDIO, audio_ocmem_lcl.buf);
 			if (ret == -EAGAIN) {
 				pr_debug("%s: received EAGAIN\n", __func__);
@@ -466,7 +469,7 @@
 						pr_err("%s: ocmem_shrink failed, state[0x%x]\n",
 							__func__,
 				atomic_read(&audio_ocmem_lcl.audio_state));
-							goto fail_cmd;
+							goto fail_cmd1;
 					}
 					pr_debug("calling free after EAGAIN");
 					ret = ocmem_free(OCMEM_LP_AUDIO,
@@ -474,19 +477,19 @@
 					if (ret) {
 						pr_err("%s: ocmem_free failed\n",
 								__func__);
-						goto fail_cmd;
+						goto fail_cmd2;
 					}
 				} else {
 					pr_debug("%s: shrink callback already processed\n",
 								__func__);
-					goto fail_cmd;
+					goto fail_cmd1;
 				}
 			} else if (ret) {
 				pr_err("%s: ocmem_free failed, state[0x%x], ret:%d\n",
 					__func__,
 				atomic_read(&audio_ocmem_lcl.audio_state),
 				ret);
-				goto fail_cmd;
+				goto fail_cmd2;
 			}
 			pr_debug("%s: ocmem_free success\n", __func__);
 		/* Fall through */
@@ -508,6 +511,14 @@
 		mutex_unlock(&audio_ocmem_lcl.state_process_lock);
 	}
 	ret = 0;
+	goto fail_cmd;
+
+fail_cmd1:
+	ret = ocmem_free(OCMEM_LP_AUDIO, audio_ocmem_lcl.buf);
+	if (ret)
+		pr_err("%s: ocmem_free failed\n", __func__);
+fail_cmd2:
+	mutex_unlock(&audio_ocmem_lcl.state_process_lock);
 fail_cmd:
 	pr_debug("%s: exit\n", __func__);
 	audio_ocmem_lcl.audio_ocmem_running = false;
diff --git a/sound/soc/msm/qdsp6v2/q6core.c b/sound/soc/msm/qdsp6v2/q6core.c
index 42cbcd1..5fec0c1 100644
--- a/sound/soc/msm/qdsp6v2/q6core.c
+++ b/sound/soc/msm/qdsp6v2/q6core.c
@@ -29,7 +29,7 @@
 	struct apr_svc *core_handle_q;
 	wait_queue_head_t bus_bw_req_wait;
 	u32 bus_bw_resp_received;
-	struct avcs_cmd_rsp_get_low_power_segments_info_t *lp_ocm_payload;
+	struct avcs_cmd_rsp_get_low_power_segments_info_t lp_ocm_payload;
 };
 
 static struct q6core_str q6core_lcl;
@@ -74,19 +74,19 @@
 		pr_info("%s: cmd = AVCS_CMDRSP_GET_LOW_POWER_SEGMENTS_INFO num_segments = 0x%x\n",
 					__func__, payload1[0]);
 		nseg = payload1[0];
-		q6core_lcl.lp_ocm_payload->num_segments = nseg;
-		q6core_lcl.lp_ocm_payload->bandwidth = payload1[1];
+		q6core_lcl.lp_ocm_payload.num_segments = nseg;
+		q6core_lcl.lp_ocm_payload.bandwidth = payload1[1];
 		for (i = 0, j = 2; i < nseg; i++) {
-			q6core_lcl.lp_ocm_payload->mem_segment[i].type =
+			q6core_lcl.lp_ocm_payload.mem_segment[i].type =
 					(payload1[j] & 0xffff);
-			q6core_lcl.lp_ocm_payload->mem_segment[i].category =
+			q6core_lcl.lp_ocm_payload.mem_segment[i].category =
 					((payload1[j++] >> 16) & 0xffff);
-			q6core_lcl.lp_ocm_payload->mem_segment[i].size =
+			q6core_lcl.lp_ocm_payload.mem_segment[i].size =
 					payload1[j++];
-			q6core_lcl.lp_ocm_payload->
+			q6core_lcl.lp_ocm_payload.
 				mem_segment[i].start_address_lsw =
 				payload1[j++];
-			q6core_lcl.lp_ocm_payload->
+			q6core_lcl.lp_ocm_payload.
 				mem_segment[i].start_address_msw =
 				payload1[j++];
 		}
@@ -152,7 +152,6 @@
 		struct avcs_cmd_rsp_get_low_power_segments_info_t **lp_memseg)
 {
 	struct avcs_cmd_get_low_power_segments_info lp_ocm_cmd;
-	u8 *cptr = NULL;
 	int ret = 0;
 
 	pr_debug("%s: ", __func__);
@@ -163,16 +162,6 @@
 		return -ENODEV;
 	}
 
-	cptr = kzalloc(
-		sizeof(struct avcs_cmd_rsp_get_low_power_segments_info_t),
-		GFP_KERNEL);
-	if (!cptr) {
-		pr_err("%s: Failed to allocate memory for low power segment struct\n",
-				__func__);
-		return -ENOMEM;
-	}
-	q6core_lcl.lp_ocm_payload =
-		(struct avcs_cmd_rsp_get_low_power_segments_info_t *) cptr;
 
 	lp_ocm_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
@@ -201,7 +190,7 @@
 		goto fail_cmd;
 	}
 
-	*lp_memseg = q6core_lcl.lp_ocm_payload;
+	*lp_memseg = &q6core_lcl.lp_ocm_payload;
 	return 0;
 
 fail_cmd:
@@ -215,14 +204,6 @@
 	q6core_lcl.bus_bw_resp_received = 0;
 
 	q6core_lcl.core_handle_q = NULL;
-	q6core_lcl.lp_ocm_payload = kzalloc(
-	sizeof(struct avcs_cmd_rsp_get_low_power_segments_info_t), GFP_KERNEL);
-
-	if (!q6core_lcl.lp_ocm_payload) {
-		pr_err("%s: Failed to allocate memory for low power segment struct\n",
-				__func__);
-		return -ENOMEM;
-	}
 
 	return 0;
 }
@@ -230,7 +211,7 @@
 
 static void __exit core_exit(void)
 {
-	kfree(q6core_lcl.lp_ocm_payload);
+
 }
 module_exit(core_exit);
 MODULE_DESCRIPTION("ADSP core driver");