| From 7b62e8b789f8163f882dbf5ba7d5a4fe905cc926 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 23 Oct 2019 14:46:49 +0100 |
| Subject: ASoC: kirkwood: fix device remove ordering |
| |
| From: Russell King <rmk+kernel@armlinux.org.uk> |
| |
| [ Upstream commit dc39596a906d5b604f4e64597b6e904fc14625e8 ] |
| |
| The devm conversion of kirkwood was incorrect; on removal, devm takes |
| effect after the "remove" function has returned. So, the effect of |
| the conversion was to change the order during remove from: |
| |
| - snd_soc_unregister_component() (unpublishes interfaces) |
| - clk_disable_unprepare() |
| - cleanup resources |
| |
| After the conversion, this became: |
| |
| - clk_disable_unprepare() - while the device may still be active |
| - snd_soc_unregister_component() |
| - cleanup resources |
| |
| Hence, it introduces a bug, where the internal clock for the device |
| may be shut down before the device itself has been shut down. It is |
| known that Marvell SoCs, including Dove, locks up if registers for a |
| peripheral that has its clocks disabled are accessed. |
| |
| Fixes: f98fc0f8154e ("ASoC: kirkwood: replace platform to component") |
| Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> |
| Link: https://lore.kernel.org/r/E1iNGyP-0004oN-BA@rmk-PC.armlinux.org.uk |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| sound/soc/kirkwood/kirkwood-i2s.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c |
| index c323ae314b554..eb38cdb37f0ea 100644 |
| --- a/sound/soc/kirkwood/kirkwood-i2s.c |
| +++ b/sound/soc/kirkwood/kirkwood-i2s.c |
| @@ -591,7 +591,7 @@ static int kirkwood_i2s_dev_probe(struct platform_device *pdev) |
| priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128; |
| } |
| |
| - err = devm_snd_soc_register_component(&pdev->dev, &kirkwood_soc_component, |
| + err = snd_soc_register_component(&pdev->dev, &kirkwood_soc_component, |
| soc_dai, 2); |
| if (err) { |
| dev_err(&pdev->dev, "snd_soc_register_component failed\n"); |
| @@ -614,6 +614,7 @@ static int kirkwood_i2s_dev_remove(struct platform_device *pdev) |
| { |
| struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev); |
| |
| + snd_soc_unregister_component(&pdev->dev); |
| if (!IS_ERR(priv->extclk)) |
| clk_disable_unprepare(priv->extclk); |
| clk_disable_unprepare(priv->clk); |
| -- |
| 2.20.1 |
| |