ASoC: msm: qdsp6v2: Add a new waitqueue and state for mem map/unmap

All of the commands being sent to the DSP are using cmd_state flag
which can be overwritten when several commands are sent at the same
time. This results in Memory map/unmap command timing out. The change
will separate the memory flag from flags for other commands so that
they do not overwrite each other.

CRs-fixed: 673781
Change-Id: I61e059f402feb2c4e1e3dbed1825990456e78471
Signed-off-by: Damir Didjusto <damird@codeaurora.org>
This commit is contained in:
Damir Didjusto 2014-06-05 14:40:06 -07:00 committed by Banajit Goswami
parent ac06b734d8
commit 89f32db377
2 changed files with 27 additions and 26 deletions

View file

@ -167,6 +167,7 @@ struct audio_client {
/* Relative or absolute TS */
atomic_t time_flag;
atomic_t nowait_cmd_cnt;
atomic_t mem_state;
void *priv;
uint32_t io_mode;
uint64_t time_stamp;
@ -178,6 +179,7 @@ struct audio_client {
struct audio_port_data port[2];
wait_queue_head_t cmd_wait;
wait_queue_head_t time_wait;
wait_queue_head_t mem_wait;
int perf_mode;
int stream_id;
/* audio cache operations fptr*/

View file

@ -561,7 +561,7 @@ int send_asm_custom_topology(struct audio_client *ac)
q6asm_add_hdr_custom_topology(ac, &asm_top.hdr,
APR_PKT_SIZE(APR_HDR_SIZE,
sizeof(asm_top)), TRUE);
atomic_set(&ac->cmd_state, 1);
atomic_set(&ac->mem_state, 1);
asm_top.hdr.opcode = ASM_CMD_ADD_TOPOLOGIES;
asm_top.payload_addr_lsw = lower_32_bits(cal_block->cal_data.paddr);
asm_top.payload_addr_msw = upper_32_bits(cal_block->cal_data.paddr);
@ -581,8 +581,8 @@ int send_asm_custom_topology(struct audio_client *ac)
}
result = wait_event_timeout(ac->cmd_wait,
(atomic_read(&ac->cmd_state) <= 0), 5*HZ);
result = wait_event_timeout(ac->mem_wait,
(atomic_read(&ac->mem_state) <= 0), 5*HZ);
if (!result) {
pr_err("%s: Set topologies failed after timedout payload = 0x%pa\n",
@ -961,6 +961,7 @@ struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv)
init_waitqueue_head(&ac->cmd_wait);
init_waitqueue_head(&ac->time_wait);
init_waitqueue_head(&ac->mem_wait);
atomic_set(&ac->time_flag, 1);
atomic_set(&ac->reset, 0);
INIT_LIST_HEAD(&ac->port[0].mem_map_handle);
@ -973,6 +974,7 @@ struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv)
}
atomic_set(&ac->cmd_state, 0);
atomic_set(&ac->nowait_cmd_cnt, 0);
atomic_set(&ac->mem_state, 0);
rc = send_asm_custom_topology(ac);
if (rc < 0) {
@ -1280,10 +1282,8 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
atomic_set(&ac->unmap_cb_success, 1);
}
if (atomic_read(&ac->cmd_state)) {
atomic_set(&ac->cmd_state, 0);
wake_up(&ac->cmd_wait);
}
if (atomic_cmpxchg(&ac->mem_state, 1, 0))
wake_up(&ac->mem_wait);
pr_debug("%s:Payload = [0x%x] status[0x%x]\n",
__func__, payload[0], payload[1]);
break;
@ -1303,10 +1303,9 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
pr_debug("%s:PL#0[0x%x] dir=%x s_id=%x\n",
__func__, payload[0], dir, sid);
spin_lock_irqsave(&port->dsp_lock, dsp_flags);
if (atomic_read(&ac->cmd_state)) {
if (atomic_cmpxchg(&ac->mem_state, 1, 0)) {
ac->port[dir].tmp_hdl = payload[0];
atomic_set(&ac->cmd_state, 0);
wake_up(&ac->cmd_wait);
wake_up(&ac->mem_wait);
}
spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
break;
@ -1315,10 +1314,8 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
pr_debug("%s:PL#0[0x%x]PL#1 [0x%x]\n",
__func__, payload[0], payload[1]);
spin_lock_irqsave(&port->dsp_lock, dsp_flags);
if (atomic_read(&ac->cmd_state)) {
atomic_set(&ac->cmd_state, 0);
wake_up(&ac->cmd_wait);
}
if (atomic_cmpxchg(&ac->mem_state, 1, 0))
wake_up(&ac->mem_wait);
spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
break;
@ -3420,7 +3417,7 @@ int q6asm_memory_map(struct audio_client *ac, phys_addr_t buf_add, int dir,
mmap_region_cmd;
q6asm_add_mmaphdr(ac, &mmap_regions->hdr, cmd_size,
TRUE, ((ac->session << 8) | dir));
atomic_set(&ac->cmd_state, 1);
atomic_set(&ac->mem_state, 1);
mmap_regions->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS;
mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
mmap_regions->num_regions = bufcnt & 0x00ff;
@ -3447,8 +3444,8 @@ int q6asm_memory_map(struct audio_client *ac, phys_addr_t buf_add, int dir,
goto fail_cmd;
}
rc = wait_event_timeout(ac->cmd_wait,
(atomic_read(&ac->cmd_state) == 0 &&
rc = wait_event_timeout(ac->mem_wait,
(atomic_read(&ac->mem_state) == 0 &&
ac->port[dir].tmp_hdl), 5*HZ);
if (!rc) {
pr_err("timeout. waited for memory_map\n");
@ -3491,7 +3488,7 @@ int q6asm_memory_unmap(struct audio_client *ac, phys_addr_t buf_add, int dir)
q6asm_add_mmaphdr(ac, &mem_unmap.hdr,
sizeof(struct avs_cmd_shared_mem_unmap_regions),
TRUE, ((ac->session << 8) | dir));
atomic_set(&ac->cmd_state, 1);
atomic_set(&ac->mem_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) {
@ -3519,8 +3516,8 @@ int q6asm_memory_unmap(struct audio_client *ac, phys_addr_t buf_add, int dir)
goto fail_cmd;
}
rc = wait_event_timeout(ac->cmd_wait,
(atomic_read(&ac->cmd_state) <= 0), 5 * HZ);
rc = wait_event_timeout(ac->mem_wait,
(atomic_read(&ac->mem_state) <= 0), 5 * HZ);
if (!rc) {
pr_err("%s timeout. waited for memory_unmap of handle 0x%x\n",
__func__, mem_unmap.mem_map_handle);
@ -3608,7 +3605,7 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
mmap_region_cmd;
q6asm_add_mmaphdr(ac, &mmap_regions->hdr, cmd_size, TRUE,
((ac->session << 8) | dir));
atomic_set(&ac->cmd_state, 1);
atomic_set(&ac->mem_state, 1);
pr_debug("mmap_region=0x%p token=0x%x\n",
mmap_regions, ((ac->session << 8) | dir));
@ -3640,8 +3637,8 @@ static int q6asm_memory_map_regions(struct audio_client *ac, int dir,
goto fail_cmd;
}
rc = wait_event_timeout(ac->cmd_wait,
(atomic_read(&ac->cmd_state) <= 0)
rc = wait_event_timeout(ac->mem_wait,
(atomic_read(&ac->mem_state) <= 0)
, 5*HZ);
if (!rc) {
pr_err("timeout. waited for memory_map\n");
@ -3696,7 +3693,7 @@ static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir)
cmd_size = sizeof(struct avs_cmd_shared_mem_unmap_regions);
q6asm_add_mmaphdr(ac, &mem_unmap.hdr, cmd_size,
TRUE, ((ac->session << 8) | dir));
atomic_set(&ac->cmd_state, 1);
atomic_set(&ac->mem_state, 1);
port = &ac->port[dir];
buf_add = (uint32_t)port->buf->phys;
mem_unmap.hdr.opcode = ASM_CMD_SHARED_MEM_UNMAP_REGIONS;
@ -3726,8 +3723,8 @@ static int q6asm_memory_unmap_regions(struct audio_client *ac, int dir)
goto fail_cmd;
}
rc = wait_event_timeout(ac->cmd_wait,
(atomic_read(&ac->cmd_state) <= 0), 5*HZ);
rc = wait_event_timeout(ac->mem_wait,
(atomic_read(&ac->mem_state) <= 0), 5*HZ);
if (!rc) {
pr_err("%s timeout. waited for memory_unmap of handle 0x%x\n",
__func__, mem_unmap.mem_map_handle);
@ -5210,6 +5207,7 @@ static int __init q6asm_init(void)
common_client.port[1].buf = &common_buf[1];
init_waitqueue_head(&common_client.cmd_wait);
init_waitqueue_head(&common_client.time_wait);
init_waitqueue_head(&common_client.mem_wait);
atomic_set(&common_client.time_flag, 1);
INIT_LIST_HEAD(&common_client.port[0].mem_map_handle);
INIT_LIST_HEAD(&common_client.port[1].mem_map_handle);
@ -5220,6 +5218,7 @@ static int __init q6asm_init(void)
}
atomic_set(&common_client.cmd_state, 0);
atomic_set(&common_client.nowait_cmd_cnt, 0);
atomic_set(&common_client.mem_state, 0);
if (q6asm_init_cal_data())
pr_err("%s: could not init cal data!\n", __func__);