ASoC: dsp: Synchronise adm commands
Race condition observed while processing the get/set_pp_params and adm_close command. Synchronise adm open, close and get/set_pp_params by sending the apr cmd pkt using the same lock. Change-Id: I9a1ebcedc91f78f3940846688f8569ec9088e1e7 Signed-off-by: Soumya Managoli <smanag@codeaurora.org>
This commit is contained in:
parent
a8631caadd
commit
a567a8e232
120
dsp/q6adm.c
120
dsp/q6adm.c
@ -909,10 +909,11 @@ EXPORT_SYMBOL(adm_set_custom_chmix_cfg);
|
|||||||
* adm_apr_send_pkt : returns 0 on success, negative otherwise.
|
* adm_apr_send_pkt : returns 0 on success, negative otherwise.
|
||||||
*/
|
*/
|
||||||
int adm_apr_send_pkt(void *data, wait_queue_head_t *wait,
|
int adm_apr_send_pkt(void *data, wait_queue_head_t *wait,
|
||||||
int port_idx, int copp_idx)
|
int port_idx, int copp_idx, int opcode)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
atomic_t *copp_stat = NULL;
|
atomic_t *copp_stat = NULL;
|
||||||
|
int32_t time_out = msecs_to_jiffies(TIMEOUT_MS);
|
||||||
wait = &this_adm.copp.wait[port_idx][copp_idx];
|
wait = &this_adm.copp.wait[port_idx][copp_idx];
|
||||||
|
|
||||||
if (!wait)
|
if (!wait)
|
||||||
@ -924,18 +925,30 @@ int adm_apr_send_pkt(void *data, wait_queue_head_t *wait,
|
|||||||
copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
|
copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
|
||||||
atomic_set(copp_stat, -1);
|
atomic_set(copp_stat, -1);
|
||||||
|
|
||||||
if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]) == 0) {
|
if (opcode != ADM_CMD_DEVICE_OPEN_V8 &&
|
||||||
pr_err("%s: port[0x%x] coppid[0x%x] is not active, ERROR\n",
|
opcode != ADM_CMD_DEVICE_OPEN_V6 &&
|
||||||
__func__, port_idx, copp_idx);
|
opcode != ADM_CMD_DEVICE_OPEN_V5 &&
|
||||||
mutex_unlock(&this_adm.adm_apr_lock);
|
opcode != ADM_CMD_DEVICE_CLOSE_V5) {
|
||||||
return -EINVAL;
|
if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx])
|
||||||
|
== 0) {
|
||||||
|
pr_err("%s: port[0x%x] copp[0x%x] inactive\n",
|
||||||
|
__func__, port_idx, copp_idx);
|
||||||
|
mutex_unlock(&this_adm.adm_apr_lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opcode == ADM_CMD_DEVICE_OPEN_V8 ||
|
||||||
|
opcode == ADM_CMD_DEVICE_OPEN_V6 ||
|
||||||
|
opcode == ADM_CMD_DEVICE_OPEN_V5) {
|
||||||
|
time_out = msecs_to_jiffies(2 * TIMEOUT_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = apr_send_pkt(this_adm.apr, data);
|
ret = apr_send_pkt(this_adm.apr, data);
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
ret = wait_event_timeout(*wait,
|
ret = wait_event_timeout(*wait,
|
||||||
atomic_read(copp_stat) >= 0,
|
atomic_read(copp_stat) >= 0,
|
||||||
msecs_to_jiffies(TIMEOUT_MS));
|
time_out);
|
||||||
if (atomic_read(copp_stat) > 0) {
|
if (atomic_read(copp_stat) > 0) {
|
||||||
pr_err("%s: DSP returned error[%s]\n", __func__,
|
pr_err("%s: DSP returned error[%s]\n", __func__,
|
||||||
adsp_err_get_err_str(atomic_read(copp_stat)));
|
adsp_err_get_err_str(atomic_read(copp_stat)));
|
||||||
@ -1027,7 +1040,7 @@ int adm_set_pp_params(int port_id, int copp_idx,
|
|||||||
}
|
}
|
||||||
ret = adm_apr_send_pkt((uint32_t *) adm_set_params,
|
ret = adm_apr_send_pkt((uint32_t *) adm_set_params,
|
||||||
&this_adm.copp.wait[port_idx][copp_idx],
|
&this_adm.copp.wait[port_idx][copp_idx],
|
||||||
port_idx, copp_idx);
|
port_idx, copp_idx, adm_set_params->apr_hdr.opcode);
|
||||||
done:
|
done:
|
||||||
kfree(adm_set_params);
|
kfree(adm_set_params);
|
||||||
return ret;
|
return ret;
|
||||||
@ -1080,7 +1093,6 @@ int adm_get_pp_params(int port_id, int copp_idx, uint32_t client_id,
|
|||||||
int returned_param_size_in_bytes = 0;
|
int returned_param_size_in_bytes = 0;
|
||||||
int port_idx = 0;
|
int port_idx = 0;
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
atomic_t *copp_stat = NULL;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (param_hdr == NULL) {
|
if (param_hdr == NULL) {
|
||||||
@ -1128,33 +1140,9 @@ int adm_get_pp_params(int port_id, int copp_idx, uint32_t client_id,
|
|||||||
else
|
else
|
||||||
adm_get_params.apr_hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5;
|
adm_get_params.apr_hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5;
|
||||||
|
|
||||||
copp_stat = &this_adm.copp.stat[port_idx][copp_idx];
|
ret = adm_apr_send_pkt((uint32_t *) &adm_get_params,
|
||||||
atomic_set(copp_stat, -1);
|
&this_adm.copp.wait[port_idx][copp_idx],
|
||||||
|
port_idx, copp_idx, adm_get_params.apr_hdr.opcode);
|
||||||
ret = apr_send_pkt(this_adm.apr, (uint32_t *) &adm_get_params);
|
|
||||||
if (ret < 0) {
|
|
||||||
pr_err("%s: Get params APR send failed port = 0x%x ret %d\n",
|
|
||||||
__func__, port_id, ret);
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
|
|
||||||
atomic_read(copp_stat) >= 0,
|
|
||||||
msecs_to_jiffies(TIMEOUT_MS));
|
|
||||||
if (!ret) {
|
|
||||||
pr_err("%s: Get params timed out port = 0x%x\n", __func__,
|
|
||||||
port_id);
|
|
||||||
ret = -ETIMEDOUT;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (atomic_read(copp_stat) > 0) {
|
|
||||||
pr_err("%s: DSP returned error[%s]\n", __func__,
|
|
||||||
adsp_err_get_err_str(atomic_read(copp_stat)));
|
|
||||||
ret = adsp_err_get_lnx_err_code(atomic_read(copp_stat));
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
/* Copy data to caller if sent in band */
|
/* Copy data to caller if sent in band */
|
||||||
if (!returned_param_data) {
|
if (!returned_param_data) {
|
||||||
@ -1182,7 +1170,6 @@ int adm_get_pp_params(int port_id, int copp_idx, uint32_t client_id,
|
|||||||
|
|
||||||
memcpy(returned_param_data, &adm_get_parameters[idx + 1],
|
memcpy(returned_param_data, &adm_get_parameters[idx + 1],
|
||||||
returned_param_size_in_bytes);
|
returned_param_size_in_bytes);
|
||||||
done:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(adm_get_pp_params);
|
EXPORT_SYMBOL(adm_get_pp_params);
|
||||||
@ -3401,8 +3388,9 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
|
|||||||
ep2_payload_size);
|
ep2_payload_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = apr_send_pkt(this_adm.apr,
|
ret = adm_apr_send_pkt((uint32_t *) adm_params,
|
||||||
(uint32_t *)adm_params);
|
&this_adm.copp.wait[port_idx][copp_idx],
|
||||||
|
port_idx, copp_idx, open_v8.hdr.opcode);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pr_err("%s: port_id: 0x%x for[0x%x] failed %d for open_v8\n",
|
pr_err("%s: port_id: 0x%x for[0x%x] failed %d for open_v8\n",
|
||||||
__func__, tmp_port, port_id, ret);
|
__func__, tmp_port, port_id, ret);
|
||||||
@ -3488,11 +3476,13 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = apr_send_pkt(this_adm.apr,
|
ret = adm_apr_send_pkt((uint32_t *) &open_v6,
|
||||||
(uint32_t *)&open_v6);
|
&this_adm.copp.wait[port_idx][copp_idx],
|
||||||
|
port_idx, copp_idx, open_v6.hdr.opcode);
|
||||||
} else {
|
} else {
|
||||||
ret = apr_send_pkt(this_adm.apr,
|
ret = adm_apr_send_pkt((uint32_t *) &open,
|
||||||
(uint32_t *)&open);
|
&this_adm.copp.wait[port_idx][copp_idx],
|
||||||
|
port_idx, copp_idx, open.hdr.opcode);
|
||||||
}
|
}
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pr_err("%s: port_id: 0x%x for[0x%x] failed %d\n",
|
pr_err("%s: port_id: 0x%x for[0x%x] failed %d\n",
|
||||||
@ -3500,26 +3490,6 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for the callback with copp id */
|
|
||||||
ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
|
|
||||||
atomic_read(&this_adm.copp.stat
|
|
||||||
[port_idx][copp_idx]) >= 0,
|
|
||||||
msecs_to_jiffies(2 * TIMEOUT_MS));
|
|
||||||
if (!ret) {
|
|
||||||
pr_err("%s: ADM open timedout for port_id: 0x%x for [0x%x]\n",
|
|
||||||
__func__, tmp_port, port_id);
|
|
||||||
return -EINVAL;
|
|
||||||
} else if (atomic_read(&this_adm.copp.stat
|
|
||||||
[port_idx][copp_idx]) > 0) {
|
|
||||||
pr_err("%s: DSP returned error[%s]\n",
|
|
||||||
__func__, adsp_err_get_err_str(
|
|
||||||
atomic_read(&this_adm.copp.stat
|
|
||||||
[port_idx][copp_idx])));
|
|
||||||
return adsp_err_get_lnx_err_code(
|
|
||||||
atomic_read(&this_adm.copp.stat
|
|
||||||
[port_idx][copp_idx]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);
|
atomic_inc(&this_adm.copp.cnt[port_idx][copp_idx]);
|
||||||
|
|
||||||
@ -4033,8 +4003,9 @@ int adm_close(int port_id, int perf_mode, int copp_idx)
|
|||||||
|
|
||||||
clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
|
clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
|
||||||
(void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
|
(void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
|
||||||
|
ret = adm_apr_send_pkt((uint32_t *) &close,
|
||||||
ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close);
|
&this_adm.copp.wait[port_idx][copp_idx],
|
||||||
|
port_idx, copp_idx, close.opcode);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
pr_err("%s: ADM close failed %d\n", __func__, ret);
|
pr_err("%s: ADM close failed %d\n", __func__, ret);
|
||||||
if (this_adm.tx_port_id == port_id &&
|
if (this_adm.tx_port_id == port_id &&
|
||||||
@ -4098,25 +4069,6 @@ int adm_close(int port_id, int perf_mode, int copp_idx)
|
|||||||
}
|
}
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
|
|
||||||
atomic_read(&this_adm.copp.stat
|
|
||||||
[port_idx][copp_idx]) >= 0,
|
|
||||||
msecs_to_jiffies(TIMEOUT_MS));
|
|
||||||
if (!ret) {
|
|
||||||
pr_err("%s: ADM cmd Route timedout for port 0x%x\n",
|
|
||||||
__func__, port_id);
|
|
||||||
return -EINVAL;
|
|
||||||
} else if (atomic_read(&this_adm.copp.stat
|
|
||||||
[port_idx][copp_idx]) > 0) {
|
|
||||||
pr_err("%s: DSP returned error[%s]\n",
|
|
||||||
__func__, adsp_err_get_err_str(
|
|
||||||
atomic_read(&this_adm.copp.stat
|
|
||||||
[port_idx][copp_idx])));
|
|
||||||
return adsp_err_get_lnx_err_code(
|
|
||||||
atomic_read(&this_adm.copp.stat
|
|
||||||
[port_idx][copp_idx]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) {
|
if (perf_mode != ULTRA_LOW_LATENCY_PCM_MODE) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
@ -882,7 +882,7 @@ int send_adm_apr(void *buf, u32 opcode)
|
|||||||
mutex_unlock(&rtac_adm_apr_mutex);
|
mutex_unlock(&rtac_adm_apr_mutex);
|
||||||
|
|
||||||
result = adm_apr_send_pkt((uint32_t *)rtac_adm_buffer,
|
result = adm_apr_send_pkt((uint32_t *)rtac_adm_buffer,
|
||||||
NULL, port_idx, copp_idx);
|
NULL, port_idx, copp_idx, adm_params.opcode);
|
||||||
|
|
||||||
mutex_lock(&rtac_adm_apr_mutex);
|
mutex_lock(&rtac_adm_apr_mutex);
|
||||||
if (opcode == ADM_CMD_GET_PP_PARAMS_V5) {
|
if (opcode == ADM_CMD_GET_PP_PARAMS_V5) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
#ifndef __Q6_ADM_V2_H__
|
#ifndef __Q6_ADM_V2_H__
|
||||||
#define __Q6_ADM_V2_H__
|
#define __Q6_ADM_V2_H__
|
||||||
@ -230,5 +230,5 @@ void msm_dts_srs_release_lock(void);
|
|||||||
void adm_set_native_mode(int mode);
|
void adm_set_native_mode(int mode);
|
||||||
int adm_set_ffecns_freeze_event(bool ffecns_freeze_event);
|
int adm_set_ffecns_freeze_event(bool ffecns_freeze_event);
|
||||||
int adm_apr_send_pkt(void *data, wait_queue_head_t *wait,
|
int adm_apr_send_pkt(void *data, wait_queue_head_t *wait,
|
||||||
int port_idx, int copp_idx);
|
int port_idx, int copp_idx, int opcode);
|
||||||
#endif /* __Q6_ADM_V2_H__ */
|
#endif /* __Q6_ADM_V2_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user