From 0565b726e637486acd7f213d575f01e212318db0 Mon Sep 17 00:00:00 2001 From: Bhalchandra Gajare Date: Tue, 30 Aug 2016 14:31:23 -0700 Subject: [PATCH] ASoC: wcd9335: Fix race during codec master clock (mclk) enablement It is possible that codec master clock enablement could race from two different execution contexts, causing the mclk to be not enabled at all. This will result in failure of use cases that expect the clock to be present. Fix this issue by making sure the race condition does not occur during mclk enablement. bug: b/30983442 Change-Id: Ie254b8876524956b816267eaaed205f65641c000 Signed-off-by: Bhalchandra Gajare --- sound/soc/codecs/wcd9335.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 9394ee52cad0..b2d4e08a55cc 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -842,6 +842,9 @@ struct tasha_priv { int rx_8_count; bool clk_mode; bool clk_internal; + + /* Lock to protect mclk enablement */ + struct mutex mclk_lock; }; static int tasha_codec_vote_max_bw(struct snd_soc_codec *codec, @@ -1152,13 +1155,14 @@ static int tasha_cdc_req_mclk_enable(struct tasha_priv *tasha, { int ret = 0; + mutex_lock(&tasha->mclk_lock); if (enable) { tasha_cdc_sido_ccl_enable(tasha, true); ret = clk_prepare_enable(tasha->wcd_ext_clk); if (ret) { dev_err(tasha->dev, "%s: ext clk enable failed\n", __func__); - goto err; + goto unlock_mutex; } /* get BG */ wcd_resmgr_enable_master_bias(tasha->resmgr); @@ -1172,7 +1176,8 @@ static int tasha_cdc_req_mclk_enable(struct tasha_priv *tasha, clk_disable_unprepare(tasha->wcd_ext_clk); tasha_cdc_sido_ccl_enable(tasha, false); } -err: +unlock_mutex: + mutex_unlock(&tasha->mclk_lock); return ret; } @@ -14114,6 +14119,7 @@ static int tasha_probe(struct platform_device *pdev) mutex_init(&tasha->swr_read_lock); mutex_init(&tasha->swr_write_lock); mutex_init(&tasha->swr_clk_lock); + mutex_init(&tasha->mclk_lock); cdc_pwr = devm_kzalloc(&pdev->dev, sizeof(struct wcd9xxx_power_region), GFP_KERNEL); @@ -14199,6 +14205,7 @@ err_clk: err_resmgr: devm_kfree(&pdev->dev, cdc_pwr); err_cdc_pwr: + mutex_destroy(&tasha->mclk_lock); devm_kfree(&pdev->dev, tasha); return ret; } @@ -14213,6 +14220,7 @@ static int tasha_remove(struct platform_device *pdev) clk_put(tasha->wcd_ext_clk); if (tasha->wcd_native_clk) clk_put(tasha->wcd_native_clk); + mutex_destroy(&tasha->mclk_lock); devm_kfree(&pdev->dev, tasha); snd_soc_unregister_codec(&pdev->dev); return 0;