linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] ASoC: cs42l42: Fixes to power-down
@ 2021-10-26 12:57 Richard Fitzgerald
  2021-10-26 12:57 ` [PATCH 1/2] ASoC: cs42l42: Reset and power-down on remove() and failed probe() Richard Fitzgerald
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Richard Fitzgerald @ 2021-10-26 12:57 UTC (permalink / raw)
  To: broonie; +Cc: alsa-devel, linux-kernel, patches, Richard Fitzgerald

Driver probe and remove were inconsistent in what they did to power-down
and neither did all steps. In addition to that, neither function
prevented the interrupt handler from running during and after power-down.

Richard Fitzgerald (2):
  ASoC: cs42l42: Reset and power-down on remove() and failed probe()
  ASoC: cs42l42: free_irq() before powering-down on probe() fail

 sound/soc/codecs/cs42l42.c | 43 +++++++++++++++++++++++++++++++------------
 1 file changed, 31 insertions(+), 12 deletions(-)

-- 
2.11.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] ASoC: cs42l42: Reset and power-down on remove() and failed probe()
  2021-10-26 12:57 [PATCH 0/2] ASoC: cs42l42: Fixes to power-down Richard Fitzgerald
@ 2021-10-26 12:57 ` Richard Fitzgerald
  2021-10-26 12:57 ` [PATCH 2/2] ASoC: cs42l42: free_irq() before powering-down on probe() fail Richard Fitzgerald
  2021-10-26 19:06 ` [PATCH 0/2] ASoC: cs42l42: Fixes to power-down Mark Brown
  2 siblings, 0 replies; 4+ messages in thread
From: Richard Fitzgerald @ 2021-10-26 12:57 UTC (permalink / raw)
  To: broonie; +Cc: alsa-devel, linux-kernel, patches, Richard Fitzgerald

Driver remove() should assert RESET and disable the supplies.

probe() fail was disabling supplies but it didn't assert reset or
put the codec into a power-down state.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
---
 sound/soc/codecs/cs42l42.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index a8fff274ec63..dc12842ee6e1 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -2067,7 +2067,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client,
 		"reset", GPIOD_OUT_LOW);
 	if (IS_ERR(cs42l42->reset_gpio)) {
 		ret = PTR_ERR(cs42l42->reset_gpio);
-		goto err_disable;
+		goto err_disable_noreset;
 	}
 
 	if (cs42l42->reset_gpio) {
@@ -2111,7 +2111,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client,
 	ret = regmap_read(cs42l42->regmap, CS42L42_REVID, &reg);
 	if (ret < 0) {
 		dev_err(&i2c_client->dev, "Get Revision ID failed\n");
-		goto err_disable;
+		goto err_shutdown;
 	}
 
 	dev_info(&i2c_client->dev,
@@ -2136,7 +2136,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client,
 
 	ret = cs42l42_handle_device_data(&i2c_client->dev, cs42l42);
 	if (ret != 0)
-		goto err_disable;
+		goto err_shutdown;
 
 	/* Setup headset detection */
 	cs42l42_setup_hs_type_detect(cs42l42);
@@ -2148,10 +2148,18 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client,
 	ret = devm_snd_soc_register_component(&i2c_client->dev,
 			&soc_component_dev_cs42l42, &cs42l42_dai, 1);
 	if (ret < 0)
-		goto err_disable;
+		goto err_shutdown;
+
 	return 0;
 
+err_shutdown:
+	regmap_write(cs42l42->regmap, CS42L42_CODEC_INT_MASK, 0xff);
+	regmap_write(cs42l42->regmap, CS42L42_TSRS_PLUG_INT_MASK, 0xff);
+	regmap_write(cs42l42->regmap, CS42L42_PWR_CTL1, 0xff);
+
 err_disable:
+	gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
+err_disable_noreset:
 	regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies),
 				cs42l42->supplies);
 	return ret;
@@ -2164,6 +2172,14 @@ static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
 	if (i2c_client->irq)
 		devm_free_irq(&i2c_client->dev, i2c_client->irq, cs42l42);
 
+	/*
+	 * The driver might not have control of reset and power supplies,
+	 * so ensure that the chip internals are powered down.
+	 */
+	regmap_write(cs42l42->regmap, CS42L42_CODEC_INT_MASK, 0xff);
+	regmap_write(cs42l42->regmap, CS42L42_TSRS_PLUG_INT_MASK, 0xff);
+	regmap_write(cs42l42->regmap, CS42L42_PWR_CTL1, 0xff);
+
 	gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
 	regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies);
 
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] ASoC: cs42l42: free_irq() before powering-down on probe() fail
  2021-10-26 12:57 [PATCH 0/2] ASoC: cs42l42: Fixes to power-down Richard Fitzgerald
  2021-10-26 12:57 ` [PATCH 1/2] ASoC: cs42l42: Reset and power-down on remove() and failed probe() Richard Fitzgerald
@ 2021-10-26 12:57 ` Richard Fitzgerald
  2021-10-26 19:06 ` [PATCH 0/2] ASoC: cs42l42: Fixes to power-down Mark Brown
  2 siblings, 0 replies; 4+ messages in thread
From: Richard Fitzgerald @ 2021-10-26 12:57 UTC (permalink / raw)
  To: broonie; +Cc: alsa-devel, linux-kernel, patches, Richard Fitzgerald

Relying on devm to free the irq handler on probe failure leaves a
small window of opportunity for an interrupt to become pending and
then the handler to run after the chip has been reset and powered
off.

For safety cs42l42_probe() should free the irq in the error path.
As the irq is now disabled by the driver in probe() and remove()
there is no point allocating it as a devres-managed item, so
convert to plain non-devres.

Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
---
 sound/soc/codecs/cs42l42.c | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index dc12842ee6e1..1029f6b3eb48 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -2078,17 +2078,16 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client,
 
 	/* Request IRQ if one was specified */
 	if (i2c_client->irq) {
-		ret = devm_request_threaded_irq(&i2c_client->dev,
-						i2c_client->irq,
-						NULL, cs42l42_irq_thread,
-						IRQF_ONESHOT | IRQF_TRIGGER_LOW,
-						"cs42l42", cs42l42);
+		ret = request_threaded_irq(i2c_client->irq,
+					   NULL, cs42l42_irq_thread,
+					   IRQF_ONESHOT | IRQF_TRIGGER_LOW,
+					   "cs42l42", cs42l42);
 		if (ret == -EPROBE_DEFER) {
-			goto err_disable;
+			goto err_disable_noirq;
 		} else if (ret != 0) {
 			dev_err(&i2c_client->dev,
 				"Failed to request IRQ: %d\n", ret);
-			goto err_disable;
+			goto err_disable_noirq;
 		}
 	}
 
@@ -2158,6 +2157,10 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client,
 	regmap_write(cs42l42->regmap, CS42L42_PWR_CTL1, 0xff);
 
 err_disable:
+	if (i2c_client->irq)
+		free_irq(i2c_client->irq, cs42l42);
+
+err_disable_noirq:
 	gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
 err_disable_noreset:
 	regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies),
@@ -2170,7 +2173,7 @@ static int cs42l42_i2c_remove(struct i2c_client *i2c_client)
 	struct cs42l42_private *cs42l42 = i2c_get_clientdata(i2c_client);
 
 	if (i2c_client->irq)
-		devm_free_irq(&i2c_client->dev, i2c_client->irq, cs42l42);
+		free_irq(i2c_client->irq, cs42l42);
 
 	/*
 	 * The driver might not have control of reset and power supplies,
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] ASoC: cs42l42: Fixes to power-down
  2021-10-26 12:57 [PATCH 0/2] ASoC: cs42l42: Fixes to power-down Richard Fitzgerald
  2021-10-26 12:57 ` [PATCH 1/2] ASoC: cs42l42: Reset and power-down on remove() and failed probe() Richard Fitzgerald
  2021-10-26 12:57 ` [PATCH 2/2] ASoC: cs42l42: free_irq() before powering-down on probe() fail Richard Fitzgerald
@ 2021-10-26 19:06 ` Mark Brown
  2 siblings, 0 replies; 4+ messages in thread
From: Mark Brown @ 2021-10-26 19:06 UTC (permalink / raw)
  To: Richard Fitzgerald; +Cc: alsa-devel, linux-kernel, patches

On Tue, 26 Oct 2021 13:57:20 +0100, Richard Fitzgerald wrote:
> Driver probe and remove were inconsistent in what they did to power-down
> and neither did all steps. In addition to that, neither function
> prevented the interrupt handler from running during and after power-down.
> 
> Richard Fitzgerald (2):
>   ASoC: cs42l42: Reset and power-down on remove() and failed probe()
>   ASoC: cs42l42: free_irq() before powering-down on probe() fail
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/2] ASoC: cs42l42: Reset and power-down on remove() and failed probe()
      commit: 6cb725b8a5cc7b9106d5d6dd5d2ca78c76913775
[2/2] ASoC: cs42l42: free_irq() before powering-down on probe() fail
      commit: a10148a8cf561d728c0f57994330b2da1df35577

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

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-10-26 19:07 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-26 12:57 [PATCH 0/2] ASoC: cs42l42: Fixes to power-down Richard Fitzgerald
2021-10-26 12:57 ` [PATCH 1/2] ASoC: cs42l42: Reset and power-down on remove() and failed probe() Richard Fitzgerald
2021-10-26 12:57 ` [PATCH 2/2] ASoC: cs42l42: free_irq() before powering-down on probe() fail Richard Fitzgerald
2021-10-26 19:06 ` [PATCH 0/2] ASoC: cs42l42: Fixes to power-down Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).