Эх сурвалжийг харах

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 <[email protected]>
Yuhui Zhao 2 жил өмнө
parent
commit
b78dc76483

+ 1 - 0
asoc/codecs/lpass-cdc/internal.h

@@ -52,6 +52,7 @@ struct lpass_cdc_priv {
 	struct device *dev;
 	struct snd_soc_component *component;
 	struct regmap *regmap;
+	struct mutex macro_lock;
 	struct mutex io_lock;
 	struct mutex clk_lock;
 	struct mutex vote_lock;

+ 6 - 0
asoc/codecs/lpass-cdc/lpass-cdc.c

@@ -663,6 +663,7 @@ int lpass_cdc_register_macro(struct device *dev, u16 macro_id,
 	if (macro_id == VA_MACRO)
 		priv->macro_params[macro_id].reg_wake_irq =
 						ops->reg_wake_irq;
+	mutex_lock(&priv->macro_lock);
 	priv->num_dais += ops->num_dais;
 	priv->num_macros_registered++;
 	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);
 		if (ret < 0) {
 			dev_err(dev, "%s: copy_dais failed\n", __func__);
+			mutex_unlock(&priv->macro_lock);
 			return ret;
 		}
 		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);
 		if (ret < 0) {
 			dev_err(dev, "%s: register codec failed\n", __func__);
+			mutex_unlock(&priv->macro_lock);
 			return ret;
 		}
 	}
+	mutex_unlock(&priv->macro_lock);
 	return 0;
 }
 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;
 
 	dev_set_drvdata(&pdev->dev, priv);
+	mutex_init(&priv->macro_lock);
 	mutex_init(&priv->io_lock);
 	mutex_init(&priv->clk_lock);
 	mutex_init(&priv->vote_lock);
@@ -1393,6 +1398,7 @@ static int lpass_cdc_remove(struct platform_device *pdev)
 		return -EINVAL;
 
 	of_platform_depopulate(&pdev->dev);
+	mutex_destroy(&priv->macro_lock);
 	mutex_destroy(&priv->io_lock);
 	mutex_destroy(&priv->clk_lock);
 	mutex_destroy(&priv->vote_lock);