diff mbox series

spi: synquacer: Disable clock in probe error path

Message ID 232281df1ab91d8f0f553a62d5f97fc264ace4da.1604874488.git.lukas@wunner.de (mailing list archive)
State Accepted
Commit 8853b2503014aca5c793d2c7f0aabc990b32bdad
Headers show
Series spi: synquacer: Disable clock in probe error path | expand

Commit Message

Lukas Wunner Nov. 8, 2020, 10:41 p.m. UTC
If the calls to platform_get_irq() or devm_request_irq() fail on probe
of the SynQuacer SPI driver, the clock "sspi->clk" is erroneously not
unprepared and disabled.

If the clock rate "master->max_speed_hz" cannot be determined, the same
happens and in addition the spi_master struct is not freed.

Fix it.

Fixes: b0823ee35cf9 ("spi: Add spi driver for Socionext SynQuacer platform")
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: <stable@vger.kernel.org> # v5.3+
Cc: Masahisa Kojima <masahisa.kojima@linaro.org>
---
 drivers/spi/spi-synquacer.c | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

Comments

Andy Shevchenko Nov. 9, 2020, 2:22 p.m. UTC | #1
On Mon, Nov 9, 2020 at 12:52 AM Lukas Wunner <lukas@wunner.de> wrote:
>
> If the calls to platform_get_irq() or devm_request_irq() fail on probe
> of the SynQuacer SPI driver, the clock "sspi->clk" is erroneously not
> unprepared and disabled.
>
> If the clock rate "master->max_speed_hz" cannot be determined, the same
> happens and in addition the spi_master struct is not freed.

Wouldn't be better to switch over devm_add_action_or_reset() in such cases?
Lukas Wunner Nov. 9, 2020, 3:04 p.m. UTC | #2
On Mon, Nov 09, 2020 at 04:22:38PM +0200, Andy Shevchenko wrote:
> On Mon, Nov 9, 2020 at 12:52 AM Lukas Wunner <lukas@wunner.de> wrote:
> > If the calls to platform_get_irq() or devm_request_irq() fail on probe
> > of the SynQuacer SPI driver, the clock "sspi->clk" is erroneously not
> > unprepared and disabled.
> >
> > If the clock rate "master->max_speed_hz" cannot be determined, the same
> > happens and in addition the spi_master struct is not freed.
> 
> Wouldn't be better to switch over devm_add_action_or_reset() in such cases?

I'd rather prefer a devm_clk_prepare_enable().  This is common enough
to merit a function of its own.

As for the spi_master struct being leaked:  I'm about to submit
a series which introduces devm_spi_alloc_master/slave() and uses
that to fix a use-after-free in 9 drivers and an spi_master leak
in 8 drivers.  Patches are on this development branch:

https://github.com/l1k/linux/commits/spi_fixes

I'm too busy with this series to also look into adding a
devm_clk_prepare_enable().  Hopefully someone else can do that.

Thanks,

Lukas
Mark Brown Nov. 12, 2020, 7:39 p.m. UTC | #3
On Sun, 8 Nov 2020 23:41:00 +0100, Lukas Wunner wrote:
> If the calls to platform_get_irq() or devm_request_irq() fail on probe
> of the SynQuacer SPI driver, the clock "sspi->clk" is erroneously not
> unprepared and disabled.
> 
> If the clock rate "master->max_speed_hz" cannot be determined, the same
> happens and in addition the spi_master struct is not freed.
> 
> [...]

Applied to

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

Thanks!

[1/1] spi: synquacer: Disable clock in probe error path
      commit: 8853b2503014aca5c793d2c7f0aabc990b32bdad

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
diff mbox series

Patch

diff --git a/drivers/spi/spi-synquacer.c b/drivers/spi/spi-synquacer.c
index 42e82dbe3d41..8cdca6ab8098 100644
--- a/drivers/spi/spi-synquacer.c
+++ b/drivers/spi/spi-synquacer.c
@@ -657,7 +657,8 @@  static int synquacer_spi_probe(struct platform_device *pdev)
 
 	if (!master->max_speed_hz) {
 		dev_err(&pdev->dev, "missing clock source\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto disable_clk;
 	}
 	master->min_speed_hz = master->max_speed_hz / 254;
 
@@ -670,7 +671,7 @@  static int synquacer_spi_probe(struct platform_device *pdev)
 	rx_irq = platform_get_irq(pdev, 0);
 	if (rx_irq <= 0) {
 		ret = rx_irq;
-		goto put_spi;
+		goto disable_clk;
 	}
 	snprintf(sspi->rx_irq_name, SYNQUACER_HSSPI_IRQ_NAME_MAX, "%s-rx",
 		 dev_name(&pdev->dev));
@@ -678,13 +679,13 @@  static int synquacer_spi_probe(struct platform_device *pdev)
 				0, sspi->rx_irq_name, sspi);
 	if (ret) {
 		dev_err(&pdev->dev, "request rx_irq failed (%d)\n", ret);
-		goto put_spi;
+		goto disable_clk;
 	}
 
 	tx_irq = platform_get_irq(pdev, 1);
 	if (tx_irq <= 0) {
 		ret = tx_irq;
-		goto put_spi;
+		goto disable_clk;
 	}
 	snprintf(sspi->tx_irq_name, SYNQUACER_HSSPI_IRQ_NAME_MAX, "%s-tx",
 		 dev_name(&pdev->dev));
@@ -692,7 +693,7 @@  static int synquacer_spi_probe(struct platform_device *pdev)
 				0, sspi->tx_irq_name, sspi);
 	if (ret) {
 		dev_err(&pdev->dev, "request tx_irq failed (%d)\n", ret);
-		goto put_spi;
+		goto disable_clk;
 	}
 
 	master->dev.of_node = np;
@@ -710,7 +711,7 @@  static int synquacer_spi_probe(struct platform_device *pdev)
 
 	ret = synquacer_spi_enable(master);
 	if (ret)
-		goto fail_enable;
+		goto disable_clk;
 
 	pm_runtime_set_active(sspi->dev);
 	pm_runtime_enable(sspi->dev);
@@ -723,7 +724,7 @@  static int synquacer_spi_probe(struct platform_device *pdev)
 
 disable_pm:
 	pm_runtime_disable(sspi->dev);
-fail_enable:
+disable_clk:
 	clk_disable_unprepare(sspi->clk);
 put_spi:
 	spi_master_put(master);