| From db357034f7e0cf23f233f414a8508312dfe8fbbe Mon Sep 17 00:00:00 2001 |
| From: Johan Hovold <johan@kernel.org> |
| Date: Fri, 10 Apr 2026 17:49:06 +0200 |
| Subject: spi: fix resource leaks on device setup failure |
| |
| From: Johan Hovold <johan@kernel.org> |
| |
| commit db357034f7e0cf23f233f414a8508312dfe8fbbe upstream. |
| |
| Make sure to call controller cleanup() if spi_setup() fails while |
| registering a device to avoid leaking any resources allocated by |
| setup(). |
| |
| Fixes: c7299fea6769 ("spi: Fix spi device unregister flow") |
| Cc: stable@vger.kernel.org # 5.13 |
| Cc: Saravana Kannan <saravanak@kernel.org> |
| Signed-off-by: Johan Hovold <johan@kernel.org> |
| Link: https://patch.msgid.link/20260410154907.129248-2-johan@kernel.org |
| Signed-off-by: Mark Brown <broonie@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/spi/spi.c | 61 ++++++++++++++++++++++++++++++++---------------------- |
| 1 file changed, 37 insertions(+), 24 deletions(-) |
| |
| --- a/drivers/spi/spi.c |
| +++ b/drivers/spi/spi.c |
| @@ -43,6 +43,8 @@ EXPORT_TRACEPOINT_SYMBOL(spi_transfer_st |
| |
| #include "internals.h" |
| |
| +static int __spi_setup(struct spi_device *spi, bool initial_setup); |
| + |
| static DEFINE_IDR(spi_controller_idr); |
| |
| static void spidev_release(struct device *dev) |
| @@ -729,7 +731,7 @@ static int __spi_add_device(struct spi_d |
| * normally rely on the device being setup. Devices |
| * using SPI_CS_HIGH can't coexist well otherwise... |
| */ |
| - status = spi_setup(spi); |
| + status = __spi_setup(spi, true); |
| if (status < 0) { |
| dev_err(dev, "can't setup %s, status %d\n", |
| dev_name(&spi->dev), status); |
| @@ -3993,27 +3995,7 @@ static int spi_set_cs_timing(struct spi_ |
| return status; |
| } |
| |
| -/** |
| - * spi_setup - setup SPI mode and clock rate |
| - * @spi: the device whose settings are being modified |
| - * Context: can sleep, and no requests are queued to the device |
| - * |
| - * SPI protocol drivers may need to update the transfer mode if the |
| - * device doesn't work with its default. They may likewise need |
| - * to update clock rates or word sizes from initial values. This function |
| - * changes those settings, and must be called from a context that can sleep. |
| - * Except for SPI_CS_HIGH, which takes effect immediately, the changes take |
| - * effect the next time the device is selected and data is transferred to |
| - * or from it. When this function returns, the SPI device is deselected. |
| - * |
| - * Note that this call will fail if the protocol driver specifies an option |
| - * that the underlying controller or its driver does not support. For |
| - * example, not all hardware supports wire transfers using nine bit words, |
| - * LSB-first wire encoding, or active-high chipselects. |
| - * |
| - * Return: zero on success, else a negative error code. |
| - */ |
| -int spi_setup(struct spi_device *spi) |
| +static int __spi_setup(struct spi_device *spi, bool initial_setup) |
| { |
| unsigned bad_bits, ugly_bits; |
| int status; |
| @@ -4098,7 +4080,7 @@ int spi_setup(struct spi_device *spi) |
| status = spi_set_cs_timing(spi); |
| if (status) { |
| mutex_unlock(&spi->controller->io_mutex); |
| - return status; |
| + goto err_cleanup; |
| } |
| |
| if (spi->controller->auto_runtime_pm && spi->controller->set_cs) { |
| @@ -4107,7 +4089,7 @@ int spi_setup(struct spi_device *spi) |
| mutex_unlock(&spi->controller->io_mutex); |
| dev_err(&spi->controller->dev, "Failed to power device: %d\n", |
| status); |
| - return status; |
| + goto err_cleanup; |
| } |
| |
| /* |
| @@ -4143,6 +4125,37 @@ int spi_setup(struct spi_device *spi) |
| status); |
| |
| return status; |
| + |
| +err_cleanup: |
| + if (initial_setup) |
| + spi_cleanup(spi); |
| + |
| + return status; |
| +} |
| + |
| +/** |
| + * spi_setup - setup SPI mode and clock rate |
| + * @spi: the device whose settings are being modified |
| + * Context: can sleep, and no requests are queued to the device |
| + * |
| + * SPI protocol drivers may need to update the transfer mode if the |
| + * device doesn't work with its default. They may likewise need |
| + * to update clock rates or word sizes from initial values. This function |
| + * changes those settings, and must be called from a context that can sleep. |
| + * Except for SPI_CS_HIGH, which takes effect immediately, the changes take |
| + * effect the next time the device is selected and data is transferred to |
| + * or from it. When this function returns, the SPI device is deselected. |
| + * |
| + * Note that this call will fail if the protocol driver specifies an option |
| + * that the underlying controller or its driver does not support. For |
| + * example, not all hardware supports wire transfers using nine bit words, |
| + * LSB-first wire encoding, or active-high chipselects. |
| + * |
| + * Return: zero on success, else a negative error code. |
| + */ |
| +int spi_setup(struct spi_device *spi) |
| +{ |
| + return __spi_setup(spi, false); |
| } |
| EXPORT_SYMBOL_GPL(spi_setup); |
| |