Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 97f90ea9 authored by Soumya Managoli's avatar Soumya Managoli Committed by Gerrit - the friendly Code Review server
Browse files

ASoC: dsp: Synchronise adm and rtac commands



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.

Change-Id: Id89d98217dc5cad3703e5d545ddee21cb145c874
Signed-off-by: default avatarSoumya Managoli <smanag@codeaurora.org>
parent 227a982a
Loading
Loading
Loading
Loading
+75 −32
Original line number Diff line number Diff line
@@ -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;
@@ -869,6 +870,58 @@ int adm_set_custom_chmix_cfg(int port_id, int copp_idx,
}
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,7 +1630,14 @@ 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))
						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
@@ -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();
+4 −26
Original line number Diff line number Diff line
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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__ */