ASoC: msm: qdsp6: Fixed the issue unmap command is sent incorrectly

When session CLOSE command is sent right before session RUN command
is acknowledged, callback function can mistakenly think that
the next received acknowledgement is for CLOSE command instead of
RUN command. This triggers driver to send memory unmap command to
the Q6 while it is still processing the CLOSE command. Eventually,
this leads to an invalid memory access and causes Q6 crash.

Change-Id: Ib5d560fbcb7e8ced79cc1075a9f6bea3b55a86b6
CRs-Fixed: 377281
Signed-off-by: Jay Wang <jaywang@codeaurora.org>
This commit is contained in:
Jay Wang 2012-07-11 18:53:21 -07:00 committed by Stephen Boyd
parent 0f74ac2734
commit 79a415c76b
2 changed files with 13 additions and 3 deletions

View file

@ -151,6 +151,7 @@ struct audio_client {
atomic_t cmd_state;
atomic_t time_flag;
atomic_t nowait_cmd_cnt;
wait_queue_head_t cmd_wait;
wait_queue_head_t time_wait;

View file

@ -805,6 +805,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
uint32_t token;
unsigned long dsp_flags;
uint32_t *payload;
uint32_t wakeup_flag = 1;
if ((ac == NULL) || (data == NULL)) {
@ -816,7 +817,13 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
ac->session);
return -EINVAL;
}
if (atomic_read(&ac->nowait_cmd_cnt) > 0) {
pr_debug("%s: nowait_cmd_cnt %d\n",
__func__,
atomic_read(&ac->nowait_cmd_cnt));
atomic_dec(&ac->nowait_cmd_cnt);
wakeup_flag = 0;
}
payload = data->payload;
if (data->opcode == RESET_EVENTS) {
@ -862,7 +869,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
case ASM_STREAM_CMD_OPEN_WRITE_COMPRESSED:
case ASM_STREAM_CMD_OPEN_READ_COMPRESSED:
if (atomic_read(&ac->cmd_state)) {
if (atomic_read(&ac->cmd_state) && wakeup_flag) {
atomic_set(&ac->cmd_state, 0);
if (payload[1] == ADSP_EUNSUPPORTED)
atomic_set(&ac->cmd_response, 1);
@ -1618,12 +1625,12 @@ int q6asm_run_nowait(struct audio_client *ac, uint32_t flags,
run.flags = flags;
run.msw_ts = msw_ts;
run.lsw_ts = lsw_ts;
rc = apr_send_pkt(ac->apr, (uint32_t *) &run);
if (rc < 0) {
pr_err("%s:Commmand run failed[%d]", __func__, rc);
return -EINVAL;
}
atomic_inc(&ac->nowait_cmd_cnt);
return 0;
}
@ -3541,11 +3548,13 @@ int q6asm_cmd_nowait(struct audio_client *ac, int cmd)
pr_debug("%s:session[%d]opcode[0x%x] ", __func__,
ac->session,
hdr.opcode);
rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
if (rc < 0) {
pr_err("%s:Commmand 0x%x failed\n", __func__, hdr.opcode);
goto fail_cmd;
}
atomic_inc(&ac->nowait_cmd_cnt);
return 0;
fail_cmd:
return -EINVAL;