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

Commit f2e5dd21 authored by Vangala, Amarnath's avatar Vangala, Amarnath
Browse files

asoc: codecs: fix race condition of core vote and reg access



Auto suspend timer for core vote is triggering before read write complete.
Move the auto suspend of core vote to post read write operation.

Change-Id: Ib0f6b026fe0e7fd3fbe052691db492915e436a78
Signed-off-by: default avatarVangala, Amarnath <avangala@codeaurora.org>
parent 7c1dc5a7
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -1280,6 +1280,7 @@ static int rx_macro_mclk_enable(struct rx_macro_priv *rx_priv,
							   rx_priv->default_clk_id,
							   rx_priv->clk_id,
							   true);
			rx_macro_core_vote(rx_priv, false);
			if (ret < 0) {
				dev_err(rx_priv->dev,
					"%s: rx request clock enable failed\n",
@@ -1334,6 +1335,7 @@ static int rx_macro_mclk_enable(struct rx_macro_priv *rx_priv,
						 rx_priv->default_clk_id,
						 rx_priv->clk_id,
						 false);
			rx_macro_core_vote(rx_priv, false);
			rx_priv->clk_id = rx_priv->default_clk_id;
		}
	}
@@ -1453,11 +1455,11 @@ static int rx_macro_event_handler(struct snd_soc_component *component,
				"%s, failed to enable clk, ret:%d\n",
				__func__, ret);
		} else {
			rx_macro_core_vote(rx_priv, true);
			bolero_clk_rsc_request_clock(rx_priv->dev,
						rx_priv->default_clk_id,
						RX_CORE_CLK, false);
		}
		rx_macro_core_vote(rx_priv, false);
		break;
	case BOLERO_MACRO_EVT_SSR_UP:
		trace_printk("%s, enter SSR up\n", __func__);
@@ -3735,22 +3737,25 @@ static const struct snd_soc_dapm_route rx_audio_map[] = {

static int rx_macro_core_vote(void *handle, bool enable)
{
	int rc = 0;
	struct rx_macro_priv *rx_priv = (struct rx_macro_priv *) handle;

	if (rx_priv == NULL) {
		pr_err("%s: rx priv data is NULL\n", __func__);
		return -EINVAL;
	}

	if (enable) {
		pm_runtime_get_sync(rx_priv->dev);
		if (bolero_check_core_votes(rx_priv->dev))
			rc = 0;
		else
			rc = -ENOTSYNC;
	} else {
		pm_runtime_put_autosuspend(rx_priv->dev);
		pm_runtime_mark_last_busy(rx_priv->dev);
	}

	if (bolero_check_core_votes(rx_priv->dev))
		return 0;
	else
		return -EINVAL;
	return rc;
}

static int rx_swrm_clock(void *handle, bool enable)
+8 −5
Original line number Diff line number Diff line
@@ -2918,22 +2918,25 @@ static int tx_macro_clk_switch(struct snd_soc_component *component, int clk_src)

static int tx_macro_core_vote(void *handle, bool enable)
{
	int rc = 0;
	struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle;

	if (tx_priv == NULL) {
		pr_err("%s: tx priv data is NULL\n", __func__);
		return -EINVAL;
	}

	if (enable) {
		pm_runtime_get_sync(tx_priv->dev);
		if (bolero_check_core_votes(tx_priv->dev))
			rc = 0;
		else
			rc = -ENOTSYNC;
	} else {
		pm_runtime_put_autosuspend(tx_priv->dev);
		pm_runtime_mark_last_busy(tx_priv->dev);
	}

	if (bolero_check_core_votes(tx_priv->dev))
		return 0;
	else
		return -EINVAL;
	return rc;
}

static int tx_macro_swrm_clock(void *handle, bool enable)
+8 −5
Original line number Diff line number Diff line
@@ -725,22 +725,25 @@ static int va_macro_tx_va_mclk_enable(struct va_macro_priv *va_priv,

static int va_macro_core_vote(void *handle, bool enable)
{
	int rc = 0;
	struct va_macro_priv *va_priv = (struct va_macro_priv *) handle;

	if (va_priv == NULL) {
		pr_err("%s: va priv data is NULL\n", __func__);
		return -EINVAL;
	}

	if (enable) {
		pm_runtime_get_sync(va_priv->dev);
		if (bolero_check_core_votes(va_priv->dev))
			rc = 0;
		else
			rc = -ENOTSYNC;
	} else {
		pm_runtime_put_autosuspend(va_priv->dev);
		pm_runtime_mark_last_busy(va_priv->dev);
	}

	if (bolero_check_core_votes(va_priv->dev))
		return 0;
	else
		return -EINVAL;
	return rc;
}

static int va_macro_swrm_clock(void *handle, bool enable)
+8 −5
Original line number Diff line number Diff line
@@ -2833,22 +2833,25 @@ static void wsa_macro_init_reg(struct snd_soc_component *component)

static int wsa_macro_core_vote(void *handle, bool enable)
{
	int rc = 0;
	struct wsa_macro_priv *wsa_priv = (struct wsa_macro_priv *) handle;

	if (wsa_priv == NULL) {
		pr_err("%s: wsa priv data is NULL\n", __func__);
		return -EINVAL;
	}

	if (enable) {
		pm_runtime_get_sync(wsa_priv->dev);
		if (bolero_check_core_votes(wsa_priv->dev))
			rc = 0;
		else
			rc = -ENOTSYNC;
	} else {
		pm_runtime_put_autosuspend(wsa_priv->dev);
		pm_runtime_mark_last_busy(wsa_priv->dev);
	}

	if (bolero_check_core_votes(wsa_priv->dev))
		return 0;
	else
		return -EINVAL;
	return rc;
}

static int wsa_swrm_clock(void *handle, bool enable)
+38 −7
Original line number Diff line number Diff line
@@ -508,7 +508,7 @@ static int swrm_get_ssp_period(struct swr_mstr_ctrl *swrm,
	return ((swrm->bus_clk * 2) / ((row * col) * frame_sync));
}

static int swrm_core_vote_request(struct swr_mstr_ctrl *swrm)
static int swrm_core_vote_request(struct swr_mstr_ctrl *swrm, bool enable)
{
	int ret = 0;

@@ -521,7 +521,7 @@ static int swrm_core_vote_request(struct swr_mstr_ctrl *swrm)
		goto exit;
	}
	if (swrm->core_vote) {
		ret = swrm->core_vote(swrm->handle, true);
		ret = swrm->core_vote(swrm->handle, enable);
		if (ret)
			dev_err_ratelimited(swrm->dev,
				"%s: core vote request failed\n", __func__);
@@ -552,8 +552,10 @@ static int swrm_clk_request(struct swr_mstr_ctrl *swrm, bool enable)
					dev_err_ratelimited(swrm->dev,
						"%s: core vote request failed\n",
						__func__);
					swrm->core_vote(swrm->handle, false);
					goto exit;
				}
				ret = swrm->core_vote(swrm->handle, false);
			}
		}
		swrm->clk_ref_count++;
@@ -589,6 +591,7 @@ static int swrm_ahb_write(struct swr_mstr_ctrl *swrm,
{
	u32 temp = (u32)(*value);
	int ret = 0;
	int vote_ret = 0;

	mutex_lock(&swrm->devlock);
	if (!swrm->dev_up)
@@ -602,13 +605,20 @@ static int swrm_ahb_write(struct swr_mstr_ctrl *swrm,
					    __func__);
			goto err;
		}
	} else if (swrm_core_vote_request(swrm)) {
	} else {
		vote_ret = swrm_core_vote_request(swrm, true);
		if (vote_ret == -ENOTSYNC)
			goto err_vote;
		else if (vote_ret)
			goto err;
	}

	iowrite32(temp, swrm->swrm_dig_base + reg);
	if (is_swr_clk_needed(swrm))
		swrm_clk_request(swrm, FALSE);
err_vote:
	if (!is_swr_clk_needed(swrm))
		swrm_core_vote_request(swrm, false);
err:
	mutex_unlock(&swrm->devlock);
	return ret;
@@ -619,6 +629,7 @@ static int swrm_ahb_read(struct swr_mstr_ctrl *swrm,
{
	u32 temp = 0;
	int ret = 0;
	int vote_ret = 0;

	mutex_lock(&swrm->devlock);
	if (!swrm->dev_up)
@@ -631,7 +642,11 @@ static int swrm_ahb_read(struct swr_mstr_ctrl *swrm,
					    __func__);
			goto err;
		}
	} else if (swrm_core_vote_request(swrm)) {
	} else {
		vote_ret = swrm_core_vote_request(swrm, true);
		if (vote_ret == -ENOTSYNC)
			goto err_vote;
		else if (vote_ret)
			goto err;
	}

@@ -639,6 +654,9 @@ static int swrm_ahb_read(struct swr_mstr_ctrl *swrm,
	*value = temp;
	if (is_swr_clk_needed(swrm))
		swrm_clk_request(swrm, FALSE);
err_vote:
	if (!is_swr_clk_needed(swrm))
		swrm_core_vote_request(swrm, false);
err:
	mutex_unlock(&swrm->devlock);
	return ret;
@@ -2582,6 +2600,7 @@ static int swrm_probe(struct platform_device *pdev)
	struct clk *lpass_core_hw_vote = NULL;
	struct clk *lpass_core_audio = NULL;
	u32 is_wcd937x = 0;
	u32 swrm_hw_ver = 0;

	/* Allocate soundwire master driver structure */
	swrm = devm_kzalloc(&pdev->dev, sizeof(struct swr_mstr_ctrl),
@@ -2608,6 +2627,14 @@ static int swrm_probe(struct platform_device *pdev)
		ret = -EINVAL;
		goto err_pdata_fail;
	}
	ret = of_property_read_u32(pdev->dev.of_node,
				"qcom,swr-master-version",
				&swrm->version);
	if (ret) {
		dev_dbg(&pdev->dev, "%s: swrm version not defined, use default\n",
			 __func__);
		swrm->version = SWRM_VERSION_1_6;
	}
	ret = of_property_read_u32(pdev->dev.of_node, "qcom,swr_master_id",
				&swrm->master_id);
	if (ret) {
@@ -2877,11 +2904,15 @@ static int swrm_probe(struct platform_device *pdev)
		dev_dbg(&pdev->dev, "%s: Audio HW Vote is failed\n", __func__);
	mutex_lock(&swrm->mlock);
	swrm_clk_request(swrm, true);
	swrm->version = swr_master_read(swrm, SWRM_COMP_HW_VERSION);
	swrm->rd_fifo_depth = ((swr_master_read(swrm, SWRM_COMP_PARAMS)
				& SWRM_COMP_PARAMS_RD_FIFO_DEPTH) >> 15);
	swrm->wr_fifo_depth = ((swr_master_read(swrm, SWRM_COMP_PARAMS)
				& SWRM_COMP_PARAMS_WR_FIFO_DEPTH) >> 10);
	swrm_hw_ver = swr_master_read(swrm, SWRM_COMP_HW_VERSION);
	if (swrm->version != swrm_hw_ver)
		dev_info(&pdev->dev,
			 "%s: version specified in dtsi: 0x%x not match with HW read version 0x%x\n",
			 __func__, swrm->version, swrm_hw_ver);
	ret = swrm_master_init(swrm);
	if (ret < 0) {
		dev_err(&pdev->dev,