diff options
author | Soumya Managoli <smanag@codeaurora.org> | 2020-04-28 09:16:55 +0530 |
---|---|---|
committer | Yung Ti Su <andysu@google.com> | 2021-03-22 08:53:10 +0000 |
commit | a83073669dd609c6c2c8eb82f8c0e48bb6a18517 (patch) | |
tree | c79c778676f873693688ed00653aec1065981228 | |
parent | b72406258ac8a875410299f146347d97a5003204 (diff) | |
download | msm-extra-a83073669dd609c6c2c8eb82f8c0e48bb6a18517.tar.gz |
ASoC: dsp: Synchronise adm and rtac commandsandroid-11.0.0_r0.110
Race condition observed while processing the
set_pp_params command responses sent back to back
by adsp for commands sent from adm and rtac.
Handle this by synchronising the get/set pp_params
command in both the drivers.
QCT CR-2771103
Bug: 181819518
Change-Id: Id89d98217dc5cad3703e5d545ddee21cb145c874
Signed-off-by: Soumya Managoli <smanag@codeaurora.org>
-rw-r--r-- | dsp/q6adm.c | 107 | ||||
-rw-r--r-- | dsp/rtac.c | 30 | ||||
-rw-r--r-- | include/dsp/q6adm-v2.h | 2 |
3 files changed, 81 insertions, 58 deletions
diff --git a/dsp/q6adm.c b/dsp/q6adm.c index 4be8b118..2f8d2ac4 100644 --- a/dsp/q6adm.c +++ b/dsp/q6adm.c @@ -95,6 +95,7 @@ struct adm_ctl { struct param_outband outband_memmap; struct source_tracking_data sourceTrackingData; + struct mutex adm_apr_lock; int set_custom_topology; int ec_ref_rx; int num_ec_ref_rx_chans; @@ -870,6 +871,58 @@ exit: EXPORT_SYMBOL(adm_set_custom_chmix_cfg); /* + * adm_apr_send_pkt : returns 0 on success, negative otherwise. + */ +int adm_apr_send_pkt(void *data, wait_queue_head_t *wait, + int port_idx, int copp_idx) +{ + int ret = 0; + atomic_t *copp_stat = NULL; + wait = &this_adm.copp.wait[port_idx][copp_idx]; + + if (!wait) + return -EINVAL; + + mutex_lock(&this_adm.adm_apr_lock); + pr_debug("%s: port idx %d copp idx %d\n", __func__, + port_idx, copp_idx); + copp_stat = &this_adm.copp.stat[port_idx][copp_idx]; + atomic_set(copp_stat, -1); + + if (atomic_read(&this_adm.copp.cnt[port_idx][copp_idx]) == 0) { + pr_err("%s: port[0x%x] coppid[0x%x] is not active, ERROR\n", + __func__, port_idx, copp_idx); + mutex_unlock(&this_adm.adm_apr_lock); + return -EINVAL; + } + + ret = apr_send_pkt(this_adm.apr, data); + if (ret > 0) { + ret = wait_event_timeout(*wait, + atomic_read(copp_stat) >= 0, + msecs_to_jiffies(TIMEOUT_MS)); + 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)); + } else if (!ret) { + pr_err_ratelimited("%s: request timedout\n", + __func__); + ret = -ETIMEDOUT; + } else { + ret = 0; + } + } else if (ret == 0) { + pr_err("%s: packet not transmitted\n", __func__); + /* apr_send_pkt can return 0 when nothing is transmitted */ + ret = -EINVAL; + } + + mutex_unlock(&this_adm.adm_apr_lock); + return ret; +} + +/* * With pre-packed data, only the opcode differes from V5 and V6. * Use q6common_pack_pp_params to pack the data correctly. */ @@ -880,7 +933,6 @@ int adm_set_pp_params(int port_id, int copp_idx, struct adm_cmd_set_pp_params *adm_set_params = NULL; int size = 0; int port_idx = 0; - atomic_t *copp_stat = NULL; int ret = 0; port_id = afe_convert_virtual_to_portid(port_id); @@ -938,32 +990,9 @@ int adm_set_pp_params(int port_id, int copp_idx, ret = -EINVAL; goto done; } - - copp_stat = &this_adm.copp.stat[port_idx][copp_idx]; - atomic_set(copp_stat, -1); - ret = apr_send_pkt(this_adm.apr, (uint32_t *) adm_set_params); - if (ret < 0) { - pr_err("%s: Set params APR send failed port = 0x%x ret %d\n", - __func__, port_id, ret); - 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: Set 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; + ret = adm_apr_send_pkt((uint32_t *) adm_set_params, + &this_adm.copp.wait[port_idx][copp_idx], + port_idx, copp_idx); done: kfree(adm_set_params); return ret; @@ -1601,8 +1630,15 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) this_adm.sourceTrackingData. apr_cmd_status = payload[1]; else if (rtac_make_adm_callback(payload, - data->payload_size)) - break; + data->payload_size)) { + pr_debug("%s: rtac cmd response\n", + __func__); + } + atomic_set(&this_adm.copp.stat[port_idx] + [copp_idx], payload[1]); + wake_up( + &this_adm.copp.wait[port_idx][copp_idx]); + break; /* * if soft volume is called and already * interrupted break out of the sequence here @@ -1611,8 +1647,8 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) case ADM_CMD_DEVICE_CLOSE_V5: case ADM_CMD_DEVICE_OPEN_V6: case ADM_CMD_DEVICE_OPEN_V8: - pr_debug("%s: Basic callback received, wake up.\n", - __func__); + pr_debug("%s: Basic callback received for 0x%x, wake up.\n", + __func__, payload[0]); atomic_set(&this_adm.copp.stat[port_idx] [copp_idx], payload[1]); wake_up( @@ -1745,8 +1781,13 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) this_adm.sourceTrackingData.apr_cmd_status = payload[0]; else if (rtac_make_adm_callback(payload, - data->payload_size)) + data->payload_size)) { + pr_debug("%s: rtac cmd response\n", __func__); + atomic_set(&this_adm.copp.stat[port_idx][copp_idx], + payload[0]); + wake_up(&this_adm.copp.wait[port_idx][copp_idx]); break; + } idx = ADM_GET_PARAMETER_LENGTH * copp_idx; if (payload[0] == 0 && data->payload_size > 0) { @@ -5504,6 +5545,7 @@ int __init adm_init(void) this_adm.ffecns_port_id = -1; init_waitqueue_head(&this_adm.matrix_map_wait); init_waitqueue_head(&this_adm.adm_wait); + mutex_init(&this_adm.adm_apr_lock); for (i = 0; i < AFE_MAX_PORTS; i++) { for (j = 0; j < MAX_COPPS_PER_PORT; j++) { @@ -5528,6 +5570,7 @@ int __init adm_init(void) void adm_exit(void) { + mutex_destroy(&this_adm.adm_apr_lock); if (this_adm.apr) adm_reset_data(); adm_delete_cal_data(); @@ -728,7 +728,6 @@ bool rtac_make_adm_callback(uint32_t *payload, u32 payload_size) atomic_set(&rtac_common.apr_err_code, payload[1]); atomic_set(&rtac_adm_apr_data.cmd_state, 0); - wake_up(&rtac_adm_apr_data.cmd_wait); return true; } @@ -880,33 +879,12 @@ int send_adm_apr(void *buf, u32 opcode) pr_debug("%s: Sending RTAC command ioctl 0x%x, paddr 0x%pK\n", __func__, opcode, &rtac_cal[ADM_RTAC_CAL].cal_data.paddr); + mutex_unlock(&rtac_adm_apr_mutex); - result = apr_send_pkt(rtac_adm_apr_data.apr_handle, - (uint32_t *)rtac_adm_buffer); - if (result < 0) { - pr_err("%s: Set params failed copp = %d\n", __func__, copp_id); - goto err; - } - /* Wait for the callback */ - result = wait_event_timeout(rtac_adm_apr_data.cmd_wait, - (atomic_read(&rtac_adm_apr_data.cmd_state) == 0), - msecs_to_jiffies(TIMEOUT_MS)); - if (!result) { - pr_err("%s: Set params timed out copp = %d\n", __func__, - copp_id); - goto err; - } - if (atomic_read(&rtac_common.apr_err_code)) { - pr_err("%s: DSP returned error code = [%s], opcode = 0x%x\n", - __func__, adsp_err_get_err_str(atomic_read( - &rtac_common.apr_err_code)), - opcode); - result = adsp_err_get_lnx_err_code( - atomic_read( - &rtac_common.apr_err_code)); - goto err; - } + result = adm_apr_send_pkt((uint32_t *)rtac_adm_buffer, + NULL, port_idx, copp_idx); + mutex_lock(&rtac_adm_apr_mutex); if (opcode == ADM_CMD_GET_PP_PARAMS_V5) { bytes_returned = ((u32 *)rtac_cal[ADM_RTAC_CAL].cal_data. kvaddr)[2] + 3 * sizeof(u32); diff --git a/include/dsp/q6adm-v2.h b/include/dsp/q6adm-v2.h index 644855d0..20b2450b 100644 --- a/include/dsp/q6adm-v2.h +++ b/include/dsp/q6adm-v2.h @@ -229,4 +229,6 @@ void msm_dts_srs_acquire_lock(void); void msm_dts_srs_release_lock(void); void adm_set_native_mode(int mode); int adm_set_ffecns_freeze_event(bool ffecns_freeze_event); +int adm_apr_send_pkt(void *data, wait_queue_head_t *wait, + int port_idx, int copp_idx); #endif /* __Q6_ADM_V2_H__ */ |