ASoC: adau1372: Fix error handling in adau1372_set_power()
Subsystems (3)
v2 cover ASoC: adau1372: Fix error handling in adau1372_set_power()
adau1372_set_power() had two related error handling issues in its enable
path: clk_prepare_enable() was called but its return value discarded, and adau1372_enable_pll() was a void function that silently swallowed lock failures, leaving mclk enabled and adau1372->enabled set to true despite the device being in a broken state.
Patch 1 fixes the unchecked clk_prepare_enable() by making adau1372_set_power() return int and propagating the error.
Patch 2 converts adau1372_enable_pll() to return int and adds a full unwind in adau1372_set_power() if PLL lock fails, reversing the regcache, GPIO power-down, and clock state.
Changes in v2:
- [1/2]: No changes.
- [2/2]: Also unwind regcache and GPIO power-down state on PLL lock failure, as noted by Mark Brown.
Jihed Chaibi (2):
ASoC: adau1372: Fix unchecked clk_prepare_enable() return value
ASoC: adau1372: Fix clock leak on PLL lock failure
sound/soc/codecs/adau1372.c | 34 ++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 10 deletions(-)
--
2.47.3
PATCH v2 1/2 ASoC: adau1372: Fix unchecked clk_prepare_enable() return value
adau1372_set_power() calls clk_prepare_enable() but discards the return value. If the clock enable fails, the driver proceeds to access registers on unpowered hardware, potentially causing silent corruption.
Make adau1372_set_power() return int and propagate the error from clk_prepare_enable(). Update adau1372_set_bias_level() to return the error directly for the STANDBY and OFF cases.
---
Changes in v2:
- No changes.
sound/soc/codecs/adau1372.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
sound/soc/codecs/adau1372.c +10 -7
@@ -782,15 +782,18 @@ static void adau1372_enable_pll(struct adau1372 *adau1372)dev_err (adau1372->dev,"Failed to lock PLL\n" ); } -static void adau1372_set_power (struct adau1372 *adau1372,bool enable) +static int adau1372_set_power (struct adau1372 *adau1372,bool enable) {if (adau1372->enabled == enable) -return ; +return 0 ;if (enable) {unsigned int clk_ctrl =ADAU1372_CLK_CTRL_MCLK_EN ; +int ret; -clk_prepare_enable (adau1372->mclk); + ret =clk_prepare_enable (adau1372->mclk); +if (ret) +return ret;if (adau1372->pd_gpio)gpiod_set_value (adau1372->pd_gpio,0 );
@@ -829,6 +832,8 @@ static void adau1372_set_power(struct adau1372 *adau1372, bool enable) } adau1372->enabled = enable; + +return 0 ; } static int adau1372_set_bias_level(struct snd_soc_component *component,
@@ -842,11 +847,9 @@ static int adau1372_set_bias_level(struct snd_soc_component *component,case SND_SOC_BIAS_PREPARE :break ;case SND_SOC_BIAS_STANDBY : -adau1372_set_power (adau1372, true); -break ; +return adau1372_set_power (adau1372, true);case SND_SOC_BIAS_OFF : -adau1372_set_power (adau1372, false); -break ; +return adau1372_set_power (adau1372, false); }return 0 ;
--
2.47.3
Re: [PATCH v2 1/2] ASoC: adau1372: Fix unchecked clk_prepare_enable() return value
Quoted 10 lines · Jihed Chaibi
adau1372_set_power()callsclk_prepare_enable()but discards the return value. If the clock enable fails, the driver proceeds to access registers on unpowered hardware, potentially causing silent corruption.Make
adau1372_set_power()return int and propagate the error fromclk_prepare_enable(). Updateadau1372_set_bias_level()to return the error directly for the STANDBY and OFF cases.Signed-off-by Jihed Chaibi <[email protected]>---
No Fixes tag?
- Nuno Sá
Quoted 57 lines
Changes in v2:
- No changes.sound/soc/codecs/adau1372.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)sound/soc/codecs/adau1372.c +8
-3@@ -782,15 +782,18 @@ static void adau1372_enable_pll(struct adau1372 *adau1372) dev_err(adau1372->dev, "Failed to lock PLL\n"); } -static void adau1372_set_power (struct adau1372 *adau1372,bool enable) +static int adau1372_set_power (struct adau1372 *adau1372,bool enable) { if (adau1372->enabled == enable) -return ; +return 0 ; if (enable) { unsigned int clk_ctrl = ADAU1372_CLK_CTRL_MCLK_EN; +int ret; -clk_prepare_enable (adau1372->mclk); + ret =clk_prepare_enable (adau1372->mclk); +if (ret) +return ret; if (adau1372->pd_gpio) gpiod_set_value(adau1372->pd_gpio, 0);@@ -829,6 +832,8 @@ static void adau1372_set_power(struct adau1372 *adau1372, bool enable) } adau1372->enabled = enable; + +return 0 ; } static int adau1372_set_bias_level(struct snd_soc_component *component,@@ -842,11 +847,9 @@ static int adau1372_set_bias_level(struct snd_soc_component *component,case
SND_SOC_BIAS_PREPARE:
break;
caseSND_SOC_BIAS_STANDBY:sound/soc/codecs/adau1372.c +1
-2-adau1372_set_power (adau1372, true); -break ; +return adau1372_set_power (adau1372, true);case
SND_SOC_BIAS_OFF:sound/soc/codecs/adau1372.c +1
-2-adau1372_set_power (adau1372, false); -break ; +return adau1372_set_power (adau1372, false);}
return 0;
--
2.47.3
PATCH v2 2/2 ASoC: adau1372: Fix clock leak on PLL lock failure
In reply to Jihed Chaibiadau1372_enable_pll() was a void function that logged a dev_err() on PLL lock timeout but did not propagate the error. As a result, adau1372_set_power() would continue with adau1372->enabled set to true despite the PLL being unlocked, and the mclk left enabled with no corresponding disable on the error path.
Convert adau1372_enable_pll() to return int, using -ETIMEDOUT on lock timeout and propagating regmap errors directly. In adau1372_set_power(), check the return value and unwind in reverse order: restore regcache to cache-only mode, reassert GPIO power-down, and disable the clock before returning the error.
---
Changes in v2:
- Also unwind regcache and GPIO power-down state on PLL lock failure, as noted by Mark Brown.
sound/soc/codecs/adau1372.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
sound/soc/codecs/adau1372.c +14 -3
@@ -762,7 +762,7 @@ static int adau1372_startup(struct snd_pcm_substream *substream, struct snd_soc_return 0 ; } -static void adau1372_enable_pll (struct adau1372 *adau1372) +static int adau1372_enable_pll (struct adau1372 *adau1372) {unsigned int val, timeout =0 ;int ret;
@@ -778,8 +778,12 @@ static void adau1372_enable_pll(struct adau1372 *adau1372) timeout++; }while (!(val &1 ) && timeout <3 ); -if (ret <0 || !(val &1 )) +if (ret <0 || !(val &1 )) {dev_err (adau1372->dev,"Failed to lock PLL\n" ); +return ret <0 ? ret : -ETIMEDOUT ; + } + +return 0 ; }static int adau1372_set_power (struct adau1372 *adau1372,bool enable)
@@ -807,7 +811,14 @@ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)* accessed. */ if (adau1372->use_pll) { -adau1372_enable_pll (adau1372); + ret =adau1372_enable_pll (adau1372); +if (ret) { +regcache_cache_only (adau1372->regmap, true); +if (adau1372->pd_gpio) +gpiod_set_value (adau1372->pd_gpio,1 ); +clk_disable_unprepare (adau1372->mclk); +return ret; + } clk_ctrl |=ADAU1372_CLK_CTRL_CLKSRC ; }
--
2.47.3
Re: [PATCH v2 2/2] ASoC: adau1372: Fix clock leak on PLL lock failure
Quoted 6 lines · Jihed Chaibi
adau1372_enable_pll()was a void function that logged adev_err()on PLL lock timeout but did not propagate the error. As a result,adau1372_set_power()would continue withadau1372->enabledset to true despite the PLL being unlocked, and the mclk left enabled with no corresponding disable on the error path.
Quoted 8 lines
Convert
adau1372_enable_pll()to return int, using-ETIMEDOUTon lock timeout and propagating regmap errors directly. Inadau1372_set_power(), check the return value and unwind in reverse order: restore regcache to cache-only mode, reassert GPIO power-down, and disable the clock before returning the error.Signed-off-by Jihed Chaibi <[email protected]>---
Also deserves a Fixes tag IMO.
Quoted 53 lines
Changes in v2:
- Also unwind regcache and GPIO power-down state on PLL lock failure, as noted by Mark Brown.sound/soc/codecs/adau1372.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)sound/soc/codecs/adau1372.c +0
-0@@ -762,7 +762,7 @@ static int adau1372_startup(struct snd_pcm_substream *substream, struct
snd_soc_
return 0;
}sound/soc/codecs/adau1372.c +1
-1-static void adau1372_enable_pll (struct adau1372 *adau1372) +static int adau1372_enable_pll (struct adau1372 *adau1372){
unsigned int val, timeout = 0;
int ret;sound/soc/codecs/adau1372.c +13
-3@@ -778,8 +778,12 @@ static void adau1372_enable_pll(struct adau1372 *adau1372) timeout++; } while (!(val & 1) && timeout < 3); -if (ret <0 || !(val &1 )) +if (ret <0 || !(val &1 )) { dev_err(adau1372->dev, "Failed to lock PLL\n"); +return ret <0 ? ret : -ETIMEDOUT ; + } + +return 0 ; } static int adau1372_set_power(struct adau1372 *adau1372, bool enable)@@ -807,7 +811,14 @@ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)* accessed. */ if (adau1372->use_pll) { -adau1372_enable_pll (adau1372); + ret =adau1372_enable_pll (adau1372); +if (ret) { +regcache_cache_only (adau1372->regmap, true); +if (adau1372->pd_gpio) +gpiod_set_value (adau1372->pd_gpio,1 ); +clk_disable_unprepare (adau1372->mclk); +return ret; + } clk_ctrl |= ADAU1372_CLK_CTRL_CLKSRC; } --2.47.3
Quoted 22 lines · Jihed Chaibi
adau1372_set_power()had two related error handling issues in its enable
path:clk_prepare_enable()was called but its return value discarded, andadau1372_enable_pll()was a void function that silently swallowed lock failures, leaving mclk enabled andadau1372->enabledset to true despite the device being in a broken state.Patch 1 fixes the unchecked
clk_prepare_enable()by makingadau1372_set_power()return int and propagating the error.Patch 2 converts
adau1372_enable_pll()to return int and adds a full unwind inadau1372_set_power()if PLL lock fails, reversing the regcache, GPIO power-down, and clock state.Changes in v2:
- [1/2]: No changes.
- [2/2]: Also unwind regcache and GPIO power-down state on PLL lock failure, as noted by Mark Brown.Jihed Chaibi (2):
ASoC: adau1372: Fix uncheckedclk_prepare_enable()return value
ASoC: adau1372: Fix clock leak on PLL lock failure
Quoted 5 lines
sound/soc/codecs/adau1372.c | 34 ++++++++++++++++++++++-----------
1 file changed, 24 insertions(+), 10 deletions(-)--
2.47.3
With proper tags:
Quoted 27 lines · Nuno Sá
Quoted 25 lines · Jihed Chaibi
adau1372_set_power()had two related error handling issues in its enable
path:clk_prepare_enable()was called but its return value discarded, andadau1372_enable_pll()was a void function that silently swallowed lock failures, leaving mclk enabled andadau1372->enabledset to true despite the device being in a broken state.Patch 1 fixes the unchecked
clk_prepare_enable()by makingadau1372_set_power()return int and propagating the error.Patch 2 converts
adau1372_enable_pll()to return int and adds a full unwind inadau1372_set_power()if PLL lock fails, reversing the regcache, GPIO power-down, and clock state.Changes in v2:
- [1/2]: No changes.
- [2/2]: Also unwind regcache and GPIO power-down state on PLL lock failure, as noted by Mark Brown.Jihed Chaibi (2):
ASoC: adau1372: Fix uncheckedclk_prepare_enable()return value
ASoC: adau1372: Fix clock leak on PLL lock failuresound/soc/codecs/adau1372.c | 34 ++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 10 deletions(-)
Quoted 6 lines
Quoted 2 lines
--
2.47.3With proper tags:
Reviewed-by Nuno Sá <[email protected]>
Thanks for the review, Nuno.
Fixes tags for the series:
[v2 1/2] ASoC: adau1372: Fix unchecked clk_prepare_enable() return value
[v2 2/2] ASoC: adau1372: Fix clock leak on PLL lock failure
Mark Brown
maintainerQuoted 9 lines · Jihed Chaibi
ASoC: adau1372: Fix error handling in
adau1372_set_power()
adau1372_set_power()had two related error handling issues in its enable
path:clk_prepare_enable()was called but its return value discarded, andadau1372_enable_pll()was a void function that silently swallowed lock failures, leaving mclk enabled andadau1372->enabledset to true despite the device being in a broken state.[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-7.0
Thanks!
[1/2] ASoC: adau1372: Fix unchecked clk_prepare_enable() return value
https://git.kernel.org/broonie/sound/c/326fe8104a40 [2/2] ASoC: adau1372: Fix clock leak on PLL lock failure https://git.kernel.org/broonie/sound/c/bfe6a264effc
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks,
Mark