ASoC: msm: qdsp6: Add error check for memory commands
- Write failures observed during audio playback.
- Error checks are missing for memory map and memory unmap cmds,
we are proceeding to write data even if memory map is failed. Due
to this pcm_out_write failures are observed.
- Add proper error handling for memory map and unmap cmds.
CRs-Fixed: 485051
Change-Id: Iedd369fcd655b02a213277e973059612c040fe34
Signed-off-by: Deepa Madiregama <dmadireg@codeaurora.org>
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 512127c..f566d83 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -492,6 +492,7 @@
struct audio_buffer *buf;
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
int len;
+ unsigned int bufsz_4k_aligned;
#endif
if (!(ac) || ((dir != IN) && (dir != OUT)))
@@ -532,8 +533,15 @@
mutex_unlock(&ac->cmd_lock);
goto fail;
}
+ bufsz_4k_aligned = (bufsz + 4095) &
+ (~4095);
+ pr_debug("%s: bufsz_4k_aligned %d"\
+ "bufsz = %d\n",
+ __func__, bufsz_4k_aligned,
+ bufsz);
buf[cnt].handle = ion_alloc
- (buf[cnt].client, bufsz, SZ_4K,
+ (buf[cnt].client,
+ bufsz_4k_aligned, SZ_4K,
(0x1 << ION_AUDIO_HEAP_ID), 0);
if (IS_ERR_OR_NULL((void *)
buf[cnt].handle)) {
@@ -763,6 +771,7 @@
{
uint32_t token;
uint32_t *payload = data->payload;
+ struct audio_client *ac;
if (data->opcode == RESET_EVENTS) {
pr_debug("%s: Reset event is received: %d %d apr[%p]\n",
@@ -782,6 +791,8 @@
if (data->opcode == APR_BASIC_RSP_RESULT) {
token = data->token;
+ ac = (struct audio_client *)data->token;
+ pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
switch (payload[0]) {
case ASM_SESSION_CMD_MEMORY_MAP:
case ASM_SESSION_CMD_MEMORY_UNMAP:
@@ -789,9 +800,15 @@
case ASM_SESSION_CMD_MEMORY_UNMAP_REGIONS:
pr_debug("%s:command[0x%x]success [0x%x]\n",
__func__, payload[0], payload[1]);
- if (atomic_read(&this_mmap.cmd_state)) {
- atomic_set(&this_mmap.cmd_state, 0);
- wake_up(&this_mmap.cmd_wait);
+ if (atomic_read(&ac->cmd_state)) {
+ atomic_set(&ac->cmd_state, 0);
+ if (payload[1] != ADSP_EOK) {
+ pr_err("payload[1]:%d error case\n",
+ payload[1]);
+ atomic_set(&ac->cmd_response, 1);
+ } else
+ atomic_set(&ac->cmd_response, 0);
+ wake_up(&ac->cmd_wait);
}
break;
default:
@@ -1227,14 +1244,16 @@
static void q6asm_add_mmaphdr(struct apr_hdr *hdr, uint32_t pkt_size,
uint32_t cmd_flg)
{
+ struct audio_client *ac;
pr_debug("%s:pkt size=%d cmd_flg=%d\n", __func__, pkt_size, cmd_flg);
+ ac = (struct audio_client *)hdr->token;
+ pr_debug("%s: audio_client = %x\n", __func__, (uint32_t)ac);
hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
hdr->src_port = 0;
hdr->dest_port = 0;
if (cmd_flg) {
- hdr->token = 0;
- atomic_set(&this_mmap.cmd_state, 1);
+ atomic_set(&ac->cmd_state, 1);
}
hdr->pkt_size = pkt_size;
return;
@@ -2810,6 +2829,8 @@
mem_map.mempool_id = 0; /* EBI */
mem_map.reserved = 0;
+ pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
+ mem_map.hdr.token = (uint32_t)ac;
q6asm_add_mmaphdr(&mem_map.hdr,
sizeof(struct asm_stream_cmd_memory_map), TRUE);
@@ -2824,14 +2845,20 @@
goto fail_cmd;
}
- rc = wait_event_timeout(this_mmap.cmd_wait,
- (atomic_read(&this_mmap.cmd_state) == 0), 5 * HZ);
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
if (!rc) {
pr_err("timeout. waited for memory_map\n");
rc = -EINVAL;
goto fail_cmd;
}
+ if (atomic_read(&ac->cmd_response)) {
+ pr_err("%s: ASM_SESSION_CMD_MEMORY_MAP cmd failed\n", __func__);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
rc = 0;
+
fail_cmd:
return rc;
}
@@ -2847,6 +2874,8 @@
}
pr_debug("%s: Session[%d]\n", __func__, ac->session);
+ pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
+ mem_unmap.hdr.token = (uint32_t)ac;
q6asm_add_mmaphdr(&mem_unmap.hdr,
sizeof(struct asm_stream_cmd_memory_unmap), TRUE);
mem_unmap.hdr.opcode = ASM_SESSION_CMD_MEMORY_UNMAP;
@@ -2860,14 +2889,21 @@
goto fail_cmd;
}
- rc = wait_event_timeout(this_mmap.cmd_wait,
- (atomic_read(&this_mmap.cmd_state) == 0), 5 * HZ);
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
if (!rc) {
- pr_err("timeout. waited for memory_map\n");
+ pr_err("timeout. waited for memory_unmap\n");
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ if (atomic_read(&ac->cmd_response)) {
+ pr_err("%s: ASM_SESSION_CMD_MEMORY_UNMAP cmd failed\n",
+ __func__);
rc = -EINVAL;
goto fail_cmd;
}
rc = 0;
+
fail_cmd:
return rc;
}
@@ -2956,6 +2992,8 @@
}
mmap_regions = (struct asm_stream_cmd_memory_map_regions *)
mmap_region_cmd;
+ mmap_regions->hdr.token = (uint32_t)ac;
+ pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
q6asm_add_mmaphdr(&mmap_regions->hdr, cmd_size, TRUE);
mmap_regions->hdr.opcode = ASM_SESSION_CMD_MEMORY_MAP_REGIONS;
mmap_regions->mempool_id = 0;
@@ -2981,14 +3019,21 @@
goto fail_cmd;
}
- rc = wait_event_timeout(this_mmap.cmd_wait,
- (atomic_read(&this_mmap.cmd_state) == 0), 5*HZ);
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
if (!rc) {
- pr_err("timeout. waited for memory_map\n");
+ pr_err("timeout. waited for map_regions\n");
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ if (atomic_read(&ac->cmd_response)) {
+ pr_err("%s: ASM_SESSION_CMD_MEMORY_MAP_REGIONS cmd failed\n",
+ __func__);
rc = -EINVAL;
goto fail_cmd;
}
rc = 0;
+
fail_cmd:
kfree(mmap_region_cmd);
return rc;
@@ -3024,6 +3069,8 @@
}
unmap_regions = (struct asm_stream_cmd_memory_unmap_regions *)
unmap_region_cmd;
+ unmap_regions->hdr.token = (uint32_t)ac;
+ pr_debug("%s: audio_client addr %x\n", __func__, (uint32_t)ac);
q6asm_add_mmaphdr(&unmap_regions->hdr, cmd_size, TRUE);
unmap_regions->hdr.opcode = ASM_SESSION_CMD_MEMORY_UNMAP_REGIONS;
unmap_regions->nregions = bufcnt & 0x00ff;
@@ -3045,10 +3092,17 @@
goto fail_cmd;
}
- rc = wait_event_timeout(this_mmap.cmd_wait,
- (atomic_read(&this_mmap.cmd_state) == 0), 5*HZ);
+ 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("timeout. waited for unmap_regions\n");
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ if (atomic_read(&ac->cmd_response)) {
+ pr_err("%s: ASM_SESSION_CMD_MEMORY_UNMAP_REGIONS cmd failed\n",
+ __func__);
+ rc = -EINVAL;
goto fail_cmd;
}
rc = 0;