aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2014-04-28 17:05:17 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2014-04-28 17:05:16 -0700
commit940e3eee0098da57ac748ce325f0989c29a663cd (patch)
treed4e999abc01b2f155c411497974c9670c686a120
parentda83135574239d4fab3712610c01b594317d6db0 (diff)
parent88db73d0645c64aa1aff54fe98cb56a3bd14d784 (diff)
Merge "ASoC: msm: qdsp6v2: Do not free memory that has not been unmapped from DSP"
-rw-r--r--include/sound/q6asm-v2.h1
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c49
2 files changed, 45 insertions, 5 deletions
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 7bb2f2423d5..67298e2cb57 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -181,6 +181,7 @@ struct audio_client {
int stream_id;
/* audio cache operations fptr*/
int (*fptr_cache_ops)(struct audio_buffer *abuff, int cache_op);
+ atomic_t unmap_cb_success;
};
void q6asm_audio_client_free(struct audio_client *ac);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index d49dcc76ced..a28107d483a 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -672,8 +672,11 @@ int q6asm_audio_client_buf_free(unsigned int dir,
while (cnt >= 0) {
if (port->buf[cnt].data) {
- msm_audio_ion_free(port->buf[cnt].client,
- port->buf[cnt].handle);
+ if (!rc)
+ msm_audio_ion_free(
+ port->buf[cnt].client,
+ port->buf[cnt].handle);
+
port->buf[cnt].client = NULL;
port->buf[cnt].handle = NULL;
port->buf[cnt].data = NULL;
@@ -719,7 +722,9 @@ int q6asm_audio_client_buf_free_contiguous(unsigned int dir,
(void *)&port->buf[0].phys,
(void *)port->buf[0].client,
(void *)port->buf[0].handle);
- msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
+ if (!rc)
+ msm_audio_ion_free(port->buf[0].client,
+ port->buf[0].handle);
port->buf[0].client = NULL;
port->buf[0].handle = NULL;
}
@@ -1167,6 +1172,13 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
if (payload[1] != 0) {
pr_err("%s: cmd = 0x%x returned error = 0x%x sid:%d\n",
__func__, payload[0], payload[1], sid);
+ if (payload[0] ==
+ ASM_CMD_SHARED_MEM_UNMAP_REGIONS)
+ atomic_set(&ac->unmap_cb_success, 0);
+ } else {
+ if (payload[0] ==
+ ASM_CMD_SHARED_MEM_UNMAP_REGIONS)
+ atomic_set(&ac->unmap_cb_success, 1);
}
if (atomic_read(&ac->cmd_state)) {
@@ -3189,6 +3201,7 @@ int q6asm_memory_unmap(struct audio_client *ac, phys_addr_t buf_add, int dir)
TRUE, ((ac->session << 8) | dir));
atomic_set(&ac->cmd_state, 1);
mem_unmap.hdr.opcode = ASM_CMD_SHARED_MEM_UNMAP_REGIONS;
+ mem_unmap.mem_map_handle = 0;
list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
buf_node = list_entry(ptr, struct asm_buffer_node,
list);
@@ -3200,6 +3213,12 @@ int q6asm_memory_unmap(struct audio_client *ac, phys_addr_t buf_add, int dir)
}
pr_debug("%s: mem_unmap-mem_map_handle: 0x%x",
__func__, mem_unmap.mem_map_handle);
+
+ if (mem_unmap.mem_map_handle == 0) {
+ pr_err("%s Do not send null mem handle to DSP\n", __func__);
+ rc = 0;
+ goto fail_cmd;
+ }
rc = apr_send_pkt(ac->mmap_apr, (uint32_t *) &mem_unmap);
if (rc < 0) {
pr_err("mem_unmap op[0x%x]rc[%d]\n",
@@ -3211,7 +3230,13 @@ int q6asm_memory_unmap(struct audio_client *ac, phys_addr_t buf_add, int dir)
rc = wait_event_timeout(ac->cmd_wait,
(atomic_read(&ac->cmd_state) == 0), 5 * HZ);
if (!rc) {
- pr_err("timeout. waited for memory_unmap\n");
+ pr_err("%s timeout. waited for memory_unmap of handle 0x%x\n",
+ __func__, mem_unmap.mem_map_handle);
+ rc = -ETIMEDOUT;
+ goto fail_cmd;
+ } else if (atomic_read(&ac->unmap_cb_success) == 0) {
+ pr_err("%s Error in mem unmap callback of handle 0x%x\n",
+ __func__, mem_unmap.mem_map_handle);
rc = -EINVAL;
goto fail_cmd;
}
@@ -3370,6 +3395,7 @@ static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir)
port = &ac->port[dir];
buf_add = (uint32_t)port->buf->phys;
mem_unmap.hdr.opcode = ASM_CMD_SHARED_MEM_UNMAP_REGIONS;
+ mem_unmap.mem_map_handle = 0;
list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
buf_node = list_entry(ptr, struct asm_buffer_node,
list);
@@ -3382,6 +3408,12 @@ static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir)
pr_debug("%s: mem_unmap-mem_map_handle: 0x%x",
__func__, mem_unmap.mem_map_handle);
+
+ if (mem_unmap.mem_map_handle == 0) {
+ pr_err("%s Do not send null mem handle to DSP\n", __func__);
+ rc = 0;
+ goto fail_cmd;
+ }
rc = apr_send_pkt(ac->mmap_apr, (uint32_t *) &mem_unmap);
if (rc < 0) {
pr_err("mmap_regions op[0x%x]rc[%d]\n",
@@ -3392,7 +3424,14 @@ static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir)
rc = wait_event_timeout(ac->cmd_wait,
(atomic_read(&ac->cmd_state) == 0), 5*HZ);
if (!rc) {
- pr_err("timeout. waited for memory_unmap\n");
+ pr_err("%s timeout. waited for memory_unmap of handle 0x%x\n",
+ __func__, mem_unmap.mem_map_handle);
+ rc = -ETIMEDOUT;
+ goto fail_cmd;
+ } else if (atomic_read(&ac->unmap_cb_success) == 0) {
+ pr_err("%s Error in mem unmap callback of handle 0x%x\n",
+ __func__, mem_unmap.mem_map_handle);
+ rc = -EINVAL;
goto fail_cmd;
}
rc = 0;