Asoc: lpass-cdc: Synchronize lpass-cdc register macro function
lpass_cdc_register_macro can be called simultaneously by different macros as bootup resulting in inconsistent value of num_macros_registered. This will result in one of macro going ahead and registering lpass-cdc component and other macro failing to register which will cause probe of other macro to fail. Protect function with mutex lock so that macros access it sequentially Change-Id: I9d3811eeceb06b6a7e66d79a1b899b2c4283bb52 Signed-off-by: Yuhui Zhao <quic_yuhuzhao@quicinc.com>
This commit is contained in:
@@ -52,6 +52,7 @@ struct lpass_cdc_priv {
|
|||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct snd_soc_component *component;
|
struct snd_soc_component *component;
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
|
struct mutex macro_lock;
|
||||||
struct mutex io_lock;
|
struct mutex io_lock;
|
||||||
struct mutex clk_lock;
|
struct mutex clk_lock;
|
||||||
struct mutex vote_lock;
|
struct mutex vote_lock;
|
||||||
|
@@ -663,6 +663,7 @@ int lpass_cdc_register_macro(struct device *dev, u16 macro_id,
|
|||||||
if (macro_id == VA_MACRO)
|
if (macro_id == VA_MACRO)
|
||||||
priv->macro_params[macro_id].reg_wake_irq =
|
priv->macro_params[macro_id].reg_wake_irq =
|
||||||
ops->reg_wake_irq;
|
ops->reg_wake_irq;
|
||||||
|
mutex_lock(&priv->macro_lock);
|
||||||
priv->num_dais += ops->num_dais;
|
priv->num_dais += ops->num_dais;
|
||||||
priv->num_macros_registered++;
|
priv->num_macros_registered++;
|
||||||
priv->macros_supported[macro_id] = true;
|
priv->macros_supported[macro_id] = true;
|
||||||
@@ -673,6 +674,7 @@ int lpass_cdc_register_macro(struct device *dev, u16 macro_id,
|
|||||||
ret = lpass_cdc_copy_dais_from_macro(priv);
|
ret = lpass_cdc_copy_dais_from_macro(priv);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "%s: copy_dais failed\n", __func__);
|
dev_err(dev, "%s: copy_dais failed\n", __func__);
|
||||||
|
mutex_unlock(&priv->macro_lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
if (priv->macros_supported[TX_MACRO] == false) {
|
if (priv->macros_supported[TX_MACRO] == false) {
|
||||||
@@ -685,9 +687,11 @@ int lpass_cdc_register_macro(struct device *dev, u16 macro_id,
|
|||||||
priv->lpass_cdc_dais, priv->num_dais);
|
priv->lpass_cdc_dais, priv->num_dais);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "%s: register codec failed\n", __func__);
|
dev_err(dev, "%s: register codec failed\n", __func__);
|
||||||
|
mutex_unlock(&priv->macro_lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&priv->macro_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(lpass_cdc_register_macro);
|
EXPORT_SYMBOL(lpass_cdc_register_macro);
|
||||||
@@ -1353,6 +1357,7 @@ static int lpass_cdc_probe(struct platform_device *pdev)
|
|||||||
priv->core_audio_vote_count = 0;
|
priv->core_audio_vote_count = 0;
|
||||||
|
|
||||||
dev_set_drvdata(&pdev->dev, priv);
|
dev_set_drvdata(&pdev->dev, priv);
|
||||||
|
mutex_init(&priv->macro_lock);
|
||||||
mutex_init(&priv->io_lock);
|
mutex_init(&priv->io_lock);
|
||||||
mutex_init(&priv->clk_lock);
|
mutex_init(&priv->clk_lock);
|
||||||
mutex_init(&priv->vote_lock);
|
mutex_init(&priv->vote_lock);
|
||||||
@@ -1393,6 +1398,7 @@ static int lpass_cdc_remove(struct platform_device *pdev)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
of_platform_depopulate(&pdev->dev);
|
of_platform_depopulate(&pdev->dev);
|
||||||
|
mutex_destroy(&priv->macro_lock);
|
||||||
mutex_destroy(&priv->io_lock);
|
mutex_destroy(&priv->io_lock);
|
||||||
mutex_destroy(&priv->clk_lock);
|
mutex_destroy(&priv->clk_lock);
|
||||||
mutex_destroy(&priv->vote_lock);
|
mutex_destroy(&priv->vote_lock);
|
||||||
|
Reference in New Issue
Block a user