ASoC: nau8824: Fix semaphore unbalance at error paths

[ Upstream commit 5628560e90395d3812800a8e44a01c32ffa429ec ]

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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Takashi Iwai 2022-08-23 10:09:57 +02:00 committed by Greg Kroah-Hartman
parent 323f289a90
commit 17a21341d9

View File

@ -1072,6 +1072,7 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_component *component = dai->component; struct snd_soc_component *component = dai->component;
struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component); struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
unsigned int val_len = 0, osr, ctrl_val, bclk_fs, bclk_div; unsigned int val_len = 0, osr, ctrl_val, bclk_fs, bclk_div;
int err = -EINVAL;
nau8824_sema_acquire(nau8824, HZ); nau8824_sema_acquire(nau8824, HZ);
@ -1088,7 +1089,7 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
osr &= NAU8824_DAC_OVERSAMPLE_MASK; osr &= NAU8824_DAC_OVERSAMPLE_MASK;
if (nau8824_clock_check(nau8824, substream->stream, if (nau8824_clock_check(nau8824, substream->stream,
nau8824->fs, osr)) nau8824->fs, osr))
return -EINVAL; goto error;
regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER, regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER,
NAU8824_CLK_DAC_SRC_MASK, NAU8824_CLK_DAC_SRC_MASK,
osr_dac_sel[osr].clk_src << NAU8824_CLK_DAC_SRC_SFT); osr_dac_sel[osr].clk_src << NAU8824_CLK_DAC_SRC_SFT);
@ -1098,7 +1099,7 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
osr &= NAU8824_ADC_SYNC_DOWN_MASK; osr &= NAU8824_ADC_SYNC_DOWN_MASK;
if (nau8824_clock_check(nau8824, substream->stream, if (nau8824_clock_check(nau8824, substream->stream,
nau8824->fs, osr)) nau8824->fs, osr))
return -EINVAL; goto error;
regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER, regmap_update_bits(nau8824->regmap, NAU8824_REG_CLK_DIVIDER,
NAU8824_CLK_ADC_SRC_MASK, NAU8824_CLK_ADC_SRC_MASK,
osr_adc_sel[osr].clk_src << NAU8824_CLK_ADC_SRC_SFT); osr_adc_sel[osr].clk_src << NAU8824_CLK_ADC_SRC_SFT);
@ -1119,7 +1120,7 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
else if (bclk_fs <= 256) else if (bclk_fs <= 256)
bclk_div = 0; bclk_div = 0;
else else
return -EINVAL; goto error;
regmap_update_bits(nau8824->regmap, regmap_update_bits(nau8824->regmap,
NAU8824_REG_PORT0_I2S_PCM_CTRL_2, NAU8824_REG_PORT0_I2S_PCM_CTRL_2,
NAU8824_I2S_LRC_DIV_MASK | NAU8824_I2S_BLK_DIV_MASK, NAU8824_I2S_LRC_DIV_MASK | NAU8824_I2S_BLK_DIV_MASK,
@ -1140,15 +1141,17 @@ static int nau8824_hw_params(struct snd_pcm_substream *substream,
val_len |= NAU8824_I2S_DL_32; val_len |= NAU8824_I2S_DL_32;
break; break;
default: default:
return -EINVAL; goto error;
} }
regmap_update_bits(nau8824->regmap, NAU8824_REG_PORT0_I2S_PCM_CTRL_1, regmap_update_bits(nau8824->regmap, NAU8824_REG_PORT0_I2S_PCM_CTRL_1,
NAU8824_I2S_DL_MASK, val_len); NAU8824_I2S_DL_MASK, val_len);
err = 0;
error:
nau8824_sema_release(nau8824); nau8824_sema_release(nau8824);
return 0; return err;
} }
static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
@ -1157,8 +1160,6 @@ static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component); struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component);
unsigned int ctrl1_val = 0, ctrl2_val = 0; unsigned int ctrl1_val = 0, ctrl2_val = 0;
nau8824_sema_acquire(nau8824, HZ);
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM: case SND_SOC_DAIFMT_CBM_CFM:
ctrl2_val |= NAU8824_I2S_MS_MASTER; ctrl2_val |= NAU8824_I2S_MS_MASTER;
@ -1200,6 +1201,8 @@ static int nau8824_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return -EINVAL; return -EINVAL;
} }
nau8824_sema_acquire(nau8824, HZ);
regmap_update_bits(nau8824->regmap, NAU8824_REG_PORT0_I2S_PCM_CTRL_1, regmap_update_bits(nau8824->regmap, NAU8824_REG_PORT0_I2S_PCM_CTRL_1,
NAU8824_I2S_DF_MASK | NAU8824_I2S_BP_MASK | NAU8824_I2S_DF_MASK | NAU8824_I2S_BP_MASK |
NAU8824_I2S_PCMB_EN, ctrl1_val); NAU8824_I2S_PCMB_EN, ctrl1_val);