ASoC: nau8824: Fix semaphore unbalance at error paths
authorTakashi Iwai <tiwai@suse.de>
Tue, 23 Aug 2022 08:09:57 +0000 (10:09 +0200)
committerMark Brown <broonie@kernel.org>
Tue, 23 Aug 2022 12:04:43 +0000 (13:04 +0100)
The semaphore of nau8824 wasn't properly unlocked at some error
handling code paths, hence this may result in the unbalance (and
potential lock-up).  Fix them to handle the semaphore up properly.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://lore.kernel.org/r/20220823081000.2965-3-tiwai@suse.de
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/codecs/nau8824.c

index ad54d70f7d8e75d4eda4f527548852d60a132363..10bdfebe92d598a15bee0a69440b657da1d56e59 100644 (file)
@@ -1043,6 +1043,7 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_component *component = dai->component;
        struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
        unsigned int val_len = 0, osr, ctrl_val, bclk_fs, bclk_div;
+       int err = -EINVAL;
 
        nau8824_sema_acquire(nau8824, HZ);
 
@@ -1059,7 +1060,7 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
                osr &= NAU8824_DAC_OVERSAMPLE_MASK;
                if (nau8824_clock_check(nau8824, substream->stream,
                        nau8824->fs, osr))
-                       return -EINVAL;
+                       goto error;
                regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER,
                        NAU8824_CLK_DAC_SRC_MASK,
                        osr_dac_sel[osr].clk_src << NAU8824_CLK_DAC_SRC_SFT);
@@ -1069,7 +1070,7 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
                osr &= NAU8824_ADC_SYNC_DOWN_MASK;
                if (nau8824_clock_check(nau8824, substream->stream,
                        nau8824->fs, osr))
-                       return -EINVAL;
+                       goto error;
                regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER,
                        NAU8824_CLK_ADC_SRC_MASK,
                        osr_adc_sel[osr].clk_src << NAU8824_CLK_ADC_SRC_SFT);
@@ -1090,7 +1091,7 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
                else if (bclk_fs <= 256)
                        bclk_div = 0;
                else
-                       return -EINVAL;
+                       goto error;
                regmap_update_bits(nau8824->regmap,
                        NAU8824_REG_PORT0_I2S_PCM_CTRL_2,
                        NAU8824_I2S_LRC_DIV_MASK | NAU8824_I2S_BLK_DIV_MASK,
@@ -1111,15 +1112,17 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
                val_len |= NAU8824_I2S_DL_32;
                break;
        default:
-               return -EINVAL;
+               goto error;
        }
 
        regmap_update_bits(nau8824->regmap, NAU8824_REG_PORT0_I2S_PCM_CTRL_1,
                NAU8824_I2S_DL_MASK, val_len);
+       err = 0;
 
+ error:
        nau8824_sema_release(nau8824);
 
-       return 0;
+       return err;
 }
 
 static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
@@ -1128,8 +1131,6 @@ static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
        struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
        unsigned int ctrl1_val = 0, ctrl2_val = 0;
 
-       nau8824_sema_acquire(nau8824, HZ);
-
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBM_CFM:
                ctrl2_val |= NAU8824_I2S_MS_MASTER;
@@ -1171,6 +1172,8 @@ static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                return -EINVAL;
        }
 
+       nau8824_sema_acquire(nau8824, HZ);
+
        regmap_update_bits(nau8824->regmap, NAU8824_REG_PORT0_I2S_PCM_CTRL_1,
                NAU8824_I2S_DF_MASK | NAU8824_I2S_BP_MASK |
                NAU8824_I2S_PCMB_EN, ctrl1_val);